1 use crate::codegen::ir::{ArgumentExtension, ArgumentPurpose};
2 use crate::config::Config;
3 use anyhow::Result;
4 use arbitrary::{Arbitrary, Unstructured};
5 use cranelift::codegen::ir::immediates::Offset32;
6 use cranelift::codegen::ir::instructions::InstructionFormat;
7 use cranelift::codegen::ir::stackslot::StackSize;
8 use cranelift::codegen::ir::{types::*, FuncRef, LibCall, UserExternalName, UserFuncName};
9 use cranelift::codegen::ir::{
10     AbiParam, Block, ExternalName, Function, JumpTable, Opcode, Signature, StackSlot, Type, Value,
11 };
12 use cranelift::codegen::isa::CallConv;
13 use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
14 use cranelift::prelude::{
15     EntityRef, ExtFuncData, FloatCC, InstBuilder, IntCC, JumpTableData, MemFlags, StackSlotData,
16     StackSlotKind,
17 };
18 use std::collections::HashMap;
19 use std::ops::RangeInclusive;
20 
21 type BlockSignature = Vec<Type>;
22 
23 fn insert_opcode(
24     fgen: &mut FunctionGenerator,
25     builder: &mut FunctionBuilder,
26     opcode: Opcode,
27     args: &'static [Type],
28     rets: &'static [Type],
29 ) -> Result<()> {
30     let mut vals = Vec::with_capacity(args.len());
31     for &arg in args.into_iter() {
32         let var = fgen.get_variable_of_type(arg)?;
33         let val = builder.use_var(var);
34         vals.push(val);
35     }
36 
37     // For pretty much every instruction the control type is the return type
38     // except for Iconcat and Isplit which are *special* and the control type
39     // is the input type.
40     let ctrl_type = if opcode == Opcode::Iconcat || opcode == Opcode::Isplit {
41         args.first()
42     } else {
43         rets.first()
44     }
45     .copied()
46     .unwrap_or(INVALID);
47 
48     // Choose the appropriate instruction format for this opcode
49     let (inst, dfg) = match opcode.format() {
50         InstructionFormat::NullAry => builder.ins().NullAry(opcode, ctrl_type),
51         InstructionFormat::Unary => builder.ins().Unary(opcode, ctrl_type, vals[0]),
52         InstructionFormat::Binary => builder.ins().Binary(opcode, ctrl_type, vals[0], vals[1]),
53         InstructionFormat::Ternary => builder
54             .ins()
55             .Ternary(opcode, ctrl_type, vals[0], vals[1], vals[2]),
56         _ => unimplemented!(),
57     };
58     let results = dfg.inst_results(inst).to_vec();
59 
60     for (val, &ty) in results.into_iter().zip(rets) {
61         let var = fgen.get_variable_of_type(ty)?;
62         builder.def_var(var, val);
63     }
64     Ok(())
65 }
66 
67 fn insert_call(
68     fgen: &mut FunctionGenerator,
69     builder: &mut FunctionBuilder,
70     opcode: Opcode,
71     _args: &'static [Type],
72     _rets: &'static [Type],
73 ) -> Result<()> {
74     assert_eq!(opcode, Opcode::Call, "only call handled at the moment");
75     let (sig, func_ref) = fgen.u.choose(&fgen.resources.func_refs)?.clone();
76 
77     let actuals = fgen.generate_values_for_signature(
78         builder,
79         sig.params.iter().map(|abi_param| abi_param.value_type),
80     )?;
81 
82     builder.ins().call(func_ref, &actuals);
83     Ok(())
84 }
85 
86 fn insert_stack_load(
87     fgen: &mut FunctionGenerator,
88     builder: &mut FunctionBuilder,
89     _opcode: Opcode,
90     _args: &'static [Type],
91     rets: &'static [Type],
92 ) -> Result<()> {
93     let typevar = rets[0];
94     let type_size = typevar.bytes();
95     let (slot, slot_size) = fgen.stack_slot_with_size(type_size)?;
96     let offset = fgen.u.int_in_range(0..=(slot_size - type_size))? as i32;
97 
98     let val = builder.ins().stack_load(typevar, slot, offset);
99     let var = fgen.get_variable_of_type(typevar)?;
100     builder.def_var(var, val);
101 
102     Ok(())
103 }
104 
105 fn insert_stack_store(
106     fgen: &mut FunctionGenerator,
107     builder: &mut FunctionBuilder,
108     _opcode: Opcode,
109     args: &'static [Type],
110     _rets: &'static [Type],
111 ) -> Result<()> {
112     let typevar = args[0];
113     let type_size = typevar.bytes();
114     let (slot, slot_size) = fgen.stack_slot_with_size(type_size)?;
115     let offset = fgen.u.int_in_range(0..=(slot_size - type_size))? as i32;
116 
117     let arg0 = fgen.get_variable_of_type(typevar)?;
118     let arg0 = builder.use_var(arg0);
119 
120     builder.ins().stack_store(arg0, slot, offset);
121     Ok(())
122 }
123 
124 fn insert_cmp(
125     fgen: &mut FunctionGenerator,
126     builder: &mut FunctionBuilder,
127     opcode: Opcode,
128     args: &'static [Type],
129     rets: &'static [Type],
130 ) -> Result<()> {
131     let lhs = fgen.get_variable_of_type(args[0])?;
132     let lhs = builder.use_var(lhs);
133 
134     let rhs = fgen.get_variable_of_type(args[1])?;
135     let rhs = builder.use_var(rhs);
136 
137     let res = if opcode == Opcode::Fcmp {
138         let cc = *fgen.u.choose(FloatCC::all())?;
139         builder.ins().fcmp(cc, lhs, rhs)
140     } else {
141         let cc = *fgen.u.choose(IntCC::all())?;
142         builder.ins().icmp(cc, lhs, rhs)
143     };
144 
145     let var = fgen.get_variable_of_type(rets[0])?;
146     builder.def_var(var, res);
147 
148     Ok(())
149 }
150 
151 fn insert_const(
152     fgen: &mut FunctionGenerator,
153     builder: &mut FunctionBuilder,
154     _opcode: Opcode,
155     _args: &'static [Type],
156     rets: &'static [Type],
157 ) -> Result<()> {
158     let typevar = rets[0];
159     let var = fgen.get_variable_of_type(typevar)?;
160     let val = fgen.generate_const(builder, typevar)?;
161     builder.def_var(var, val);
162     Ok(())
163 }
164 
165 fn insert_load_store(
166     fgen: &mut FunctionGenerator,
167     builder: &mut FunctionBuilder,
168     opcode: Opcode,
169     args: &'static [Type],
170     rets: &'static [Type],
171 ) -> Result<()> {
172     let ctrl_type = *rets.first().or(args.first()).unwrap();
173     let type_size = ctrl_type.bytes();
174     let (address, offset) = fgen.generate_load_store_address(builder, type_size)?;
175 
176     // TODO: More advanced MemFlags
177     let flags = MemFlags::new();
178 
179     // The variable being loaded or stored into
180     let var = fgen.get_variable_of_type(ctrl_type)?;
181 
182     if opcode.can_store() {
183         let val = builder.use_var(var);
184 
185         builder
186             .ins()
187             .Store(opcode, ctrl_type, flags, offset, val, address);
188     } else {
189         let (inst, dfg) = builder
190             .ins()
191             .Load(opcode, ctrl_type, flags, offset, address);
192 
193         let new_val = dfg.first_result(inst);
194         builder.def_var(var, new_val);
195     }
196 
197     Ok(())
198 }
199 
200 type OpcodeInserter = fn(
201     fgen: &mut FunctionGenerator,
202     builder: &mut FunctionBuilder,
203     Opcode,
204     &'static [Type],
205     &'static [Type],
206 ) -> Result<()>;
207 
208 // TODO: Derive this from the `cranelift-meta` generator.
209 const OPCODE_SIGNATURES: &'static [(
210     Opcode,
211     &'static [Type], // Args
212     &'static [Type], // Rets
213     OpcodeInserter,
214 )] = &[
215     (Opcode::Nop, &[], &[], insert_opcode),
216     // Iadd
217     (Opcode::Iadd, &[I8, I8], &[I8], insert_opcode),
218     (Opcode::Iadd, &[I16, I16], &[I16], insert_opcode),
219     (Opcode::Iadd, &[I32, I32], &[I32], insert_opcode),
220     (Opcode::Iadd, &[I64, I64], &[I64], insert_opcode),
221     (Opcode::Iadd, &[I128, I128], &[I128], insert_opcode),
222     // Isub
223     (Opcode::Isub, &[I8, I8], &[I8], insert_opcode),
224     (Opcode::Isub, &[I16, I16], &[I16], insert_opcode),
225     (Opcode::Isub, &[I32, I32], &[I32], insert_opcode),
226     (Opcode::Isub, &[I64, I64], &[I64], insert_opcode),
227     (Opcode::Isub, &[I128, I128], &[I128], insert_opcode),
228     // Imul
229     (Opcode::Imul, &[I8, I8], &[I8], insert_opcode),
230     (Opcode::Imul, &[I16, I16], &[I16], insert_opcode),
231     (Opcode::Imul, &[I32, I32], &[I32], insert_opcode),
232     (Opcode::Imul, &[I64, I64], &[I64], insert_opcode),
233     (Opcode::Imul, &[I128, I128], &[I128], insert_opcode),
234     // Udiv
235     // udiv.i128 not implemented on x64: https://github.com/bytecodealliance/wasmtime/issues/4756
236     (Opcode::Udiv, &[I8, I8], &[I8], insert_opcode),
237     (Opcode::Udiv, &[I16, I16], &[I16], insert_opcode),
238     (Opcode::Udiv, &[I32, I32], &[I32], insert_opcode),
239     (Opcode::Udiv, &[I64, I64], &[I64], insert_opcode),
240     // (Opcode::Udiv, &[I128, I128], &[I128], insert_opcode),
241     // Sdiv
242     // sdiv.i128 not implemented on x64: https://github.com/bytecodealliance/wasmtime/issues/4770
243     (Opcode::Sdiv, &[I8, I8], &[I8], insert_opcode),
244     (Opcode::Sdiv, &[I16, I16], &[I16], insert_opcode),
245     (Opcode::Sdiv, &[I32, I32], &[I32], insert_opcode),
246     (Opcode::Sdiv, &[I64, I64], &[I64], insert_opcode),
247     // (Opcode::Sdiv, &[I128, I128], &[I128], insert_opcode),
248     // Rotr
249     (Opcode::Rotr, &[I8, I8], &[I8], insert_opcode),
250     (Opcode::Rotr, &[I8, I16], &[I8], insert_opcode),
251     (Opcode::Rotr, &[I8, I32], &[I8], insert_opcode),
252     (Opcode::Rotr, &[I8, I64], &[I8], insert_opcode),
253     (Opcode::Rotr, &[I8, I128], &[I8], insert_opcode),
254     (Opcode::Rotr, &[I16, I8], &[I16], insert_opcode),
255     (Opcode::Rotr, &[I16, I16], &[I16], insert_opcode),
256     (Opcode::Rotr, &[I16, I32], &[I16], insert_opcode),
257     (Opcode::Rotr, &[I16, I64], &[I16], insert_opcode),
258     (Opcode::Rotr, &[I16, I128], &[I16], insert_opcode),
259     (Opcode::Rotr, &[I32, I8], &[I32], insert_opcode),
260     (Opcode::Rotr, &[I32, I16], &[I32], insert_opcode),
261     (Opcode::Rotr, &[I32, I32], &[I32], insert_opcode),
262     (Opcode::Rotr, &[I32, I64], &[I32], insert_opcode),
263     (Opcode::Rotr, &[I32, I128], &[I32], insert_opcode),
264     (Opcode::Rotr, &[I64, I8], &[I64], insert_opcode),
265     (Opcode::Rotr, &[I64, I16], &[I64], insert_opcode),
266     (Opcode::Rotr, &[I64, I32], &[I64], insert_opcode),
267     (Opcode::Rotr, &[I64, I64], &[I64], insert_opcode),
268     (Opcode::Rotr, &[I64, I128], &[I64], insert_opcode),
269     (Opcode::Rotr, &[I128, I8], &[I128], insert_opcode),
270     (Opcode::Rotr, &[I128, I16], &[I128], insert_opcode),
271     (Opcode::Rotr, &[I128, I32], &[I128], insert_opcode),
272     (Opcode::Rotr, &[I128, I64], &[I128], insert_opcode),
273     (Opcode::Rotr, &[I128, I128], &[I128], insert_opcode),
274     // Rotl
275     (Opcode::Rotl, &[I8, I8], &[I8], insert_opcode),
276     (Opcode::Rotl, &[I8, I16], &[I8], insert_opcode),
277     (Opcode::Rotl, &[I8, I32], &[I8], insert_opcode),
278     (Opcode::Rotl, &[I8, I64], &[I8], insert_opcode),
279     (Opcode::Rotl, &[I8, I128], &[I8], insert_opcode),
280     (Opcode::Rotl, &[I16, I8], &[I16], insert_opcode),
281     (Opcode::Rotl, &[I16, I16], &[I16], insert_opcode),
282     (Opcode::Rotl, &[I16, I32], &[I16], insert_opcode),
283     (Opcode::Rotl, &[I16, I64], &[I16], insert_opcode),
284     (Opcode::Rotl, &[I16, I128], &[I16], insert_opcode),
285     (Opcode::Rotl, &[I32, I8], &[I32], insert_opcode),
286     (Opcode::Rotl, &[I32, I16], &[I32], insert_opcode),
287     (Opcode::Rotl, &[I32, I32], &[I32], insert_opcode),
288     (Opcode::Rotl, &[I32, I64], &[I32], insert_opcode),
289     (Opcode::Rotl, &[I32, I128], &[I32], insert_opcode),
290     (Opcode::Rotl, &[I64, I8], &[I64], insert_opcode),
291     (Opcode::Rotl, &[I64, I16], &[I64], insert_opcode),
292     (Opcode::Rotl, &[I64, I32], &[I64], insert_opcode),
293     (Opcode::Rotl, &[I64, I64], &[I64], insert_opcode),
294     (Opcode::Rotl, &[I64, I128], &[I64], insert_opcode),
295     (Opcode::Rotl, &[I128, I8], &[I128], insert_opcode),
296     (Opcode::Rotl, &[I128, I16], &[I128], insert_opcode),
297     (Opcode::Rotl, &[I128, I32], &[I128], insert_opcode),
298     (Opcode::Rotl, &[I128, I64], &[I128], insert_opcode),
299     (Opcode::Rotl, &[I128, I128], &[I128], insert_opcode),
300     // Ishl
301     // Some test cases disabled due to: https://github.com/bytecodealliance/wasmtime/issues/4699
302     (Opcode::Ishl, &[I8, I8], &[I8], insert_opcode),
303     (Opcode::Ishl, &[I8, I16], &[I8], insert_opcode),
304     (Opcode::Ishl, &[I8, I32], &[I8], insert_opcode),
305     (Opcode::Ishl, &[I8, I64], &[I8], insert_opcode),
306     // (Opcode::Ishl, &[I8, I128], &[I8], insert_opcode),
307     (Opcode::Ishl, &[I16, I8], &[I16], insert_opcode),
308     (Opcode::Ishl, &[I16, I16], &[I16], insert_opcode),
309     (Opcode::Ishl, &[I16, I32], &[I16], insert_opcode),
310     (Opcode::Ishl, &[I16, I64], &[I16], insert_opcode),
311     // (Opcode::Ishl, &[I16, I128], &[I16], insert_opcode),
312     (Opcode::Ishl, &[I32, I8], &[I32], insert_opcode),
313     (Opcode::Ishl, &[I32, I16], &[I32], insert_opcode),
314     (Opcode::Ishl, &[I32, I32], &[I32], insert_opcode),
315     (Opcode::Ishl, &[I32, I64], &[I32], insert_opcode),
316     (Opcode::Ishl, &[I32, I128], &[I32], insert_opcode),
317     (Opcode::Ishl, &[I64, I8], &[I64], insert_opcode),
318     (Opcode::Ishl, &[I64, I16], &[I64], insert_opcode),
319     (Opcode::Ishl, &[I64, I32], &[I64], insert_opcode),
320     (Opcode::Ishl, &[I64, I64], &[I64], insert_opcode),
321     (Opcode::Ishl, &[I64, I128], &[I64], insert_opcode),
322     (Opcode::Ishl, &[I128, I8], &[I128], insert_opcode),
323     (Opcode::Ishl, &[I128, I16], &[I128], insert_opcode),
324     (Opcode::Ishl, &[I128, I32], &[I128], insert_opcode),
325     (Opcode::Ishl, &[I128, I64], &[I128], insert_opcode),
326     (Opcode::Ishl, &[I128, I128], &[I128], insert_opcode),
327     // Sshr
328     (Opcode::Sshr, &[I8, I8], &[I8], insert_opcode),
329     (Opcode::Sshr, &[I8, I16], &[I8], insert_opcode),
330     (Opcode::Sshr, &[I8, I32], &[I8], insert_opcode),
331     (Opcode::Sshr, &[I8, I64], &[I8], insert_opcode),
332     (Opcode::Sshr, &[I8, I128], &[I8], insert_opcode),
333     (Opcode::Sshr, &[I16, I8], &[I16], insert_opcode),
334     (Opcode::Sshr, &[I16, I16], &[I16], insert_opcode),
335     (Opcode::Sshr, &[I16, I32], &[I16], insert_opcode),
336     (Opcode::Sshr, &[I16, I64], &[I16], insert_opcode),
337     (Opcode::Sshr, &[I16, I128], &[I16], insert_opcode),
338     (Opcode::Sshr, &[I32, I8], &[I32], insert_opcode),
339     (Opcode::Sshr, &[I32, I16], &[I32], insert_opcode),
340     (Opcode::Sshr, &[I32, I32], &[I32], insert_opcode),
341     (Opcode::Sshr, &[I32, I64], &[I32], insert_opcode),
342     (Opcode::Sshr, &[I32, I128], &[I32], insert_opcode),
343     (Opcode::Sshr, &[I64, I8], &[I64], insert_opcode),
344     (Opcode::Sshr, &[I64, I16], &[I64], insert_opcode),
345     (Opcode::Sshr, &[I64, I32], &[I64], insert_opcode),
346     (Opcode::Sshr, &[I64, I64], &[I64], insert_opcode),
347     (Opcode::Sshr, &[I64, I128], &[I64], insert_opcode),
348     (Opcode::Sshr, &[I128, I8], &[I128], insert_opcode),
349     (Opcode::Sshr, &[I128, I16], &[I128], insert_opcode),
350     (Opcode::Sshr, &[I128, I32], &[I128], insert_opcode),
351     (Opcode::Sshr, &[I128, I64], &[I128], insert_opcode),
352     (Opcode::Sshr, &[I128, I128], &[I128], insert_opcode),
353     // Ushr
354     (Opcode::Ushr, &[I8, I8], &[I8], insert_opcode),
355     (Opcode::Ushr, &[I8, I16], &[I8], insert_opcode),
356     (Opcode::Ushr, &[I8, I32], &[I8], insert_opcode),
357     (Opcode::Ushr, &[I8, I64], &[I8], insert_opcode),
358     (Opcode::Ushr, &[I8, I128], &[I8], insert_opcode),
359     (Opcode::Ushr, &[I16, I8], &[I16], insert_opcode),
360     (Opcode::Ushr, &[I16, I16], &[I16], insert_opcode),
361     (Opcode::Ushr, &[I16, I32], &[I16], insert_opcode),
362     (Opcode::Ushr, &[I16, I64], &[I16], insert_opcode),
363     (Opcode::Ushr, &[I16, I128], &[I16], insert_opcode),
364     (Opcode::Ushr, &[I32, I8], &[I32], insert_opcode),
365     (Opcode::Ushr, &[I32, I16], &[I32], insert_opcode),
366     (Opcode::Ushr, &[I32, I32], &[I32], insert_opcode),
367     (Opcode::Ushr, &[I32, I64], &[I32], insert_opcode),
368     (Opcode::Ushr, &[I32, I128], &[I32], insert_opcode),
369     (Opcode::Ushr, &[I64, I8], &[I64], insert_opcode),
370     (Opcode::Ushr, &[I64, I16], &[I64], insert_opcode),
371     (Opcode::Ushr, &[I64, I32], &[I64], insert_opcode),
372     (Opcode::Ushr, &[I64, I64], &[I64], insert_opcode),
373     (Opcode::Ushr, &[I64, I128], &[I64], insert_opcode),
374     (Opcode::Ushr, &[I128, I8], &[I128], insert_opcode),
375     (Opcode::Ushr, &[I128, I16], &[I128], insert_opcode),
376     (Opcode::Ushr, &[I128, I32], &[I128], insert_opcode),
377     (Opcode::Ushr, &[I128, I64], &[I128], insert_opcode),
378     (Opcode::Ushr, &[I128, I128], &[I128], insert_opcode),
379     // Uextend
380     (Opcode::Uextend, &[I8], &[I16], insert_opcode),
381     (Opcode::Uextend, &[I8], &[I32], insert_opcode),
382     (Opcode::Uextend, &[I8], &[I64], insert_opcode),
383     (Opcode::Uextend, &[I8], &[I128], insert_opcode),
384     (Opcode::Uextend, &[I16], &[I32], insert_opcode),
385     (Opcode::Uextend, &[I16], &[I64], insert_opcode),
386     (Opcode::Uextend, &[I16], &[I128], insert_opcode),
387     (Opcode::Uextend, &[I32], &[I64], insert_opcode),
388     (Opcode::Uextend, &[I32], &[I128], insert_opcode),
389     (Opcode::Uextend, &[I64], &[I128], insert_opcode),
390     // Sextend
391     (Opcode::Sextend, &[I8], &[I16], insert_opcode),
392     (Opcode::Sextend, &[I8], &[I32], insert_opcode),
393     (Opcode::Sextend, &[I8], &[I64], insert_opcode),
394     (Opcode::Sextend, &[I8], &[I128], insert_opcode),
395     (Opcode::Sextend, &[I16], &[I32], insert_opcode),
396     (Opcode::Sextend, &[I16], &[I64], insert_opcode),
397     (Opcode::Sextend, &[I16], &[I128], insert_opcode),
398     (Opcode::Sextend, &[I32], &[I64], insert_opcode),
399     (Opcode::Sextend, &[I32], &[I128], insert_opcode),
400     (Opcode::Sextend, &[I64], &[I128], insert_opcode),
401     // Ireduce
402     (Opcode::Ireduce, &[I16], &[I8], insert_opcode),
403     (Opcode::Ireduce, &[I32], &[I8], insert_opcode),
404     (Opcode::Ireduce, &[I32], &[I16], insert_opcode),
405     (Opcode::Ireduce, &[I64], &[I8], insert_opcode),
406     (Opcode::Ireduce, &[I64], &[I16], insert_opcode),
407     (Opcode::Ireduce, &[I64], &[I32], insert_opcode),
408     (Opcode::Ireduce, &[I128], &[I8], insert_opcode),
409     (Opcode::Ireduce, &[I128], &[I16], insert_opcode),
410     (Opcode::Ireduce, &[I128], &[I32], insert_opcode),
411     (Opcode::Ireduce, &[I128], &[I64], insert_opcode),
412     // Isplit
413     (Opcode::Isplit, &[I128], &[I64, I64], insert_opcode),
414     // Iconcat
415     (Opcode::Iconcat, &[I64, I64], &[I128], insert_opcode),
416     // Fadd
417     (Opcode::Fadd, &[F32, F32], &[F32], insert_opcode),
418     (Opcode::Fadd, &[F64, F64], &[F64], insert_opcode),
419     // Fmul
420     (Opcode::Fmul, &[F32, F32], &[F32], insert_opcode),
421     (Opcode::Fmul, &[F64, F64], &[F64], insert_opcode),
422     // Fsub
423     (Opcode::Fsub, &[F32, F32], &[F32], insert_opcode),
424     (Opcode::Fsub, &[F64, F64], &[F64], insert_opcode),
425     // Fdiv
426     (Opcode::Fdiv, &[F32, F32], &[F32], insert_opcode),
427     (Opcode::Fdiv, &[F64, F64], &[F64], insert_opcode),
428     // Fmin
429     (Opcode::Fmin, &[F32, F32], &[F32], insert_opcode),
430     (Opcode::Fmin, &[F64, F64], &[F64], insert_opcode),
431     // Fmax
432     (Opcode::Fmax, &[F32, F32], &[F32], insert_opcode),
433     (Opcode::Fmax, &[F64, F64], &[F64], insert_opcode),
434     // FminPseudo
435     (Opcode::FminPseudo, &[F32, F32], &[F32], insert_opcode),
436     (Opcode::FminPseudo, &[F64, F64], &[F64], insert_opcode),
437     // FmaxPseudo
438     (Opcode::FmaxPseudo, &[F32, F32], &[F32], insert_opcode),
439     (Opcode::FmaxPseudo, &[F64, F64], &[F64], insert_opcode),
440     // Fcopysign
441     (Opcode::Fcopysign, &[F32, F32], &[F32], insert_opcode),
442     (Opcode::Fcopysign, &[F64, F64], &[F64], insert_opcode),
443     // Fma
444     (Opcode::Fma, &[F32, F32, F32], &[F32], insert_opcode),
445     (Opcode::Fma, &[F64, F64, F64], &[F64], insert_opcode),
446     // Fabs
447     (Opcode::Fabs, &[F32], &[F32], insert_opcode),
448     (Opcode::Fabs, &[F64], &[F64], insert_opcode),
449     // Fneg
450     (Opcode::Fneg, &[F32], &[F32], insert_opcode),
451     (Opcode::Fneg, &[F64], &[F64], insert_opcode),
452     // Sqrt
453     (Opcode::Sqrt, &[F32], &[F32], insert_opcode),
454     (Opcode::Sqrt, &[F64], &[F64], insert_opcode),
455     // Ceil
456     (Opcode::Ceil, &[F32], &[F32], insert_opcode),
457     (Opcode::Ceil, &[F64], &[F64], insert_opcode),
458     // Floor
459     (Opcode::Floor, &[F32], &[F32], insert_opcode),
460     (Opcode::Floor, &[F64], &[F64], insert_opcode),
461     // Trunc
462     (Opcode::Trunc, &[F32], &[F32], insert_opcode),
463     (Opcode::Trunc, &[F64], &[F64], insert_opcode),
464     // Nearest
465     (Opcode::Nearest, &[F32], &[F32], insert_opcode),
466     (Opcode::Nearest, &[F64], &[F64], insert_opcode),
467     // Fcmp
468     (Opcode::Fcmp, &[F32, F32], &[B1], insert_cmp),
469     (Opcode::Fcmp, &[F64, F64], &[B1], insert_cmp),
470     // Icmp
471     (Opcode::Icmp, &[I8, I8], &[B1], insert_cmp),
472     (Opcode::Icmp, &[I16, I16], &[B1], insert_cmp),
473     (Opcode::Icmp, &[I32, I32], &[B1], insert_cmp),
474     (Opcode::Icmp, &[I64, I64], &[B1], insert_cmp),
475     (Opcode::Icmp, &[I128, I128], &[B1], insert_cmp),
476     // Stack Access
477     (Opcode::StackStore, &[I8], &[], insert_stack_store),
478     (Opcode::StackStore, &[I16], &[], insert_stack_store),
479     (Opcode::StackStore, &[I32], &[], insert_stack_store),
480     (Opcode::StackStore, &[I64], &[], insert_stack_store),
481     (Opcode::StackStore, &[I128], &[], insert_stack_store),
482     (Opcode::StackLoad, &[], &[I8], insert_stack_load),
483     (Opcode::StackLoad, &[], &[I16], insert_stack_load),
484     (Opcode::StackLoad, &[], &[I32], insert_stack_load),
485     (Opcode::StackLoad, &[], &[I64], insert_stack_load),
486     (Opcode::StackLoad, &[], &[I128], insert_stack_load),
487     // Loads
488     (Opcode::Load, &[], &[I8], insert_load_store),
489     (Opcode::Load, &[], &[I16], insert_load_store),
490     (Opcode::Load, &[], &[I32], insert_load_store),
491     (Opcode::Load, &[], &[I64], insert_load_store),
492     (Opcode::Load, &[], &[I128], insert_load_store),
493     (Opcode::Load, &[], &[F32], insert_load_store),
494     (Opcode::Load, &[], &[F64], insert_load_store),
495     // Special Loads
496     (Opcode::Uload8, &[], &[I16], insert_load_store),
497     (Opcode::Uload8, &[], &[I32], insert_load_store),
498     (Opcode::Uload8, &[], &[I64], insert_load_store),
499     (Opcode::Uload16, &[], &[I32], insert_load_store),
500     (Opcode::Uload16, &[], &[I64], insert_load_store),
501     (Opcode::Uload32, &[], &[I64], insert_load_store),
502     (Opcode::Sload8, &[], &[I16], insert_load_store),
503     (Opcode::Sload8, &[], &[I32], insert_load_store),
504     (Opcode::Sload8, &[], &[I64], insert_load_store),
505     (Opcode::Sload16, &[], &[I32], insert_load_store),
506     (Opcode::Sload16, &[], &[I64], insert_load_store),
507     (Opcode::Sload32, &[], &[I64], insert_load_store),
508     // TODO: Unimplemented in the interpreter
509     // Opcode::Uload8x8
510     // Opcode::Sload8x8
511     // Opcode::Uload16x4
512     // Opcode::Sload16x4
513     // Opcode::Uload32x2
514     // Opcode::Sload32x2
515     // Stores
516     (Opcode::Store, &[I8], &[], insert_load_store),
517     (Opcode::Store, &[I16], &[], insert_load_store),
518     (Opcode::Store, &[I32], &[], insert_load_store),
519     (Opcode::Store, &[I64], &[], insert_load_store),
520     (Opcode::Store, &[I128], &[], insert_load_store),
521     (Opcode::Store, &[F32], &[], insert_load_store),
522     (Opcode::Store, &[F64], &[], insert_load_store),
523     // Special Stores
524     (Opcode::Istore8, &[I16], &[], insert_load_store),
525     (Opcode::Istore8, &[I32], &[], insert_load_store),
526     (Opcode::Istore8, &[I64], &[], insert_load_store),
527     (Opcode::Istore16, &[I32], &[], insert_load_store),
528     (Opcode::Istore16, &[I64], &[], insert_load_store),
529     (Opcode::Istore32, &[I64], &[], insert_load_store),
530     // Integer Consts
531     (Opcode::Iconst, &[], &[I8], insert_const),
532     (Opcode::Iconst, &[], &[I16], insert_const),
533     (Opcode::Iconst, &[], &[I32], insert_const),
534     (Opcode::Iconst, &[], &[I64], insert_const),
535     (Opcode::Iconst, &[], &[I128], insert_const),
536     // Float Consts
537     (Opcode::F32const, &[], &[F32], insert_const),
538     (Opcode::F64const, &[], &[F64], insert_const),
539     // Bool Consts
540     (Opcode::Bconst, &[], &[B1], insert_const),
541     // Call
542     (Opcode::Call, &[], &[], insert_call),
543 ];
544 
545 /// These libcalls need a interpreter implementation in `cranelift-fuzzgen.rs`
546 const ALLOWED_LIBCALLS: &'static [LibCall] = &[
547     LibCall::CeilF32,
548     LibCall::CeilF64,
549     LibCall::FloorF32,
550     LibCall::FloorF64,
551     LibCall::TruncF32,
552     LibCall::TruncF64,
553 ];
554 
555 pub struct FunctionGenerator<'r, 'data>
556 where
557     'data: 'r,
558 {
559     u: &'r mut Unstructured<'data>,
560     config: &'r Config,
561     resources: Resources,
562 }
563 
564 #[derive(Default)]
565 struct Resources {
566     vars: HashMap<Type, Vec<Variable>>,
567     blocks: Vec<(Block, BlockSignature)>,
568     blocks_without_params: Vec<Block>,
569     jump_tables: Vec<JumpTable>,
570     func_refs: Vec<(Signature, FuncRef)>,
571     stack_slots: Vec<(StackSlot, StackSize)>,
572 }
573 
574 impl<'r, 'data> FunctionGenerator<'r, 'data>
575 where
576     'data: 'r,
577 {
578     pub fn new(u: &'r mut Unstructured<'data>, config: &'r Config) -> Self {
579         Self {
580             u,
581             config,
582             resources: Resources::default(),
583         }
584     }
585 
586     /// Generates a random value for config `param`
587     fn param(&mut self, param: &RangeInclusive<usize>) -> Result<usize> {
588         Ok(self.u.int_in_range(param.clone())?)
589     }
590 
591     fn generate_callconv(&mut self) -> Result<CallConv> {
592         // TODO: Generate random CallConvs per target
593         Ok(CallConv::SystemV)
594     }
595 
596     fn system_callconv(&mut self) -> CallConv {
597         // TODO: This currently only runs on linux, so this is the only choice
598         // We should improve this once we generate flags and targets
599         CallConv::SystemV
600     }
601 
602     fn generate_type(&mut self) -> Result<Type> {
603         // TODO: It would be nice if we could get these directly from cranelift
604         let scalars = [
605             // IFLAGS, FFLAGS,
606             B1, // B8, B16, B32, B64, B128,
607             I8, I16, I32, I64, I128, F32, F64,
608             // R32, R64,
609         ];
610         // TODO: vector types
611 
612         let ty = self.u.choose(&scalars[..])?;
613         Ok(*ty)
614     }
615 
616     fn generate_abi_param(&mut self) -> Result<AbiParam> {
617         let value_type = self.generate_type()?;
618         // TODO: There are more argument purposes to be explored...
619         let purpose = ArgumentPurpose::Normal;
620         let extension = match self.u.int_in_range(0..=2)? {
621             2 => ArgumentExtension::Sext,
622             1 => ArgumentExtension::Uext,
623             _ => ArgumentExtension::None,
624         };
625 
626         Ok(AbiParam {
627             value_type,
628             purpose,
629             extension,
630         })
631     }
632 
633     fn generate_signature(&mut self) -> Result<Signature> {
634         let callconv = self.generate_callconv()?;
635         let mut sig = Signature::new(callconv);
636 
637         for _ in 0..self.param(&self.config.signature_params)? {
638             sig.params.push(self.generate_abi_param()?);
639         }
640 
641         for _ in 0..self.param(&self.config.signature_rets)? {
642             sig.returns.push(self.generate_abi_param()?);
643         }
644 
645         Ok(sig)
646     }
647 
648     /// Finds a stack slot with size of at least n bytes
649     fn stack_slot_with_size(&mut self, n: u32) -> Result<(StackSlot, StackSize)> {
650         let first = self
651             .resources
652             .stack_slots
653             .partition_point(|&(_slot, size)| size < n);
654         Ok(*self.u.choose(&self.resources.stack_slots[first..])?)
655     }
656 
657     /// Generates an address that should allow for a store or a load.
658     ///
659     /// Addresses aren't generated like other values. They are never stored in variables so that
660     /// we don't run the risk of returning them from a function, which would make the fuzzer
661     /// complain since they are different from the interpreter to the backend.
662     ///
663     /// The address is not guaranteed to be valid, but there's a chance that it is.
664     ///
665     /// `min_size`: Controls the amount of space that the address should have.This is not
666     /// guaranteed to be respected
667     fn generate_load_store_address(
668         &mut self,
669         builder: &mut FunctionBuilder,
670         min_size: u32,
671     ) -> Result<(Value, Offset32)> {
672         // TODO: Currently our only source of addresses is stack_addr, but we should
673         // add heap_addr, global_value, symbol_value eventually
674         let (addr, available_size) = {
675             let (ss, slot_size) = self.stack_slot_with_size(min_size)?;
676             let max_offset = slot_size.saturating_sub(min_size);
677             let offset = self.u.int_in_range(0..=max_offset)? as i32;
678             let base_addr = builder.ins().stack_addr(I64, ss, offset);
679             let available_size = (slot_size as i32).saturating_sub(offset);
680             (base_addr, available_size)
681         };
682 
683         // TODO: Insert a bunch of amode opcodes here to modify the address!
684 
685         // Now that we have an address and a size, we just choose a random offset to return to the
686         // caller. Try to preserve min_size bytes.
687         let max_offset = available_size.saturating_sub(min_size as i32);
688         let offset = self.u.int_in_range(0..=max_offset)? as i32;
689 
690         Ok((addr, offset.into()))
691     }
692 
693     /// Get a variable of type `ty` from the current function
694     fn get_variable_of_type(&mut self, ty: Type) -> Result<Variable> {
695         let opts = self.resources.vars.get(&ty).map_or(&[][..], Vec::as_slice);
696         let var = self.u.choose(opts)?;
697         Ok(*var)
698     }
699 
700     /// Generates an instruction(`iconst`/`fconst`/etc...) to introduce a constant value
701     fn generate_const(&mut self, builder: &mut FunctionBuilder, ty: Type) -> Result<Value> {
702         Ok(match ty {
703             I128 => {
704                 // See: https://github.com/bytecodealliance/wasmtime/issues/2906
705                 let hi = builder.ins().iconst(I64, self.u.arbitrary::<i64>()?);
706                 let lo = builder.ins().iconst(I64, self.u.arbitrary::<i64>()?);
707                 builder.ins().iconcat(lo, hi)
708             }
709             ty if ty.is_int() => {
710                 let imm64 = match ty {
711                     I8 => self.u.arbitrary::<i8>()? as i64,
712                     I16 => self.u.arbitrary::<i16>()? as i64,
713                     I32 => self.u.arbitrary::<i32>()? as i64,
714                     I64 => self.u.arbitrary::<i64>()?,
715                     _ => unreachable!(),
716                 };
717                 builder.ins().iconst(ty, imm64)
718             }
719             ty if ty.is_bool() => builder.ins().bconst(ty, bool::arbitrary(self.u)?),
720             // f{32,64}::arbitrary does not generate a bunch of important values
721             // such as Signaling NaN's / NaN's with payload, so generate floats from integers.
722             F32 => builder
723                 .ins()
724                 .f32const(f32::from_bits(u32::arbitrary(self.u)?)),
725             F64 => builder
726                 .ins()
727                 .f64const(f64::from_bits(u64::arbitrary(self.u)?)),
728             _ => unimplemented!(),
729         })
730     }
731 
732     /// Chooses a random block which can be targeted by a jump / branch.
733     /// This means any block that is not the first block.
734     ///
735     /// For convenience we also generate values that match the block's signature
736     fn generate_target_block(
737         &mut self,
738         builder: &mut FunctionBuilder,
739     ) -> Result<(Block, Vec<Value>)> {
740         let block_targets = &self.resources.blocks[1..];
741         let (block, signature) = self.u.choose(block_targets)?.clone();
742         let args = self.generate_values_for_signature(builder, signature.into_iter())?;
743         Ok((block, args))
744     }
745 
746     fn generate_values_for_signature<I: Iterator<Item = Type>>(
747         &mut self,
748         builder: &mut FunctionBuilder,
749         signature: I,
750     ) -> Result<Vec<Value>> {
751         signature
752             .map(|ty| {
753                 let var = self.get_variable_of_type(ty)?;
754                 let val = builder.use_var(var);
755                 Ok(val)
756             })
757             .collect()
758     }
759 
760     fn generate_return(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
761         let types: Vec<Type> = {
762             let rets = &builder.func.signature.returns;
763             rets.iter().map(|p| p.value_type).collect()
764         };
765         let vals = self.generate_values_for_signature(builder, types.into_iter())?;
766 
767         builder.ins().return_(&vals[..]);
768         Ok(())
769     }
770 
771     fn generate_jump(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
772         let (block, args) = self.generate_target_block(builder)?;
773         builder.ins().jump(block, &args[..]);
774         Ok(())
775     }
776 
777     /// Generates a br_table into a random block
778     fn generate_br_table(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
779         let var = self.get_variable_of_type(I32)?; // br_table only supports I32
780         let val = builder.use_var(var);
781 
782         let default_block = *self.u.choose(&self.resources.blocks_without_params)?;
783 
784         let jt = *self.u.choose(&self.resources.jump_tables)?;
785         builder.ins().br_table(val, default_block, jt);
786         Ok(())
787     }
788 
789     /// Generates a brz/brnz into a random block
790     fn generate_br(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
791         let (block, args) = self.generate_target_block(builder)?;
792 
793         let condbr_types = [I8, I16, I32, I64, I128, B1];
794         let _type = *self.u.choose(&condbr_types[..])?;
795         let var = self.get_variable_of_type(_type)?;
796         let val = builder.use_var(var);
797 
798         if bool::arbitrary(self.u)? {
799             builder.ins().brz(val, block, &args[..]);
800         } else {
801             builder.ins().brnz(val, block, &args[..]);
802         }
803 
804         // After brz/brnz we must generate a jump
805         self.generate_jump(builder)?;
806         Ok(())
807     }
808 
809     fn generate_bricmp(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
810         let (block, args) = self.generate_target_block(builder)?;
811         let cond = *self.u.choose(IntCC::all())?;
812 
813         let bricmp_types = [
814             I8, I16, I32,
815             I64,
816             // I128 - TODO: https://github.com/bytecodealliance/wasmtime/issues/4406
817         ];
818         let _type = *self.u.choose(&bricmp_types[..])?;
819 
820         let lhs_var = self.get_variable_of_type(_type)?;
821         let lhs_val = builder.use_var(lhs_var);
822 
823         let rhs_var = self.get_variable_of_type(_type)?;
824         let rhs_val = builder.use_var(rhs_var);
825 
826         builder
827             .ins()
828             .br_icmp(cond, lhs_val, rhs_val, block, &args[..]);
829 
830         // After bricmp's we must generate a jump
831         self.generate_jump(builder)?;
832         Ok(())
833     }
834 
835     fn generate_switch(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
836         let _type = *self.u.choose(&[I8, I16, I32, I64, I128][..])?;
837         let switch_var = self.get_variable_of_type(_type)?;
838         let switch_val = builder.use_var(switch_var);
839 
840         let default_block = *self.u.choose(&self.resources.blocks_without_params)?;
841 
842         // Build this into a HashMap since we cannot have duplicate entries.
843         let mut entries = HashMap::new();
844         for _ in 0..self.param(&self.config.switch_cases)? {
845             // The Switch API only allows for entries that are addressable by the index type
846             // so we need to limit the range of values that we generate.
847             let (ty_min, ty_max) = _type.bounds(false);
848             let range_start = self.u.int_in_range(ty_min..=ty_max)?;
849 
850             // We can either insert a contiguous range of blocks or a individual block
851             // This is done because the Switch API specializes contiguous ranges.
852             let range_size = if bool::arbitrary(self.u)? {
853                 1
854             } else {
855                 self.param(&self.config.switch_max_range_size)?
856             } as u128;
857 
858             // Build the switch entries
859             for i in 0..range_size {
860                 let index = range_start.wrapping_add(i) % ty_max;
861                 let block = *self.u.choose(&self.resources.blocks_without_params)?;
862                 entries.insert(index, block);
863             }
864         }
865 
866         let mut switch = Switch::new();
867         for (entry, block) in entries.into_iter() {
868             switch.set_entry(entry, block);
869         }
870         switch.emit(builder, switch_val, default_block);
871 
872         Ok(())
873     }
874 
875     /// We always need to exit safely out of a block.
876     /// This either means a jump into another block or a return.
877     fn finalize_block(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
878         let gen = self.u.choose(
879             &[
880                 Self::generate_bricmp,
881                 Self::generate_br,
882                 Self::generate_br_table,
883                 Self::generate_jump,
884                 Self::generate_return,
885                 Self::generate_switch,
886             ][..],
887         )?;
888 
889         gen(self, builder)
890     }
891 
892     /// Fills the current block with random instructions
893     fn generate_instructions(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
894         for _ in 0..self.param(&self.config.instructions_per_block)? {
895             let (op, args, rets, inserter) = *self.u.choose(OPCODE_SIGNATURES)?;
896             inserter(self, builder, op, args, rets)?;
897         }
898 
899         Ok(())
900     }
901 
902     fn generate_jumptables(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
903         for _ in 0..self.param(&self.config.jump_tables_per_function)? {
904             let mut jt_data = JumpTableData::new();
905 
906             for _ in 0..self.param(&self.config.jump_table_entries)? {
907                 let block = *self.u.choose(&self.resources.blocks_without_params)?;
908                 jt_data.push_entry(block);
909             }
910 
911             self.resources
912                 .jump_tables
913                 .push(builder.create_jump_table(jt_data));
914         }
915         Ok(())
916     }
917 
918     fn generate_funcrefs(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
919         let count = self.param(&self.config.funcrefs_per_function)?;
920         for func_index in 0..count.try_into().unwrap() {
921             let (ext_name, sig) = if self.u.arbitrary::<bool>()? {
922                 let user_func_ref = builder
923                     .func
924                     .declare_imported_user_function(UserExternalName {
925                         namespace: 0,
926                         index: func_index,
927                     });
928                 let name = ExternalName::User(user_func_ref);
929                 let signature = self.generate_signature()?;
930                 (name, signature)
931             } else {
932                 let libcall = *self.u.choose(ALLOWED_LIBCALLS)?;
933                 // TODO: Use [CallConv::for_libcall] once we generate flags.
934                 let callconv = self.system_callconv();
935                 let signature = libcall.signature(callconv);
936                 (ExternalName::LibCall(libcall), signature)
937             };
938 
939             let sig_ref = builder.import_signature(sig.clone());
940             let func_ref = builder.import_function(ExtFuncData {
941                 name: ext_name,
942                 signature: sig_ref,
943                 colocated: self.u.arbitrary()?,
944             });
945 
946             self.resources.func_refs.push((sig, func_ref));
947         }
948 
949         Ok(())
950     }
951 
952     fn generate_stack_slots(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
953         for _ in 0..self.param(&self.config.static_stack_slots_per_function)? {
954             let bytes = self.param(&self.config.static_stack_slot_size)? as u32;
955             let ss_data = StackSlotData::new(StackSlotKind::ExplicitSlot, bytes);
956             let slot = builder.create_sized_stack_slot(ss_data);
957             self.resources.stack_slots.push((slot, bytes));
958         }
959 
960         self.resources
961             .stack_slots
962             .sort_unstable_by_key(|&(_slot, bytes)| bytes);
963 
964         Ok(())
965     }
966 
967     /// Zero initializes the stack slot by inserting `stack_store`'s.
968     fn initialize_stack_slots(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
969         let i128_zero = builder.ins().iconst(I128, 0);
970         let i64_zero = builder.ins().iconst(I64, 0);
971         let i32_zero = builder.ins().iconst(I32, 0);
972         let i16_zero = builder.ins().iconst(I16, 0);
973         let i8_zero = builder.ins().iconst(I8, 0);
974 
975         for &(slot, init_size) in self.resources.stack_slots.iter() {
976             let mut size = init_size;
977 
978             // Insert the largest available store for the remaining size.
979             while size != 0 {
980                 let offset = (init_size - size) as i32;
981                 let (val, filled) = match size {
982                     sz if sz / 16 > 0 => (i128_zero, 16),
983                     sz if sz / 8 > 0 => (i64_zero, 8),
984                     sz if sz / 4 > 0 => (i32_zero, 4),
985                     sz if sz / 2 > 0 => (i16_zero, 2),
986                     _ => (i8_zero, 1),
987                 };
988                 builder.ins().stack_store(val, slot, offset);
989                 size -= filled;
990             }
991         }
992         Ok(())
993     }
994 
995     /// Creates a random amount of blocks in this function
996     fn generate_blocks(
997         &mut self,
998         builder: &mut FunctionBuilder,
999         sig: &Signature,
1000     ) -> Result<Vec<(Block, BlockSignature)>> {
1001         let extra_block_count = self.param(&self.config.blocks_per_function)?;
1002 
1003         // We must always have at least one block, so we generate the "extra" blocks and add 1 for
1004         // the entry block.
1005         let block_count = 1 + extra_block_count;
1006 
1007         (0..block_count)
1008             .map(|i| {
1009                 let is_entry = i == 0;
1010                 let block = builder.create_block();
1011 
1012                 // Optionally mark blocks that are not the entry block as cold
1013                 if !is_entry {
1014                     if bool::arbitrary(self.u)? {
1015                         builder.set_cold_block(block);
1016                     }
1017                 }
1018 
1019                 // The first block has to have the function signature, but for the rest of them we generate
1020                 // a random signature;
1021                 if is_entry {
1022                     builder.append_block_params_for_function_params(block);
1023                     Ok((block, sig.params.iter().map(|a| a.value_type).collect()))
1024                 } else {
1025                     let sig = self.generate_block_signature()?;
1026                     sig.iter().for_each(|ty| {
1027                         builder.append_block_param(block, *ty);
1028                     });
1029                     Ok((block, sig))
1030                 }
1031             })
1032             .collect()
1033     }
1034 
1035     fn generate_block_signature(&mut self) -> Result<BlockSignature> {
1036         let param_count = self.param(&self.config.block_signature_params)?;
1037 
1038         let mut params = Vec::with_capacity(param_count);
1039         for _ in 0..param_count {
1040             params.push(self.generate_type()?);
1041         }
1042         Ok(params)
1043     }
1044 
1045     fn build_variable_pool(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1046         let block = builder.current_block().unwrap();
1047 
1048         // Define variables for the function signature
1049         let mut vars: Vec<_> = builder
1050             .func
1051             .signature
1052             .params
1053             .iter()
1054             .map(|param| param.value_type)
1055             .zip(builder.block_params(block).iter().copied())
1056             .collect();
1057 
1058         // Create a pool of vars that are going to be used in this function
1059         for _ in 0..self.param(&self.config.vars_per_function)? {
1060             let ty = self.generate_type()?;
1061             let value = self.generate_const(builder, ty)?;
1062             vars.push((ty, value));
1063         }
1064 
1065         for (id, (ty, value)) in vars.into_iter().enumerate() {
1066             let var = Variable::new(id);
1067             builder.declare_var(var, ty);
1068             builder.def_var(var, value);
1069             self.resources
1070                 .vars
1071                 .entry(ty)
1072                 .or_insert_with(Vec::new)
1073                 .push(var);
1074         }
1075 
1076         Ok(())
1077     }
1078 
1079     /// We generate a function in multiple stages:
1080     ///
1081     /// * First we generate a random number of empty blocks
1082     /// * Then we generate a random pool of variables to be used throughout the function
1083     /// * We then visit each block and generate random instructions
1084     ///
1085     /// Because we generate all blocks and variables up front we already know everything that
1086     /// we need when generating instructions (i.e. jump targets / variables)
1087     pub fn generate(mut self) -> Result<Function> {
1088         let sig = self.generate_signature()?;
1089 
1090         let mut fn_builder_ctx = FunctionBuilderContext::new();
1091         // function name must be in a different namespace than TESTFILE_NAMESPACE (0)
1092         let mut func = Function::with_name_signature(UserFuncName::user(1, 0), sig.clone());
1093 
1094         let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx);
1095 
1096         self.resources.blocks = self.generate_blocks(&mut builder, &sig)?;
1097 
1098         // Valid blocks for jump tables have to have no parameters in the signature, and must also
1099         // not be the first block.
1100         self.resources.blocks_without_params = self.resources.blocks[1..]
1101             .iter()
1102             .filter(|(_, sig)| sig.len() == 0)
1103             .map(|(b, _)| *b)
1104             .collect();
1105 
1106         // Function preamble
1107         self.generate_jumptables(&mut builder)?;
1108         self.generate_funcrefs(&mut builder)?;
1109         self.generate_stack_slots(&mut builder)?;
1110 
1111         // Main instruction generation loop
1112         for (i, (block, block_sig)) in self.resources.blocks.clone().iter().enumerate() {
1113             let is_block0 = i == 0;
1114             builder.switch_to_block(*block);
1115 
1116             if is_block0 {
1117                 // The first block is special because we must create variables both for the
1118                 // block signature and for the variable pool. Additionally, we must also define
1119                 // initial values for all variables that are not the function signature.
1120                 self.build_variable_pool(&mut builder)?;
1121 
1122                 // Stack slots have random bytes at the beginning of the function
1123                 // initialize them to a constant value so that execution stays predictable.
1124                 self.initialize_stack_slots(&mut builder)?;
1125             } else {
1126                 // Define variables for the block params
1127                 for (i, ty) in block_sig.iter().enumerate() {
1128                     let var = self.get_variable_of_type(*ty)?;
1129                     let block_param = builder.block_params(*block)[i];
1130                     builder.def_var(var, block_param);
1131                 }
1132             }
1133 
1134             // Generate block instructions
1135             self.generate_instructions(&mut builder)?;
1136 
1137             self.finalize_block(&mut builder)?;
1138         }
1139 
1140         builder.seal_all_blocks();
1141         builder.finalize();
1142 
1143         Ok(func)
1144     }
1145 }
1146