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