1 use crate::config::Config;
2 use crate::cranelift_arbitrary::CraneliftArbitrary;
3 use anyhow::Result;
4 use arbitrary::{Arbitrary, Unstructured};
5 use cranelift::codegen::data_value::DataValue;
6 use cranelift::codegen::ir::immediates::Offset32;
7 use cranelift::codegen::ir::instructions::{InstructionFormat, ResolvedConstraint};
8 use cranelift::codegen::ir::stackslot::StackSize;
9 
10 use cranelift::codegen::ir::{
11     types::*, AtomicRmwOp, Block, ConstantData, ExternalName, FuncRef, Function, LibCall, Opcode,
12     SigRef, Signature, StackSlot, Type, UserExternalName, UserFuncName, Value,
13 };
14 use cranelift::codegen::isa::CallConv;
15 use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
16 use cranelift::prelude::{
17     EntityRef, ExtFuncData, FloatCC, InstBuilder, IntCC, JumpTableData, MemFlags, StackSlotData,
18     StackSlotKind,
19 };
20 use once_cell::sync::Lazy;
21 use std::collections::HashMap;
22 use std::ops::RangeInclusive;
23 use target_lexicon::{Architecture, Triple};
24 
25 type BlockSignature = Vec<Type>;
26 
27 fn insert_opcode(
28     fgen: &mut FunctionGenerator,
29     builder: &mut FunctionBuilder,
30     opcode: Opcode,
31     args: &[Type],
32     rets: &[Type],
33 ) -> Result<()> {
34     let mut vals = Vec::with_capacity(args.len());
35     for &arg in args.into_iter() {
36         let var = fgen.get_variable_of_type(arg)?;
37         let val = builder.use_var(var);
38         vals.push(val);
39     }
40 
41     // Some opcodes require us to look at their input arguments to determine the
42     // controlling type. This is not the general case, but we can neatly check this
43     // using `requires_typevar_operand`.
44     let ctrl_type = if opcode.constraints().requires_typevar_operand() {
45         args.first()
46     } else {
47         rets.first()
48     }
49     .copied()
50     .unwrap_or(INVALID);
51 
52     // Choose the appropriate instruction format for this opcode
53     let (inst, dfg) = match opcode.format() {
54         InstructionFormat::NullAry => builder.ins().NullAry(opcode, ctrl_type),
55         InstructionFormat::Unary => builder.ins().Unary(opcode, ctrl_type, vals[0]),
56         InstructionFormat::Binary => builder.ins().Binary(opcode, ctrl_type, vals[0], vals[1]),
57         InstructionFormat::Ternary => builder
58             .ins()
59             .Ternary(opcode, ctrl_type, vals[0], vals[1], vals[2]),
60         _ => unimplemented!(),
61     };
62     let results = dfg.inst_results(inst).to_vec();
63 
64     for (val, &ty) in results.into_iter().zip(rets) {
65         let var = fgen.get_variable_of_type(ty)?;
66         builder.def_var(var, val);
67     }
68     Ok(())
69 }
70 
71 fn insert_call(
72     fgen: &mut FunctionGenerator,
73     builder: &mut FunctionBuilder,
74     opcode: Opcode,
75     args: &[Type],
76     _rets: &[Type],
77 ) -> Result<()> {
78     assert!(matches!(opcode, Opcode::Call | Opcode::CallIndirect));
79     let (sig, sig_ref, func_ref) = fgen.u.choose(&fgen.resources.func_refs)?.clone();
80 
81     let actuals = fgen.generate_values_for_signature(
82         builder,
83         sig.params.iter().map(|abi_param| abi_param.value_type),
84     )?;
85 
86     let call = if opcode == Opcode::Call {
87         builder.ins().call(func_ref, &actuals)
88     } else {
89         let addr_ty = args[0];
90         let addr = builder.ins().func_addr(addr_ty, func_ref);
91         builder.ins().call_indirect(sig_ref, addr, &actuals)
92     };
93 
94     // Assign the return values to random variables
95     let ret_values = builder.inst_results(call).to_vec();
96     let ret_types = sig.returns.iter().map(|p| p.value_type);
97     for (ty, val) in ret_types.zip(ret_values) {
98         let var = fgen.get_variable_of_type(ty)?;
99         builder.def_var(var, val);
100     }
101 
102     Ok(())
103 }
104 
105 fn insert_stack_load(
106     fgen: &mut FunctionGenerator,
107     builder: &mut FunctionBuilder,
108     _opcode: Opcode,
109     _args: &[Type],
110     rets: &[Type],
111 ) -> Result<()> {
112     let typevar = rets[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 val = builder.ins().stack_load(typevar, slot, offset);
118     let var = fgen.get_variable_of_type(typevar)?;
119     builder.def_var(var, val);
120 
121     Ok(())
122 }
123 
124 fn insert_stack_store(
125     fgen: &mut FunctionGenerator,
126     builder: &mut FunctionBuilder,
127     _opcode: Opcode,
128     args: &[Type],
129     _rets: &[Type],
130 ) -> Result<()> {
131     let typevar = args[0];
132     let type_size = typevar.bytes();
133     let (slot, slot_size) = fgen.stack_slot_with_size(type_size)?;
134     let offset = fgen.u.int_in_range(0..=(slot_size - type_size))? as i32;
135 
136     let arg0 = fgen.get_variable_of_type(typevar)?;
137     let arg0 = builder.use_var(arg0);
138 
139     builder.ins().stack_store(arg0, slot, offset);
140     Ok(())
141 }
142 
143 fn insert_cmp(
144     fgen: &mut FunctionGenerator,
145     builder: &mut FunctionBuilder,
146     opcode: Opcode,
147     args: &[Type],
148     rets: &[Type],
149 ) -> Result<()> {
150     let lhs = fgen.get_variable_of_type(args[0])?;
151     let lhs = builder.use_var(lhs);
152 
153     let rhs = fgen.get_variable_of_type(args[1])?;
154     let rhs = builder.use_var(rhs);
155 
156     let res = if opcode == Opcode::Fcmp {
157         let cc = *fgen.u.choose(FloatCC::all())?;
158 
159         // We filter out condition codes that aren't supported by the target at
160         // this point after randomly choosing one, instead of randomly choosing a
161         // supported one, to avoid invalidating the corpus when these get implemented.
162         let unimplemented_cc = match (fgen.target_triple.architecture, cc) {
163             // Some FloatCC's are not implemented on AArch64, see:
164             // https://github.com/bytecodealliance/wasmtime/issues/4850
165             (Architecture::Aarch64(_), FloatCC::OrderedNotEqual) => true,
166             (Architecture::Aarch64(_), FloatCC::UnorderedOrEqual) => true,
167             (Architecture::Aarch64(_), FloatCC::UnorderedOrLessThan) => true,
168             (Architecture::Aarch64(_), FloatCC::UnorderedOrLessThanOrEqual) => true,
169             (Architecture::Aarch64(_), FloatCC::UnorderedOrGreaterThan) => true,
170             (Architecture::Aarch64(_), FloatCC::UnorderedOrGreaterThanOrEqual) => true,
171 
172             // These are not implemented on x86_64, for vectors.
173             (Architecture::X86_64, FloatCC::UnorderedOrEqual | FloatCC::OrderedNotEqual) => {
174                 args[0].is_vector()
175             }
176             _ => false,
177         };
178         if unimplemented_cc {
179             return Err(arbitrary::Error::IncorrectFormat.into());
180         }
181 
182         builder.ins().fcmp(cc, lhs, rhs)
183     } else {
184         let cc = *fgen.u.choose(IntCC::all())?;
185         builder.ins().icmp(cc, lhs, rhs)
186     };
187 
188     let var = fgen.get_variable_of_type(rets[0])?;
189     builder.def_var(var, res);
190 
191     Ok(())
192 }
193 
194 fn insert_const(
195     fgen: &mut FunctionGenerator,
196     builder: &mut FunctionBuilder,
197     _opcode: Opcode,
198     _args: &[Type],
199     rets: &[Type],
200 ) -> Result<()> {
201     let typevar = rets[0];
202     let var = fgen.get_variable_of_type(typevar)?;
203     let val = fgen.generate_const(builder, typevar)?;
204     builder.def_var(var, val);
205     Ok(())
206 }
207 
208 fn insert_bitcast(
209     fgen: &mut FunctionGenerator,
210     builder: &mut FunctionBuilder,
211     args: &[Type],
212     rets: &[Type],
213 ) -> Result<()> {
214     let from_var = fgen.get_variable_of_type(args[0])?;
215     let from_val = builder.use_var(from_var);
216 
217     let to_var = fgen.get_variable_of_type(rets[0])?;
218 
219     // TODO: We can generate little/big endian flags here.
220     let memflags = MemFlags::new();
221 
222     let res = builder.ins().bitcast(rets[0], memflags, from_val);
223     builder.def_var(to_var, res);
224     Ok(())
225 }
226 
227 fn insert_load_store(
228     fgen: &mut FunctionGenerator,
229     builder: &mut FunctionBuilder,
230     opcode: Opcode,
231     args: &[Type],
232     rets: &[Type],
233 ) -> Result<()> {
234     if opcode == Opcode::Bitcast {
235         return insert_bitcast(fgen, builder, args, rets);
236     }
237 
238     let ctrl_type = *rets.first().or(args.first()).unwrap();
239     let type_size = ctrl_type.bytes();
240 
241     let is_atomic = [Opcode::AtomicLoad, Opcode::AtomicStore].contains(&opcode);
242     let (address, flags, offset) =
243         fgen.generate_address_and_memflags(builder, type_size, is_atomic)?;
244 
245     // The variable being loaded or stored into
246     let var = fgen.get_variable_of_type(ctrl_type)?;
247 
248     match opcode.format() {
249         InstructionFormat::LoadNoOffset => {
250             let (inst, dfg) = builder
251                 .ins()
252                 .LoadNoOffset(opcode, ctrl_type, flags, address);
253 
254             let new_val = dfg.first_result(inst);
255             builder.def_var(var, new_val);
256         }
257         InstructionFormat::StoreNoOffset => {
258             let val = builder.use_var(var);
259 
260             builder
261                 .ins()
262                 .StoreNoOffset(opcode, ctrl_type, flags, val, address);
263         }
264         InstructionFormat::Store => {
265             let val = builder.use_var(var);
266 
267             builder
268                 .ins()
269                 .Store(opcode, ctrl_type, flags, offset, val, address);
270         }
271         InstructionFormat::Load => {
272             let (inst, dfg) = builder
273                 .ins()
274                 .Load(opcode, ctrl_type, flags, offset, address);
275 
276             let new_val = dfg.first_result(inst);
277             builder.def_var(var, new_val);
278         }
279         _ => unimplemented!(),
280     }
281 
282     Ok(())
283 }
284 
285 fn insert_atomic_rmw(
286     fgen: &mut FunctionGenerator,
287     builder: &mut FunctionBuilder,
288     _: Opcode,
289     _: &[Type],
290     rets: &[Type],
291 ) -> Result<()> {
292     let ctrl_type = *rets.first().unwrap();
293     let type_size = ctrl_type.bytes();
294 
295     let rmw_op = *fgen.u.choose(AtomicRmwOp::all())?;
296 
297     let (address, flags, offset) = fgen.generate_address_and_memflags(builder, type_size, true)?;
298 
299     // AtomicRMW does not directly support offsets, so add the offset to the address separately.
300     let address = builder.ins().iadd_imm(address, i64::from(offset));
301 
302     // Load and store target variables
303     let source_var = fgen.get_variable_of_type(ctrl_type)?;
304     let target_var = fgen.get_variable_of_type(ctrl_type)?;
305 
306     let source_val = builder.use_var(source_var);
307     let new_val = builder
308         .ins()
309         .atomic_rmw(ctrl_type, flags, rmw_op, address, source_val);
310 
311     builder.def_var(target_var, new_val);
312     Ok(())
313 }
314 
315 fn insert_atomic_cas(
316     fgen: &mut FunctionGenerator,
317     builder: &mut FunctionBuilder,
318     _: Opcode,
319     _: &[Type],
320     rets: &[Type],
321 ) -> Result<()> {
322     let ctrl_type = *rets.first().unwrap();
323     let type_size = ctrl_type.bytes();
324 
325     let (address, flags, offset) = fgen.generate_address_and_memflags(builder, type_size, true)?;
326 
327     // AtomicCas does not directly support offsets, so add the offset to the address separately.
328     let address = builder.ins().iadd_imm(address, i64::from(offset));
329 
330     // Source and Target variables
331     let expected_var = fgen.get_variable_of_type(ctrl_type)?;
332     let store_var = fgen.get_variable_of_type(ctrl_type)?;
333     let loaded_var = fgen.get_variable_of_type(ctrl_type)?;
334 
335     let expected_val = builder.use_var(expected_var);
336     let store_val = builder.use_var(store_var);
337     let new_val = builder
338         .ins()
339         .atomic_cas(flags, address, expected_val, store_val);
340 
341     builder.def_var(loaded_var, new_val);
342     Ok(())
343 }
344 
345 fn insert_shuffle(
346     fgen: &mut FunctionGenerator,
347     builder: &mut FunctionBuilder,
348     opcode: Opcode,
349     _: &[Type],
350     rets: &[Type],
351 ) -> Result<()> {
352     let ctrl_type = *rets.first().unwrap();
353 
354     let lhs = builder.use_var(fgen.get_variable_of_type(ctrl_type)?);
355     let rhs = builder.use_var(fgen.get_variable_of_type(ctrl_type)?);
356 
357     let mask = {
358         let mut lanes = [0u8; 16];
359         for lane in lanes.iter_mut() {
360             *lane = fgen.u.int_in_range(0..=31)?;
361         }
362         let lanes = ConstantData::from(lanes.as_ref());
363         builder.func.dfg.immediates.push(lanes)
364     };
365 
366     // This function is called for any `InstructionFormat::Shuffle`. Which today is just
367     // `shuffle`, but lets assert that, just to be sure we don't accidentally insert
368     // something else.
369     assert_eq!(opcode, Opcode::Shuffle);
370     let res = builder.ins().shuffle(lhs, rhs, mask);
371 
372     let target_var = fgen.get_variable_of_type(ctrl_type)?;
373     builder.def_var(target_var, res);
374 
375     Ok(())
376 }
377 
378 fn insert_ins_ext_lane(
379     fgen: &mut FunctionGenerator,
380     builder: &mut FunctionBuilder,
381     opcode: Opcode,
382     args: &[Type],
383     rets: &[Type],
384 ) -> Result<()> {
385     let vector_type = *args.first().unwrap();
386     let ret_type = *rets.first().unwrap();
387 
388     let lhs = builder.use_var(fgen.get_variable_of_type(vector_type)?);
389     let max_lane = (vector_type.lane_count() as u8) - 1;
390     let lane = fgen.u.int_in_range(0..=max_lane)?;
391 
392     let res = match opcode {
393         Opcode::Insertlane => {
394             let rhs = builder.use_var(fgen.get_variable_of_type(args[1])?);
395             builder.ins().insertlane(lhs, rhs, lane)
396         }
397         Opcode::Extractlane => builder.ins().extractlane(lhs, lane),
398         _ => todo!(),
399     };
400 
401     let target_var = fgen.get_variable_of_type(ret_type)?;
402     builder.def_var(target_var, res);
403 
404     Ok(())
405 }
406 
407 type OpcodeInserter = fn(
408     fgen: &mut FunctionGenerator,
409     builder: &mut FunctionBuilder,
410     Opcode,
411     &[Type],
412     &[Type],
413 ) -> Result<()>;
414 
415 macro_rules! exceptions {
416     ($op:expr, $args:expr, $rets:expr, $(($($cases:pat),*)),* $(,)?) => {
417         match ($op, $args, $rets) {
418             $( ($($cases,)* ..) => return false, )*
419             _ => true,
420         }
421     }
422 }
423 
424 /// Returns true if we believe this `OpcodeSignature` should compile correctly
425 /// for the given target triple. We currently have a range of known issues
426 /// with specific lowerings on specific backends, and we don't want to get
427 /// fuzz bug reports for those. Over time our goal is to eliminate all of these
428 /// exceptions.
429 fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -> bool {
430     // Rule out invalid combinations that we don't yet have a good way of rejecting with the
431     // instruction DSL type constraints.
432     match op {
433         Opcode::FcvtToUintSat | Opcode::FcvtToSintSat => {
434             assert_eq!(args.len(), 1);
435             assert_eq!(rets.len(), 1);
436 
437             let arg = args[0];
438             let ret = args[0];
439 
440             // Vector arguments must produce vector results, and scalar arguments must produce
441             // scalar results.
442             if arg.is_vector() != ret.is_vector() {
443                 return false;
444             }
445 
446             if arg.is_vector() && arg.is_vector() {
447                 // Vector conversions must have the same number of lanes, and the lanes must be the
448                 // same bit-width.
449                 if arg.lane_count() != ret.lane_count() {
450                     return false;
451                 }
452 
453                 if arg.lane_of().bits() != ret.lane_of().bits() {
454                     return false;
455                 }
456             }
457         }
458 
459         _ => {}
460     }
461 
462     match triple.architecture {
463         Architecture::X86_64 => {
464             exceptions!(
465                 op,
466                 args,
467                 rets,
468                 (Opcode::UmulOverflow | Opcode::SmulOverflow, &[I128, I128]),
469                 (Opcode::Imul, &[I8X16, I8X16]),
470                 // https://github.com/bytecodealliance/wasmtime/issues/5468
471                 (Opcode::Smulhi | Opcode::Umulhi, &[I8, I8]),
472                 // https://github.com/bytecodealliance/wasmtime/issues/4756
473                 (Opcode::Udiv | Opcode::Sdiv, &[I128, I128]),
474                 // https://github.com/bytecodealliance/wasmtime/issues/5474
475                 (Opcode::Urem | Opcode::Srem, &[I128, I128]),
476                 // https://github.com/bytecodealliance/wasmtime/issues/5466
477                 (Opcode::Iabs, &[I128]),
478                 // https://github.com/bytecodealliance/wasmtime/issues/3370
479                 (
480                     Opcode::Smin | Opcode::Umin | Opcode::Smax | Opcode::Umax,
481                     &[I128, I128]
482                 ),
483                 // https://github.com/bytecodealliance/wasmtime/issues/4870
484                 (Opcode::Bnot, &[F32 | F64]),
485                 (
486                     Opcode::Band
487                         | Opcode::Bor
488                         | Opcode::Bxor
489                         | Opcode::BandNot
490                         | Opcode::BorNot
491                         | Opcode::BxorNot,
492                     &([F32, F32] | [F64, F64])
493                 ),
494                 // https://github.com/bytecodealliance/wasmtime/issues/5041
495                 (
496                     Opcode::BandNot | Opcode::BorNot | Opcode::BxorNot,
497                     &([I8, I8] | [I16, I16] | [I32, I32] | [I64, I64] | [I128, I128])
498                 ),
499                 // https://github.com/bytecodealliance/wasmtime/issues/5107
500                 (Opcode::Cls, &[I8], &[I8]),
501                 (Opcode::Cls, &[I16], &[I16]),
502                 (Opcode::Cls, &[I32], &[I32]),
503                 (Opcode::Cls, &[I64], &[I64]),
504                 (Opcode::Cls, &[I128], &[I128]),
505                 // https://github.com/bytecodealliance/wasmtime/issues/5197
506                 (
507                     Opcode::Bitselect,
508                     &([I8, I8, I8]
509                         | [I16, I16, I16]
510                         | [I32, I32, I32]
511                         | [I64, I64, I64]
512                         | [I128, I128, I128])
513                 ),
514                 // https://github.com/bytecodealliance/wasmtime/issues/4897
515                 // https://github.com/bytecodealliance/wasmtime/issues/4899
516                 (
517                     Opcode::FcvtToUint
518                         | Opcode::FcvtToUintSat
519                         | Opcode::FcvtToSint
520                         | Opcode::FcvtToSintSat,
521                     &[F32 | F64],
522                     &[I8 | I16 | I128]
523                 ),
524                 (Opcode::FcvtToUint | Opcode::FcvtToSint, &[F32X4], &[I32X4]),
525                 (
526                     Opcode::FcvtToUint
527                         | Opcode::FcvtToUintSat
528                         | Opcode::FcvtToSint
529                         | Opcode::FcvtToSintSat,
530                     &[F64X2],
531                     &[I64X2]
532                 ),
533                 // https://github.com/bytecodealliance/wasmtime/issues/4900
534                 (Opcode::FcvtFromUint, &[I128], &[F32 | F64]),
535                 // This has a lowering, but only when preceded by `uwiden_low`.
536                 (Opcode::FcvtFromUint, &[I64X2], &[F64X2]),
537                 // https://github.com/bytecodealliance/wasmtime/issues/4900
538                 (Opcode::FcvtFromSint, &[I128], &[F32 | F64]),
539                 (Opcode::FcvtFromSint, &[I64X2], &[F64X2]),
540                 (
541                     Opcode::Umulhi | Opcode::Smulhi,
542                     &([I8X16, I8X16] | [I16X8, I16X8] | [I32X4, I32X4] | [I64X2, I64X2])
543                 ),
544                 (
545                     Opcode::UaddSat | Opcode::SaddSat | Opcode::UsubSat | Opcode::SsubSat,
546                     &([I32X4, I32X4] | [I64X2, I64X2])
547                 ),
548                 (Opcode::Fcopysign, &([F32X4, F32X4] | [F64X2, F64X2])),
549                 (Opcode::Popcnt, &([I8X16] | [I16X8] | [I32X4] | [I64X2])),
550                 (
551                     Opcode::Umax | Opcode::Smax | Opcode::Umin | Opcode::Smin,
552                     &[I64X2, I64X2]
553                 ),
554                 (Opcode::Bitcast, &[I128], &[_]),
555                 (Opcode::Bitcast, &[_], &[I128]),
556                 (Opcode::Uunarrow),
557                 (Opcode::Snarrow | Opcode::Unarrow, &[I64X2, I64X2]),
558                 (Opcode::SqmulRoundSat, &[I32X4, I32X4]),
559                 // This Icmp is not implemented: #5529
560                 (Opcode::Icmp, &[I64X2, I64X2]),
561                 // IaddPairwise is implemented, but only for some types, and with some preceding ops.
562                 (Opcode::IaddPairwise),
563                 // Nothing wrong with this select. But we have an isle rule that can optimize it
564                 // into a `min`/`max` instructions, which we don't have implemented yet.
565                 (Opcode::Select, &[_, I128, I128]),
566                 // These stack accesses can cause segfaults if they are merged into an SSE instruction.
567                 // See: #5922
568                 (
569                     Opcode::StackStore,
570                     &[I8X16 | I16X8 | I32X4 | I64X2 | F32X4 | F64X2]
571                 ),
572                 (
573                     Opcode::StackLoad,
574                     &[],
575                     &[I8X16 | I16X8 | I32X4 | I64X2 | F32X4 | F64X2]
576                 ),
577             )
578         }
579 
580         Architecture::Aarch64(_) => {
581             exceptions!(
582                 op,
583                 args,
584                 rets,
585                 (Opcode::UmulOverflow | Opcode::SmulOverflow, &[I128, I128]),
586                 // https://github.com/bytecodealliance/wasmtime/issues/4864
587                 (Opcode::Udiv | Opcode::Sdiv, &[I128, I128]),
588                 // https://github.com/bytecodealliance/wasmtime/issues/5472
589                 (Opcode::Urem | Opcode::Srem, &[I128, I128]),
590                 // https://github.com/bytecodealliance/wasmtime/issues/5467
591                 (Opcode::Iabs, &[I128]),
592                 // https://github.com/bytecodealliance/wasmtime/issues/4313
593                 (
594                     Opcode::Smin | Opcode::Umin | Opcode::Smax | Opcode::Umax,
595                     &[I128, I128]
596                 ),
597                 // https://github.com/bytecodealliance/wasmtime/issues/4870
598                 (Opcode::Bnot, &[F32 | F64]),
599                 (
600                     Opcode::Band
601                         | Opcode::Bor
602                         | Opcode::Bxor
603                         | Opcode::BandNot
604                         | Opcode::BorNot
605                         | Opcode::BxorNot,
606                     &([F32, F32] | [F64, F64])
607                 ),
608                 // https://github.com/bytecodealliance/wasmtime/issues/5198
609                 (Opcode::Bitselect, &[I128, I128, I128]),
610                 // https://github.com/bytecodealliance/wasmtime/issues/4934
611                 (
612                     Opcode::FcvtToUint
613                         | Opcode::FcvtToUintSat
614                         | Opcode::FcvtToSint
615                         | Opcode::FcvtToSintSat,
616                     &[F32 | F64]
617                 ),
618                 // https://github.com/bytecodealliance/wasmtime/issues/4933
619                 (
620                     Opcode::FcvtFromUint | Opcode::FcvtFromSint,
621                     &[I128],
622                     &[F32 | F64]
623                 ),
624                 (
625                     Opcode::Umulhi | Opcode::Smulhi,
626                     &([I8X16, I8X16] | [I16X8, I16X8] | [I32X4, I32X4] | [I64X2, I64X2])
627                 ),
628                 (Opcode::Popcnt, &[I16X8 | I32X4 | I64X2]),
629                 // Nothing wrong with this select. But we have an isle rule that can optimize it
630                 // into a `min`/`max` instructions, which we don't have implemented yet.
631                 (Opcode::Select, &[I8, I128, I128]),
632             )
633         }
634 
635         Architecture::S390x => {
636             exceptions!(
637                 op,
638                 args,
639                 rets,
640                 (Opcode::UaddOverflow | Opcode::SaddOverflow),
641                 (Opcode::UsubOverflow | Opcode::SsubOverflow),
642                 (Opcode::UmulOverflow | Opcode::SmulOverflow),
643                 (
644                     Opcode::Udiv | Opcode::Sdiv | Opcode::Urem | Opcode::Srem,
645                     &[I128, I128]
646                 ),
647                 (Opcode::Bnot, &[F32 | F64]),
648                 (
649                     Opcode::Band
650                         | Opcode::Bor
651                         | Opcode::Bxor
652                         | Opcode::BandNot
653                         | Opcode::BorNot
654                         | Opcode::BxorNot,
655                     &([F32, F32] | [F64, F64])
656                 ),
657                 (
658                     Opcode::FcvtToUint
659                         | Opcode::FcvtToUintSat
660                         | Opcode::FcvtToSint
661                         | Opcode::FcvtToSintSat,
662                     &[F32 | F64],
663                     &[I128]
664                 ),
665                 (
666                     Opcode::FcvtFromUint | Opcode::FcvtFromSint,
667                     &[I128],
668                     &[F32 | F64]
669                 ),
670                 (Opcode::SsubSat | Opcode::SaddSat, &[I64X2, I64X2]),
671             )
672         }
673 
674         Architecture::Riscv64(_) => {
675             // RISC-V Does not support SIMD at all
676             let is_simd = args.iter().chain(rets).any(|t| t.is_vector());
677             if is_simd {
678                 return false;
679             }
680 
681             exceptions!(
682                 op,
683                 args,
684                 rets,
685                 // TODO
686                 (Opcode::UaddOverflow | Opcode::SaddOverflow),
687                 (Opcode::UsubOverflow | Opcode::SsubOverflow),
688                 (Opcode::UmulOverflow | Opcode::SmulOverflow),
689                 // TODO
690                 (
691                     Opcode::Udiv | Opcode::Sdiv | Opcode::Urem | Opcode::Srem,
692                     &[I128, I128]
693                 ),
694                 // TODO
695                 (Opcode::Iabs, &[I128]),
696                 // TODO
697                 (Opcode::Bitselect, &[I128, I128, I128]),
698                 // TODO
699                 (Opcode::Bswap),
700                 // https://github.com/bytecodealliance/wasmtime/issues/5528
701                 (
702                     Opcode::FcvtToUint | Opcode::FcvtToSint,
703                     [F32 | F64],
704                     &[I128]
705                 ),
706                 (
707                     Opcode::FcvtToUintSat | Opcode::FcvtToSintSat,
708                     &[F32 | F64],
709                     &[I8 | I16 | I128]
710                 ),
711                 // https://github.com/bytecodealliance/wasmtime/issues/5528
712                 (
713                     Opcode::FcvtFromUint | Opcode::FcvtFromSint,
714                     &[I128],
715                     &[F32 | F64]
716                 ),
717             )
718         }
719 
720         _ => true,
721     }
722 }
723 
724 type OpcodeSignature = (Opcode, Vec<Type>, Vec<Type>);
725 
726 static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = Lazy::new(|| {
727     let types = &[
728         I8, I16, I32, I64, I128, // Scalar Integers
729         F32, F64, // Scalar Floats
730         I8X16, I16X8, I32X4, I64X2, // SIMD Integers
731         F32X4, F64X2, // SIMD Floats
732     ];
733 
734     Opcode::all()
735         .iter()
736         .filter(|op| {
737             match op {
738                 // Control flow opcodes should not be generated through `generate_instructions`.
739                 Opcode::BrTable | Opcode::Brif | Opcode::Jump | Opcode::Return => false,
740 
741                 // Constants are generated outside of `generate_instructions`
742                 Opcode::Iconst => false,
743 
744                 // TODO: extract_vector raises exceptions during return type generation becuase it
745                 // uses dynamic vectors.
746                 Opcode::ExtractVector => false,
747 
748                 _ => true,
749             }
750         })
751         .flat_map(|op| {
752             let constraints = op.constraints();
753 
754             let ctrl_types = if let Some(ctrls) = constraints.ctrl_typeset() {
755                 Vec::from_iter(types.iter().copied().filter(|ty| ctrls.contains(*ty)))
756             } else {
757                 vec![INVALID]
758             };
759 
760             ctrl_types.into_iter().flat_map(move |ctrl_type| {
761                 let rets = Vec::from_iter(
762                     (0..constraints.num_fixed_results())
763                         .map(|i| constraints.result_type(i, ctrl_type)),
764                 );
765 
766                 // Cols is a vector whose length will match `num_fixed_value_arguments`, and whose
767                 // elements will be vectors of types that are valid for that fixed argument
768                 // position.
769                 let mut cols = vec![];
770 
771                 for i in 0..constraints.num_fixed_value_arguments() {
772                     match constraints.value_argument_constraint(i, ctrl_type) {
773                         ResolvedConstraint::Bound(ty) => cols.push(Vec::from([ty])),
774                         ResolvedConstraint::Free(tys) => cols.push(Vec::from_iter(
775                             types.iter().copied().filter(|ty| tys.contains(*ty)),
776                         )),
777                     }
778                 }
779 
780                 // Generate the cartesian product of cols to produce a vector of argument lists,
781                 // argss. The argss vector is seeded with the empty argument list, so there's an
782                 // initial value to be extended in the loop below.
783                 let mut argss = vec![vec![]];
784                 let mut cols = cols.as_slice();
785                 while let Some((col, rest)) = cols.split_last() {
786                     cols = rest;
787 
788                     let mut next = vec![];
789                     for current in argss.iter() {
790                         // Extend the front of each argument candidate with every type in `col`.
791                         for ty in col {
792                             let mut args = vec![*ty];
793                             args.extend_from_slice(&current);
794                             next.push(args);
795                         }
796                     }
797 
798                     let _ = std::mem::replace(&mut argss, next);
799                 }
800 
801                 argss.into_iter().map(move |args| (*op, args, rets.clone()))
802             })
803         })
804         .filter(|(op, args, rets)| {
805             // These op/signature combinations need to be vetted
806             exceptions!(
807                 op,
808                 args.as_slice(),
809                 rets.as_slice(),
810                 (Opcode::Debugtrap),
811                 (Opcode::Trap),
812                 (Opcode::Trapz),
813                 (Opcode::ResumableTrap),
814                 (Opcode::Trapnz),
815                 (Opcode::ResumableTrapnz),
816                 (Opcode::CallIndirect, &[I32]),
817                 (Opcode::ReturnCall),
818                 (Opcode::ReturnCallIndirect),
819                 (Opcode::FuncAddr),
820                 (Opcode::X86Pshufb),
821                 (Opcode::AvgRound),
822                 (Opcode::Uload8x8),
823                 (Opcode::Sload8x8),
824                 (Opcode::Uload16x4),
825                 (Opcode::Sload16x4),
826                 (Opcode::Uload32x2),
827                 (Opcode::Sload32x2),
828                 (Opcode::StackAddr),
829                 (Opcode::DynamicStackLoad),
830                 (Opcode::DynamicStackStore),
831                 (Opcode::DynamicStackAddr),
832                 (Opcode::GlobalValue),
833                 (Opcode::SymbolValue),
834                 (Opcode::TlsValue),
835                 (Opcode::GetPinnedReg),
836                 (Opcode::SetPinnedReg),
837                 (Opcode::GetFramePointer),
838                 (Opcode::GetStackPointer),
839                 (Opcode::GetReturnAddress),
840                 (Opcode::TableAddr),
841                 (Opcode::Null),
842                 (Opcode::X86Blendv),
843                 (Opcode::VallTrue),
844                 (Opcode::IcmpImm),
845                 (Opcode::X86Pmulhrsw),
846                 (Opcode::IaddImm),
847                 (Opcode::ImulImm),
848                 (Opcode::UdivImm),
849                 (Opcode::SdivImm),
850                 (Opcode::UremImm),
851                 (Opcode::SremImm),
852                 (Opcode::IrsubImm),
853                 (Opcode::IaddCin),
854                 (Opcode::IaddCarry),
855                 (Opcode::UaddOverflowTrap),
856                 (Opcode::IsubBin),
857                 (Opcode::IsubBorrow),
858                 (Opcode::BandImm),
859                 (Opcode::BorImm),
860                 (Opcode::BxorImm),
861                 (Opcode::RotlImm),
862                 (Opcode::RotrImm),
863                 (Opcode::IshlImm),
864                 (Opcode::UshrImm),
865                 (Opcode::SshrImm),
866                 (Opcode::IsNull),
867                 (Opcode::IsInvalid),
868                 (Opcode::ScalarToVector),
869                 (Opcode::X86Pmaddubsw),
870                 (Opcode::X86Cvtt2dq),
871                 (Opcode::Select, &[I8, F32, F32], &[F32]),
872                 (Opcode::Select, &[I16, F32, F32], &[F32]),
873                 (Opcode::Select, &[I32, F32, F32], &[F32]),
874                 (Opcode::Select, &[I64, F32, F32], &[F32]),
875                 (Opcode::Select, &[I128, F32, F32], &[F32]),
876                 (Opcode::Select, &[I8, F64, F64], &[F64]),
877                 (Opcode::Select, &[I16, F64, F64], &[F64]),
878                 (Opcode::Select, &[I32, F64, F64], &[F64]),
879                 (Opcode::Select, &[I64, F64, F64], &[F64]),
880                 (Opcode::Select, &[I128, F64, F64], &[F64]),
881                 (Opcode::Select, &[I8, I8X16, I8X16], &[I8X16]),
882                 (Opcode::Select, &[I16, I8X16, I8X16], &[I8X16]),
883                 (Opcode::Select, &[I32, I8X16, I8X16], &[I8X16]),
884                 (Opcode::Select, &[I64, I8X16, I8X16], &[I8X16]),
885                 (Opcode::Select, &[I128, I8X16, I8X16], &[I8X16]),
886                 (Opcode::Select, &[I8, I16X8, I16X8], &[I16X8]),
887                 (Opcode::Select, &[I16, I16X8, I16X8], &[I16X8]),
888                 (Opcode::Select, &[I32, I16X8, I16X8], &[I16X8]),
889                 (Opcode::Select, &[I64, I16X8, I16X8], &[I16X8]),
890                 (Opcode::Select, &[I128, I16X8, I16X8], &[I16X8]),
891                 (Opcode::Select, &[I8, I32X4, I32X4], &[I32X4]),
892                 (Opcode::Select, &[I16, I32X4, I32X4], &[I32X4]),
893                 (Opcode::Select, &[I32, I32X4, I32X4], &[I32X4]),
894                 (Opcode::Select, &[I64, I32X4, I32X4], &[I32X4]),
895                 (Opcode::Select, &[I128, I32X4, I32X4], &[I32X4]),
896                 (Opcode::Select, &[I8, I64X2, I64X2], &[I64X2]),
897                 (Opcode::Select, &[I16, I64X2, I64X2], &[I64X2]),
898                 (Opcode::Select, &[I32, I64X2, I64X2], &[I64X2]),
899                 (Opcode::Select, &[I64, I64X2, I64X2], &[I64X2]),
900                 (Opcode::Select, &[I128, I64X2, I64X2], &[I64X2]),
901                 (Opcode::Select, &[I8, F32X4, F32X4], &[F32X4]),
902                 (Opcode::Select, &[I16, F32X4, F32X4], &[F32X4]),
903                 (Opcode::Select, &[I32, F32X4, F32X4], &[F32X4]),
904                 (Opcode::Select, &[I64, F32X4, F32X4], &[F32X4]),
905                 (Opcode::Select, &[I128, F32X4, F32X4], &[F32X4]),
906                 (Opcode::Select, &[I8, F64X2, F64X2], &[F64X2]),
907                 (Opcode::Select, &[I16, F64X2, F64X2], &[F64X2]),
908                 (Opcode::Select, &[I32, F64X2, F64X2], &[F64X2]),
909                 (Opcode::Select, &[I64, F64X2, F64X2], &[F64X2]),
910                 (Opcode::Select, &[I128, F64X2, F64X2], &[F64X2]),
911                 (Opcode::SelectSpectreGuard, &[I8, F32, F32], &[F32]),
912                 (Opcode::SelectSpectreGuard, &[I16, F32, F32], &[F32]),
913                 (Opcode::SelectSpectreGuard, &[I32, F32, F32], &[F32]),
914                 (Opcode::SelectSpectreGuard, &[I64, F32, F32], &[F32]),
915                 (Opcode::SelectSpectreGuard, &[I128, F32, F32], &[F32]),
916                 (Opcode::SelectSpectreGuard, &[I8, F64, F64], &[F64]),
917                 (Opcode::SelectSpectreGuard, &[I16, F64, F64], &[F64]),
918                 (Opcode::SelectSpectreGuard, &[I32, F64, F64], &[F64]),
919                 (Opcode::SelectSpectreGuard, &[I64, F64, F64], &[F64]),
920                 (Opcode::SelectSpectreGuard, &[I128, F64, F64], &[F64]),
921                 (Opcode::SelectSpectreGuard, &[I8, I8X16, I8X16], &[I8X16]),
922                 (Opcode::SelectSpectreGuard, &[I16, I8X16, I8X16], &[I8X16]),
923                 (Opcode::SelectSpectreGuard, &[I32, I8X16, I8X16], &[I8X16]),
924                 (Opcode::SelectSpectreGuard, &[I64, I8X16, I8X16], &[I8X16]),
925                 (Opcode::SelectSpectreGuard, &[I128, I8X16, I8X16], &[I8X16]),
926                 (Opcode::SelectSpectreGuard, &[I8, I16X8, I16X8], &[I16X8]),
927                 (Opcode::SelectSpectreGuard, &[I16, I16X8, I16X8], &[I16X8]),
928                 (Opcode::SelectSpectreGuard, &[I32, I16X8, I16X8], &[I16X8]),
929                 (Opcode::SelectSpectreGuard, &[I64, I16X8, I16X8], &[I16X8]),
930                 (Opcode::SelectSpectreGuard, &[I128, I16X8, I16X8], &[I16X8]),
931                 (Opcode::SelectSpectreGuard, &[I8, I32X4, I32X4], &[I32X4]),
932                 (Opcode::SelectSpectreGuard, &[I16, I32X4, I32X4], &[I32X4]),
933                 (Opcode::SelectSpectreGuard, &[I32, I32X4, I32X4], &[I32X4]),
934                 (Opcode::SelectSpectreGuard, &[I64, I32X4, I32X4], &[I32X4]),
935                 (Opcode::SelectSpectreGuard, &[I128, I32X4, I32X4], &[I32X4]),
936                 (Opcode::SelectSpectreGuard, &[I8, I64X2, I64X2], &[I64X2]),
937                 (Opcode::SelectSpectreGuard, &[I16, I64X2, I64X2], &[I64X2]),
938                 (Opcode::SelectSpectreGuard, &[I32, I64X2, I64X2], &[I64X2]),
939                 (Opcode::SelectSpectreGuard, &[I64, I64X2, I64X2], &[I64X2]),
940                 (Opcode::SelectSpectreGuard, &[I128, I64X2, I64X2], &[I64X2]),
941                 (Opcode::SelectSpectreGuard, &[I8, F32X4, F32X4], &[F32X4]),
942                 (Opcode::SelectSpectreGuard, &[I16, F32X4, F32X4], &[F32X4]),
943                 (Opcode::SelectSpectreGuard, &[I32, F32X4, F32X4], &[F32X4]),
944                 (Opcode::SelectSpectreGuard, &[I64, F32X4, F32X4], &[F32X4]),
945                 (Opcode::SelectSpectreGuard, &[I128, F32X4, F32X4], &[F32X4]),
946                 (Opcode::SelectSpectreGuard, &[I8, F64X2, F64X2], &[F64X2]),
947                 (Opcode::SelectSpectreGuard, &[I16, F64X2, F64X2], &[F64X2]),
948                 (Opcode::SelectSpectreGuard, &[I32, F64X2, F64X2], &[F64X2]),
949                 (Opcode::SelectSpectreGuard, &[I64, F64X2, F64X2], &[F64X2]),
950                 (Opcode::SelectSpectreGuard, &[I128, F64X2, F64X2], &[F64X2]),
951                 (Opcode::Bitselect, &[F32, F32, F32], &[F32]),
952                 (Opcode::Bitselect, &[F64, F64, F64], &[F64]),
953                 (Opcode::Bitselect, &[F32X4, F32X4, F32X4], &[F32X4]),
954                 (Opcode::Bitselect, &[F64X2, F64X2, F64X2], &[F64X2]),
955                 (Opcode::VanyTrue, &[F32X4], &[I8]),
956                 (Opcode::VanyTrue, &[F64X2], &[I8]),
957                 (Opcode::VhighBits, &[F32X4], &[I8]),
958                 (Opcode::VhighBits, &[F64X2], &[I8]),
959                 (Opcode::VhighBits, &[I8X16], &[I16]),
960                 (Opcode::VhighBits, &[I16X8], &[I16]),
961                 (Opcode::VhighBits, &[I32X4], &[I16]),
962                 (Opcode::VhighBits, &[I64X2], &[I16]),
963                 (Opcode::VhighBits, &[F32X4], &[I16]),
964                 (Opcode::VhighBits, &[F64X2], &[I16]),
965                 (Opcode::VhighBits, &[I8X16], &[I32]),
966                 (Opcode::VhighBits, &[I16X8], &[I32]),
967                 (Opcode::VhighBits, &[I32X4], &[I32]),
968                 (Opcode::VhighBits, &[I64X2], &[I32]),
969                 (Opcode::VhighBits, &[F32X4], &[I32]),
970                 (Opcode::VhighBits, &[F64X2], &[I32]),
971                 (Opcode::VhighBits, &[I8X16], &[I64]),
972                 (Opcode::VhighBits, &[I16X8], &[I64]),
973                 (Opcode::VhighBits, &[I32X4], &[I64]),
974                 (Opcode::VhighBits, &[I64X2], &[I64]),
975                 (Opcode::VhighBits, &[F32X4], &[I64]),
976                 (Opcode::VhighBits, &[F64X2], &[I64]),
977                 (Opcode::VhighBits, &[I8X16], &[I128]),
978                 (Opcode::VhighBits, &[I16X8], &[I128]),
979                 (Opcode::VhighBits, &[I32X4], &[I128]),
980                 (Opcode::VhighBits, &[I64X2], &[I128]),
981                 (Opcode::VhighBits, &[F32X4], &[I128]),
982                 (Opcode::VhighBits, &[F64X2], &[I128]),
983                 (Opcode::VhighBits, &[I8X16], &[I8X16]),
984                 (Opcode::VhighBits, &[I16X8], &[I8X16]),
985                 (Opcode::VhighBits, &[I32X4], &[I8X16]),
986                 (Opcode::VhighBits, &[I64X2], &[I8X16]),
987                 (Opcode::VhighBits, &[F32X4], &[I8X16]),
988                 (Opcode::VhighBits, &[F64X2], &[I8X16]),
989                 (Opcode::VhighBits, &[I8X16], &[I16X8]),
990                 (Opcode::VhighBits, &[I16X8], &[I16X8]),
991                 (Opcode::VhighBits, &[I32X4], &[I16X8]),
992                 (Opcode::VhighBits, &[I64X2], &[I16X8]),
993                 (Opcode::VhighBits, &[F32X4], &[I16X8]),
994                 (Opcode::VhighBits, &[F64X2], &[I16X8]),
995                 (Opcode::VhighBits, &[I8X16], &[I32X4]),
996                 (Opcode::VhighBits, &[I16X8], &[I32X4]),
997                 (Opcode::VhighBits, &[I32X4], &[I32X4]),
998                 (Opcode::VhighBits, &[I64X2], &[I32X4]),
999                 (Opcode::VhighBits, &[F32X4], &[I32X4]),
1000                 (Opcode::VhighBits, &[F64X2], &[I32X4]),
1001                 (Opcode::VhighBits, &[I8X16], &[I64X2]),
1002                 (Opcode::VhighBits, &[I16X8], &[I64X2]),
1003                 (Opcode::VhighBits, &[I32X4], &[I64X2]),
1004                 (Opcode::VhighBits, &[I64X2], &[I64X2]),
1005                 (Opcode::VhighBits, &[F32X4], &[I64X2]),
1006                 (Opcode::VhighBits, &[F64X2], &[I64X2]),
1007                 (Opcode::Ineg, &[I8X16], &[I8X16]),
1008                 (Opcode::Ineg, &[I16X8], &[I16X8]),
1009                 (Opcode::Ineg, &[I32X4], &[I32X4]),
1010                 (Opcode::Ineg, &[I64X2], &[I64X2]),
1011                 (Opcode::Umulhi, &[I128, I128], &[I128]),
1012                 (Opcode::Smulhi, &[I128, I128], &[I128]),
1013                 // https://github.com/bytecodealliance/wasmtime/issues/6073
1014                 (Opcode::Iconcat, &[I32, I32], &[I64]),
1015                 (Opcode::Iconcat, &[I16, I16], &[I32]),
1016                 (Opcode::Iconcat, &[I8, I8], &[I16]),
1017                 // https://github.com/bytecodealliance/wasmtime/issues/6073
1018                 (Opcode::Isplit, &[I64], &[I32, I32]),
1019                 (Opcode::Isplit, &[I32], &[I16, I16]),
1020                 (Opcode::Isplit, &[I16], &[I8, I8]),
1021                 (Opcode::Rotl, &[I8X16, I8], &[I8X16]),
1022                 (Opcode::Rotl, &[I8X16, I16], &[I8X16]),
1023                 (Opcode::Rotl, &[I8X16, I32], &[I8X16]),
1024                 (Opcode::Rotl, &[I8X16, I64], &[I8X16]),
1025                 (Opcode::Rotl, &[I8X16, I128], &[I8X16]),
1026                 (Opcode::Rotl, &[I16X8, I8], &[I16X8]),
1027                 (Opcode::Rotl, &[I16X8, I16], &[I16X8]),
1028                 (Opcode::Rotl, &[I16X8, I32], &[I16X8]),
1029                 (Opcode::Rotl, &[I16X8, I64], &[I16X8]),
1030                 (Opcode::Rotl, &[I16X8, I128], &[I16X8]),
1031                 (Opcode::Rotl, &[I32X4, I8], &[I32X4]),
1032                 (Opcode::Rotl, &[I32X4, I16], &[I32X4]),
1033                 (Opcode::Rotl, &[I32X4, I32], &[I32X4]),
1034                 (Opcode::Rotl, &[I32X4, I64], &[I32X4]),
1035                 (Opcode::Rotl, &[I32X4, I128], &[I32X4]),
1036                 (Opcode::Rotl, &[I64X2, I8], &[I64X2]),
1037                 (Opcode::Rotl, &[I64X2, I16], &[I64X2]),
1038                 (Opcode::Rotl, &[I64X2, I32], &[I64X2]),
1039                 (Opcode::Rotl, &[I64X2, I64], &[I64X2]),
1040                 (Opcode::Rotl, &[I64X2, I128], &[I64X2]),
1041                 (Opcode::Rotr, &[I8X16, I8], &[I8X16]),
1042                 (Opcode::Rotr, &[I8X16, I16], &[I8X16]),
1043                 (Opcode::Rotr, &[I8X16, I32], &[I8X16]),
1044                 (Opcode::Rotr, &[I8X16, I64], &[I8X16]),
1045                 (Opcode::Rotr, &[I8X16, I128], &[I8X16]),
1046                 (Opcode::Rotr, &[I16X8, I8], &[I16X8]),
1047                 (Opcode::Rotr, &[I16X8, I16], &[I16X8]),
1048                 (Opcode::Rotr, &[I16X8, I32], &[I16X8]),
1049                 (Opcode::Rotr, &[I16X8, I64], &[I16X8]),
1050                 (Opcode::Rotr, &[I16X8, I128], &[I16X8]),
1051                 (Opcode::Rotr, &[I32X4, I8], &[I32X4]),
1052                 (Opcode::Rotr, &[I32X4, I16], &[I32X4]),
1053                 (Opcode::Rotr, &[I32X4, I32], &[I32X4]),
1054                 (Opcode::Rotr, &[I32X4, I64], &[I32X4]),
1055                 (Opcode::Rotr, &[I32X4, I128], &[I32X4]),
1056                 (Opcode::Rotr, &[I64X2, I8], &[I64X2]),
1057                 (Opcode::Rotr, &[I64X2, I16], &[I64X2]),
1058                 (Opcode::Rotr, &[I64X2, I32], &[I64X2]),
1059                 (Opcode::Rotr, &[I64X2, I64], &[I64X2]),
1060                 (Opcode::Rotr, &[I64X2, I128], &[I64X2]),
1061                 (Opcode::Ishl, &[I8X16, I8], &[I8X16]),
1062                 (Opcode::Ishl, &[I8X16, I16], &[I8X16]),
1063                 (Opcode::Ishl, &[I8X16, I32], &[I8X16]),
1064                 (Opcode::Ishl, &[I8X16, I64], &[I8X16]),
1065                 (Opcode::Ishl, &[I8X16, I128], &[I8X16]),
1066                 (Opcode::Ishl, &[I16X8, I8], &[I16X8]),
1067                 (Opcode::Ishl, &[I16X8, I16], &[I16X8]),
1068                 (Opcode::Ishl, &[I16X8, I32], &[I16X8]),
1069                 (Opcode::Ishl, &[I16X8, I64], &[I16X8]),
1070                 (Opcode::Ishl, &[I16X8, I128], &[I16X8]),
1071                 (Opcode::Ishl, &[I32X4, I8], &[I32X4]),
1072                 (Opcode::Ishl, &[I32X4, I16], &[I32X4]),
1073                 (Opcode::Ishl, &[I32X4, I32], &[I32X4]),
1074                 (Opcode::Ishl, &[I32X4, I64], &[I32X4]),
1075                 (Opcode::Ishl, &[I32X4, I128], &[I32X4]),
1076                 (Opcode::Ishl, &[I64X2, I8], &[I64X2]),
1077                 (Opcode::Ishl, &[I64X2, I16], &[I64X2]),
1078                 (Opcode::Ishl, &[I64X2, I32], &[I64X2]),
1079                 (Opcode::Ishl, &[I64X2, I64], &[I64X2]),
1080                 (Opcode::Ishl, &[I64X2, I128], &[I64X2]),
1081                 (Opcode::Ushr, &[I8X16, I8], &[I8X16]),
1082                 (Opcode::Ushr, &[I8X16, I16], &[I8X16]),
1083                 (Opcode::Ushr, &[I8X16, I32], &[I8X16]),
1084                 (Opcode::Ushr, &[I8X16, I64], &[I8X16]),
1085                 (Opcode::Ushr, &[I8X16, I128], &[I8X16]),
1086                 (Opcode::Ushr, &[I16X8, I8], &[I16X8]),
1087                 (Opcode::Ushr, &[I16X8, I16], &[I16X8]),
1088                 (Opcode::Ushr, &[I16X8, I32], &[I16X8]),
1089                 (Opcode::Ushr, &[I16X8, I64], &[I16X8]),
1090                 (Opcode::Ushr, &[I16X8, I128], &[I16X8]),
1091                 (Opcode::Ushr, &[I32X4, I8], &[I32X4]),
1092                 (Opcode::Ushr, &[I32X4, I16], &[I32X4]),
1093                 (Opcode::Ushr, &[I32X4, I32], &[I32X4]),
1094                 (Opcode::Ushr, &[I32X4, I64], &[I32X4]),
1095                 (Opcode::Ushr, &[I32X4, I128], &[I32X4]),
1096                 (Opcode::Ushr, &[I64X2, I8], &[I64X2]),
1097                 (Opcode::Ushr, &[I64X2, I16], &[I64X2]),
1098                 (Opcode::Ushr, &[I64X2, I32], &[I64X2]),
1099                 (Opcode::Ushr, &[I64X2, I64], &[I64X2]),
1100                 (Opcode::Ushr, &[I64X2, I128], &[I64X2]),
1101                 (Opcode::Sshr, &[I8X16, I8], &[I8X16]),
1102                 (Opcode::Sshr, &[I8X16, I16], &[I8X16]),
1103                 (Opcode::Sshr, &[I8X16, I32], &[I8X16]),
1104                 (Opcode::Sshr, &[I8X16, I64], &[I8X16]),
1105                 (Opcode::Sshr, &[I8X16, I128], &[I8X16]),
1106                 (Opcode::Sshr, &[I16X8, I8], &[I16X8]),
1107                 (Opcode::Sshr, &[I16X8, I16], &[I16X8]),
1108                 (Opcode::Sshr, &[I16X8, I32], &[I16X8]),
1109                 (Opcode::Sshr, &[I16X8, I64], &[I16X8]),
1110                 (Opcode::Sshr, &[I16X8, I128], &[I16X8]),
1111                 (Opcode::Sshr, &[I32X4, I8], &[I32X4]),
1112                 (Opcode::Sshr, &[I32X4, I16], &[I32X4]),
1113                 (Opcode::Sshr, &[I32X4, I32], &[I32X4]),
1114                 (Opcode::Sshr, &[I32X4, I64], &[I32X4]),
1115                 (Opcode::Sshr, &[I32X4, I128], &[I32X4]),
1116                 (Opcode::Sshr, &[I64X2, I8], &[I64X2]),
1117                 (Opcode::Sshr, &[I64X2, I16], &[I64X2]),
1118                 (Opcode::Sshr, &[I64X2, I32], &[I64X2]),
1119                 (Opcode::Sshr, &[I64X2, I64], &[I64X2]),
1120                 (Opcode::Sshr, &[I64X2, I128], &[I64X2]),
1121                 (Opcode::Fmin, &[F32X4, F32X4], &[F32X4]),
1122                 (Opcode::Fmin, &[F64X2, F64X2], &[F64X2]),
1123                 (Opcode::FminPseudo, &[F32X4, F32X4], &[F32X4]),
1124                 (Opcode::FminPseudo, &[F64X2, F64X2], &[F64X2]),
1125                 (Opcode::Fmax, &[F32X4, F32X4], &[F32X4]),
1126                 (Opcode::Fmax, &[F64X2, F64X2], &[F64X2]),
1127                 (Opcode::FmaxPseudo, &[F32X4, F32X4], &[F32X4]),
1128                 (Opcode::FmaxPseudo, &[F64X2, F64X2], &[F64X2]),
1129                 (Opcode::Bitcast, &[I8], &[I8]),
1130                 (Opcode::Bitcast, &[I16], &[I8]),
1131                 (Opcode::Bitcast, &[I32], &[I8]),
1132                 (Opcode::Bitcast, &[I64], &[I8]),
1133                 (Opcode::Bitcast, &[I128], &[I8]),
1134                 (Opcode::Bitcast, &[F32], &[I8]),
1135                 (Opcode::Bitcast, &[F64], &[I8]),
1136                 (Opcode::Bitcast, &[I8X16], &[I8]),
1137                 (Opcode::Bitcast, &[I16X8], &[I8]),
1138                 (Opcode::Bitcast, &[I32X4], &[I8]),
1139                 (Opcode::Bitcast, &[I64X2], &[I8]),
1140                 (Opcode::Bitcast, &[F32X4], &[I8]),
1141                 (Opcode::Bitcast, &[F64X2], &[I8]),
1142                 (Opcode::Bitcast, &[I8], &[I16]),
1143                 (Opcode::Bitcast, &[I16], &[I16]),
1144                 (Opcode::Bitcast, &[I32], &[I16]),
1145                 (Opcode::Bitcast, &[I64], &[I16]),
1146                 (Opcode::Bitcast, &[I128], &[I16]),
1147                 (Opcode::Bitcast, &[F32], &[I16]),
1148                 (Opcode::Bitcast, &[F64], &[I16]),
1149                 (Opcode::Bitcast, &[I8X16], &[I16]),
1150                 (Opcode::Bitcast, &[I16X8], &[I16]),
1151                 (Opcode::Bitcast, &[I32X4], &[I16]),
1152                 (Opcode::Bitcast, &[I64X2], &[I16]),
1153                 (Opcode::Bitcast, &[F32X4], &[I16]),
1154                 (Opcode::Bitcast, &[F64X2], &[I16]),
1155                 (Opcode::Bitcast, &[I8], &[I32]),
1156                 (Opcode::Bitcast, &[I16], &[I32]),
1157                 (Opcode::Bitcast, &[I32], &[I32]),
1158                 (Opcode::Bitcast, &[I64], &[I32]),
1159                 (Opcode::Bitcast, &[I128], &[I32]),
1160                 (Opcode::Bitcast, &[F64], &[I32]),
1161                 (Opcode::Bitcast, &[I8X16], &[I32]),
1162                 (Opcode::Bitcast, &[I16X8], &[I32]),
1163                 (Opcode::Bitcast, &[I32X4], &[I32]),
1164                 (Opcode::Bitcast, &[I64X2], &[I32]),
1165                 (Opcode::Bitcast, &[F32X4], &[I32]),
1166                 (Opcode::Bitcast, &[F64X2], &[I32]),
1167                 (Opcode::Bitcast, &[I8], &[I64]),
1168                 (Opcode::Bitcast, &[I16], &[I64]),
1169                 (Opcode::Bitcast, &[I32], &[I64]),
1170                 (Opcode::Bitcast, &[I64], &[I64]),
1171                 (Opcode::Bitcast, &[I128], &[I64]),
1172                 (Opcode::Bitcast, &[F32], &[I64]),
1173                 (Opcode::Bitcast, &[I8X16], &[I64]),
1174                 (Opcode::Bitcast, &[I16X8], &[I64]),
1175                 (Opcode::Bitcast, &[I32X4], &[I64]),
1176                 (Opcode::Bitcast, &[I64X2], &[I64]),
1177                 (Opcode::Bitcast, &[F32X4], &[I64]),
1178                 (Opcode::Bitcast, &[F64X2], &[I64]),
1179                 (Opcode::Bitcast, &[I8], &[I128]),
1180                 (Opcode::Bitcast, &[I16], &[I128]),
1181                 (Opcode::Bitcast, &[I32], &[I128]),
1182                 (Opcode::Bitcast, &[I64], &[I128]),
1183                 (Opcode::Bitcast, &[I128], &[I128]),
1184                 (Opcode::Bitcast, &[F32], &[I128]),
1185                 (Opcode::Bitcast, &[F64], &[I128]),
1186                 (Opcode::Bitcast, &[I8X16], &[I128]),
1187                 (Opcode::Bitcast, &[I16X8], &[I128]),
1188                 (Opcode::Bitcast, &[I32X4], &[I128]),
1189                 (Opcode::Bitcast, &[I64X2], &[I128]),
1190                 (Opcode::Bitcast, &[F32X4], &[I128]),
1191                 (Opcode::Bitcast, &[F64X2], &[I128]),
1192                 (Opcode::Bitcast, &[I8], &[F32]),
1193                 (Opcode::Bitcast, &[I16], &[F32]),
1194                 (Opcode::Bitcast, &[I64], &[F32]),
1195                 (Opcode::Bitcast, &[I128], &[F32]),
1196                 (Opcode::Bitcast, &[F32], &[F32]),
1197                 (Opcode::Bitcast, &[F64], &[F32]),
1198                 (Opcode::Bitcast, &[I8X16], &[F32]),
1199                 (Opcode::Bitcast, &[I16X8], &[F32]),
1200                 (Opcode::Bitcast, &[I32X4], &[F32]),
1201                 (Opcode::Bitcast, &[I64X2], &[F32]),
1202                 (Opcode::Bitcast, &[F32X4], &[F32]),
1203                 (Opcode::Bitcast, &[F64X2], &[F32]),
1204                 (Opcode::Bitcast, &[I8], &[F64]),
1205                 (Opcode::Bitcast, &[I16], &[F64]),
1206                 (Opcode::Bitcast, &[I32], &[F64]),
1207                 (Opcode::Bitcast, &[I128], &[F64]),
1208                 (Opcode::Bitcast, &[F32], &[F64]),
1209                 (Opcode::Bitcast, &[F64], &[F64]),
1210                 (Opcode::Bitcast, &[I8X16], &[F64]),
1211                 (Opcode::Bitcast, &[I16X8], &[F64]),
1212                 (Opcode::Bitcast, &[I32X4], &[F64]),
1213                 (Opcode::Bitcast, &[I64X2], &[F64]),
1214                 (Opcode::Bitcast, &[F32X4], &[F64]),
1215                 (Opcode::Bitcast, &[F64X2], &[F64]),
1216                 (Opcode::Bitcast, &[I8], &[I8X16]),
1217                 (Opcode::Bitcast, &[I16], &[I8X16]),
1218                 (Opcode::Bitcast, &[I32], &[I8X16]),
1219                 (Opcode::Bitcast, &[I64], &[I8X16]),
1220                 (Opcode::Bitcast, &[I128], &[I8X16]),
1221                 (Opcode::Bitcast, &[F32], &[I8X16]),
1222                 (Opcode::Bitcast, &[F64], &[I8X16]),
1223                 (Opcode::Bitcast, &[I8X16], &[I8X16]),
1224                 (Opcode::Bitcast, &[I16X8], &[I8X16]),
1225                 (Opcode::Bitcast, &[I32X4], &[I8X16]),
1226                 (Opcode::Bitcast, &[I64X2], &[I8X16]),
1227                 (Opcode::Bitcast, &[F32X4], &[I8X16]),
1228                 (Opcode::Bitcast, &[F64X2], &[I8X16]),
1229                 (Opcode::Bitcast, &[I8], &[I16X8]),
1230                 (Opcode::Bitcast, &[I16], &[I16X8]),
1231                 (Opcode::Bitcast, &[I32], &[I16X8]),
1232                 (Opcode::Bitcast, &[I64], &[I16X8]),
1233                 (Opcode::Bitcast, &[I128], &[I16X8]),
1234                 (Opcode::Bitcast, &[F32], &[I16X8]),
1235                 (Opcode::Bitcast, &[F64], &[I16X8]),
1236                 (Opcode::Bitcast, &[I8X16], &[I16X8]),
1237                 (Opcode::Bitcast, &[I16X8], &[I16X8]),
1238                 (Opcode::Bitcast, &[I32X4], &[I16X8]),
1239                 (Opcode::Bitcast, &[I64X2], &[I16X8]),
1240                 (Opcode::Bitcast, &[F32X4], &[I16X8]),
1241                 (Opcode::Bitcast, &[F64X2], &[I16X8]),
1242                 (Opcode::Bitcast, &[I8], &[I32X4]),
1243                 (Opcode::Bitcast, &[I16], &[I32X4]),
1244                 (Opcode::Bitcast, &[I32], &[I32X4]),
1245                 (Opcode::Bitcast, &[I64], &[I32X4]),
1246                 (Opcode::Bitcast, &[I128], &[I32X4]),
1247                 (Opcode::Bitcast, &[F32], &[I32X4]),
1248                 (Opcode::Bitcast, &[F64], &[I32X4]),
1249                 (Opcode::Bitcast, &[I8X16], &[I32X4]),
1250                 (Opcode::Bitcast, &[I16X8], &[I32X4]),
1251                 (Opcode::Bitcast, &[I32X4], &[I32X4]),
1252                 (Opcode::Bitcast, &[I64X2], &[I32X4]),
1253                 (Opcode::Bitcast, &[F32X4], &[I32X4]),
1254                 (Opcode::Bitcast, &[F64X2], &[I32X4]),
1255                 (Opcode::Bitcast, &[I8], &[I64X2]),
1256                 (Opcode::Bitcast, &[I16], &[I64X2]),
1257                 (Opcode::Bitcast, &[I32], &[I64X2]),
1258                 (Opcode::Bitcast, &[I64], &[I64X2]),
1259                 (Opcode::Bitcast, &[I128], &[I64X2]),
1260                 (Opcode::Bitcast, &[F32], &[I64X2]),
1261                 (Opcode::Bitcast, &[F64], &[I64X2]),
1262                 (Opcode::Bitcast, &[I8X16], &[I64X2]),
1263                 (Opcode::Bitcast, &[I16X8], &[I64X2]),
1264                 (Opcode::Bitcast, &[I32X4], &[I64X2]),
1265                 (Opcode::Bitcast, &[I64X2], &[I64X2]),
1266                 (Opcode::Bitcast, &[F32X4], &[I64X2]),
1267                 (Opcode::Bitcast, &[F64X2], &[I64X2]),
1268                 (Opcode::Bitcast, &[I8], &[F32X4]),
1269                 (Opcode::Bitcast, &[I16], &[F32X4]),
1270                 (Opcode::Bitcast, &[I32], &[F32X4]),
1271                 (Opcode::Bitcast, &[I64], &[F32X4]),
1272                 (Opcode::Bitcast, &[I128], &[F32X4]),
1273                 (Opcode::Bitcast, &[F32], &[F32X4]),
1274                 (Opcode::Bitcast, &[F64], &[F32X4]),
1275                 (Opcode::Bitcast, &[I8X16], &[F32X4]),
1276                 (Opcode::Bitcast, &[I16X8], &[F32X4]),
1277                 (Opcode::Bitcast, &[I32X4], &[F32X4]),
1278                 (Opcode::Bitcast, &[I64X2], &[F32X4]),
1279                 (Opcode::Bitcast, &[F32X4], &[F32X4]),
1280                 (Opcode::Bitcast, &[F64X2], &[F32X4]),
1281                 (Opcode::Bitcast, &[I8], &[F64X2]),
1282                 (Opcode::Bitcast, &[I16], &[F64X2]),
1283                 (Opcode::Bitcast, &[I32], &[F64X2]),
1284                 (Opcode::Bitcast, &[I64], &[F64X2]),
1285                 (Opcode::Bitcast, &[I128], &[F64X2]),
1286                 (Opcode::Bitcast, &[F32], &[F64X2]),
1287                 (Opcode::Bitcast, &[F64], &[F64X2]),
1288                 (Opcode::Bitcast, &[I8X16], &[F64X2]),
1289                 (Opcode::Bitcast, &[I16X8], &[F64X2]),
1290                 (Opcode::Bitcast, &[I32X4], &[F64X2]),
1291                 (Opcode::Bitcast, &[I64X2], &[F64X2]),
1292                 (Opcode::Bitcast, &[F32X4], &[F64X2]),
1293                 (Opcode::Bitcast, &[F64X2], &[F64X2]),
1294                 (Opcode::FcvtToUintSat, &[F32X4], &[I8]),
1295                 (Opcode::FcvtToUintSat, &[F64X2], &[I8]),
1296                 (Opcode::FcvtToUintSat, &[F32X4], &[I16]),
1297                 (Opcode::FcvtToUintSat, &[F64X2], &[I16]),
1298                 (Opcode::FcvtToUintSat, &[F32X4], &[I32]),
1299                 (Opcode::FcvtToUintSat, &[F64X2], &[I32]),
1300                 (Opcode::FcvtToUintSat, &[F32X4], &[I64]),
1301                 (Opcode::FcvtToUintSat, &[F64X2], &[I64]),
1302                 (Opcode::FcvtToUintSat, &[F32X4], &[I128]),
1303                 (Opcode::FcvtToUintSat, &[F64X2], &[I128]),
1304                 (Opcode::FcvtToUintSat, &[F32], &[I8X16]),
1305                 (Opcode::FcvtToUintSat, &[F64], &[I8X16]),
1306                 (Opcode::FcvtToUintSat, &[F32X4], &[I8X16]),
1307                 (Opcode::FcvtToUintSat, &[F64X2], &[I8X16]),
1308                 (Opcode::FcvtToUintSat, &[F32], &[I16X8]),
1309                 (Opcode::FcvtToUintSat, &[F64], &[I16X8]),
1310                 (Opcode::FcvtToUintSat, &[F32X4], &[I16X8]),
1311                 (Opcode::FcvtToUintSat, &[F64X2], &[I16X8]),
1312                 (Opcode::FcvtToUintSat, &[F32], &[I32X4]),
1313                 (Opcode::FcvtToUintSat, &[F64], &[I32X4]),
1314                 (Opcode::FcvtToUintSat, &[F64X2], &[I32X4]),
1315                 (Opcode::FcvtToUintSat, &[F32], &[I64X2]),
1316                 (Opcode::FcvtToUintSat, &[F64], &[I64X2]),
1317                 (Opcode::FcvtToUintSat, &[F32X4], &[I64X2]),
1318                 (Opcode::FcvtToSintSat, &[F32X4], &[I8]),
1319                 (Opcode::FcvtToSintSat, &[F64X2], &[I8]),
1320                 (Opcode::FcvtToSintSat, &[F32X4], &[I16]),
1321                 (Opcode::FcvtToSintSat, &[F64X2], &[I16]),
1322                 (Opcode::FcvtToSintSat, &[F32X4], &[I32]),
1323                 (Opcode::FcvtToSintSat, &[F64X2], &[I32]),
1324                 (Opcode::FcvtToSintSat, &[F32X4], &[I64]),
1325                 (Opcode::FcvtToSintSat, &[F64X2], &[I64]),
1326                 (Opcode::FcvtToSintSat, &[F32X4], &[I128]),
1327                 (Opcode::FcvtToSintSat, &[F64X2], &[I128]),
1328                 (Opcode::FcvtToSintSat, &[F32], &[I8X16]),
1329                 (Opcode::FcvtToSintSat, &[F64], &[I8X16]),
1330                 (Opcode::FcvtToSintSat, &[F32X4], &[I8X16]),
1331                 (Opcode::FcvtToSintSat, &[F64X2], &[I8X16]),
1332                 (Opcode::FcvtToSintSat, &[F32], &[I16X8]),
1333                 (Opcode::FcvtToSintSat, &[F64], &[I16X8]),
1334                 (Opcode::FcvtToSintSat, &[F32X4], &[I16X8]),
1335                 (Opcode::FcvtToSintSat, &[F64X2], &[I16X8]),
1336                 (Opcode::FcvtToSintSat, &[F32], &[I32X4]),
1337                 (Opcode::FcvtToSintSat, &[F64], &[I32X4]),
1338                 (Opcode::FcvtToSintSat, &[F64X2], &[I32X4]),
1339                 (Opcode::FcvtToSintSat, &[F32], &[I64X2]),
1340                 (Opcode::FcvtToSintSat, &[F64], &[I64X2]),
1341                 (Opcode::FcvtToSintSat, &[F32X4], &[I64X2]),
1342                 (Opcode::FcvtFromUint, &[I8X16], &[F32]),
1343                 (Opcode::FcvtFromUint, &[I16X8], &[F32]),
1344                 (Opcode::FcvtFromUint, &[I32X4], &[F32]),
1345                 (Opcode::FcvtFromUint, &[I64X2], &[F32]),
1346                 (Opcode::FcvtFromUint, &[I8X16], &[F64]),
1347                 (Opcode::FcvtFromUint, &[I16X8], &[F64]),
1348                 (Opcode::FcvtFromUint, &[I32X4], &[F64]),
1349                 (Opcode::FcvtFromUint, &[I64X2], &[F64]),
1350                 (Opcode::FcvtFromUint, &[I8], &[F32X4]),
1351                 (Opcode::FcvtFromUint, &[I16], &[F32X4]),
1352                 (Opcode::FcvtFromUint, &[I32], &[F32X4]),
1353                 (Opcode::FcvtFromUint, &[I64], &[F32X4]),
1354                 (Opcode::FcvtFromUint, &[I128], &[F32X4]),
1355                 (Opcode::FcvtFromUint, &[I8X16], &[F32X4]),
1356                 (Opcode::FcvtFromUint, &[I16X8], &[F32X4]),
1357                 (Opcode::FcvtFromUint, &[I64X2], &[F32X4]),
1358                 (Opcode::FcvtFromUint, &[I8], &[F64X2]),
1359                 (Opcode::FcvtFromUint, &[I16], &[F64X2]),
1360                 (Opcode::FcvtFromUint, &[I32], &[F64X2]),
1361                 (Opcode::FcvtFromUint, &[I64], &[F64X2]),
1362                 (Opcode::FcvtFromUint, &[I128], &[F64X2]),
1363                 (Opcode::FcvtFromUint, &[I8X16], &[F64X2]),
1364                 (Opcode::FcvtFromUint, &[I16X8], &[F64X2]),
1365                 (Opcode::FcvtFromUint, &[I32X4], &[F64X2]),
1366                 (Opcode::FcvtFromSint, &[I8X16], &[F32]),
1367                 (Opcode::FcvtFromSint, &[I16X8], &[F32]),
1368                 (Opcode::FcvtFromSint, &[I32X4], &[F32]),
1369                 (Opcode::FcvtFromSint, &[I64X2], &[F32]),
1370                 (Opcode::FcvtFromSint, &[I8X16], &[F64]),
1371                 (Opcode::FcvtFromSint, &[I16X8], &[F64]),
1372                 (Opcode::FcvtFromSint, &[I32X4], &[F64]),
1373                 (Opcode::FcvtFromSint, &[I64X2], &[F64]),
1374                 (Opcode::FcvtFromSint, &[I8], &[F32X4]),
1375                 (Opcode::FcvtFromSint, &[I16], &[F32X4]),
1376                 (Opcode::FcvtFromSint, &[I32], &[F32X4]),
1377                 (Opcode::FcvtFromSint, &[I64], &[F32X4]),
1378                 (Opcode::FcvtFromSint, &[I128], &[F32X4]),
1379                 (Opcode::FcvtFromSint, &[I8X16], &[F32X4]),
1380                 (Opcode::FcvtFromSint, &[I16X8], &[F32X4]),
1381                 (Opcode::FcvtFromSint, &[I64X2], &[F32X4]),
1382                 (Opcode::FcvtFromSint, &[I8], &[F64X2]),
1383                 (Opcode::FcvtFromSint, &[I16], &[F64X2]),
1384                 (Opcode::FcvtFromSint, &[I32], &[F64X2]),
1385                 (Opcode::FcvtFromSint, &[I64], &[F64X2]),
1386                 (Opcode::FcvtFromSint, &[I128], &[F64X2]),
1387                 (Opcode::FcvtFromSint, &[I8X16], &[F64X2]),
1388                 (Opcode::FcvtFromSint, &[I16X8], &[F64X2]),
1389                 (Opcode::FcvtFromSint, &[I32X4], &[F64X2]),
1390                 (Opcode::FcvtLowFromSint, &[I8], &[F32]),
1391                 (Opcode::FcvtLowFromSint, &[I16], &[F32]),
1392                 (Opcode::FcvtLowFromSint, &[I32], &[F32]),
1393                 (Opcode::FcvtLowFromSint, &[I64], &[F32]),
1394                 (Opcode::FcvtLowFromSint, &[I128], &[F32]),
1395                 (Opcode::FcvtLowFromSint, &[I8X16], &[F32]),
1396                 (Opcode::FcvtLowFromSint, &[I16X8], &[F32]),
1397                 (Opcode::FcvtLowFromSint, &[I32X4], &[F32]),
1398                 (Opcode::FcvtLowFromSint, &[I64X2], &[F32]),
1399                 (Opcode::FcvtLowFromSint, &[I8], &[F64]),
1400                 (Opcode::FcvtLowFromSint, &[I16], &[F64]),
1401                 (Opcode::FcvtLowFromSint, &[I32], &[F64]),
1402                 (Opcode::FcvtLowFromSint, &[I64], &[F64]),
1403                 (Opcode::FcvtLowFromSint, &[I128], &[F64]),
1404                 (Opcode::FcvtLowFromSint, &[I8X16], &[F64]),
1405                 (Opcode::FcvtLowFromSint, &[I16X8], &[F64]),
1406                 (Opcode::FcvtLowFromSint, &[I32X4], &[F64]),
1407                 (Opcode::FcvtLowFromSint, &[I64X2], &[F64]),
1408                 (Opcode::FcvtLowFromSint, &[I8], &[F32X4]),
1409                 (Opcode::FcvtLowFromSint, &[I16], &[F32X4]),
1410                 (Opcode::FcvtLowFromSint, &[I32], &[F32X4]),
1411                 (Opcode::FcvtLowFromSint, &[I64], &[F32X4]),
1412                 (Opcode::FcvtLowFromSint, &[I128], &[F32X4]),
1413                 (Opcode::FcvtLowFromSint, &[I8X16], &[F32X4]),
1414                 (Opcode::FcvtLowFromSint, &[I16X8], &[F32X4]),
1415                 (Opcode::FcvtLowFromSint, &[I32X4], &[F32X4]),
1416                 (Opcode::FcvtLowFromSint, &[I64X2], &[F32X4]),
1417                 (Opcode::FcvtLowFromSint, &[I8], &[F64X2]),
1418                 (Opcode::FcvtLowFromSint, &[I16], &[F64X2]),
1419                 (Opcode::FcvtLowFromSint, &[I32], &[F64X2]),
1420                 (Opcode::FcvtLowFromSint, &[I64], &[F64X2]),
1421                 (Opcode::FcvtLowFromSint, &[I128], &[F64X2]),
1422                 (Opcode::FcvtLowFromSint, &[I8X16], &[F64X2]),
1423                 (Opcode::FcvtLowFromSint, &[I16X8], &[F64X2]),
1424                 (Opcode::FcvtLowFromSint, &[I64X2], &[F64X2]),
1425             )
1426         })
1427         .collect()
1428 });
1429 
1430 fn inserter_for_format(fmt: InstructionFormat) -> OpcodeInserter {
1431     match fmt {
1432         InstructionFormat::AtomicCas => insert_atomic_cas,
1433         InstructionFormat::AtomicRmw => insert_atomic_rmw,
1434         InstructionFormat::Binary => insert_opcode,
1435         InstructionFormat::BinaryImm64 => todo!(),
1436         InstructionFormat::BinaryImm8 => insert_ins_ext_lane,
1437         InstructionFormat::Call => insert_call,
1438         InstructionFormat::CallIndirect => insert_call,
1439         InstructionFormat::CondTrap => todo!(),
1440         InstructionFormat::DynamicStackLoad => todo!(),
1441         InstructionFormat::DynamicStackStore => todo!(),
1442         InstructionFormat::FloatCompare => insert_cmp,
1443         InstructionFormat::FuncAddr => todo!(),
1444         InstructionFormat::IntAddTrap => todo!(),
1445         InstructionFormat::IntCompare => insert_cmp,
1446         InstructionFormat::IntCompareImm => todo!(),
1447         InstructionFormat::Load => insert_load_store,
1448         InstructionFormat::LoadNoOffset => insert_load_store,
1449         InstructionFormat::NullAry => insert_opcode,
1450         InstructionFormat::Shuffle => insert_shuffle,
1451         InstructionFormat::StackLoad => insert_stack_load,
1452         InstructionFormat::StackStore => insert_stack_store,
1453         InstructionFormat::Store => insert_load_store,
1454         InstructionFormat::StoreNoOffset => insert_load_store,
1455         InstructionFormat::TableAddr => todo!(),
1456         InstructionFormat::Ternary => insert_opcode,
1457         InstructionFormat::TernaryImm8 => insert_ins_ext_lane,
1458         InstructionFormat::Trap => todo!(),
1459         InstructionFormat::Unary => insert_opcode,
1460         InstructionFormat::UnaryConst => insert_const,
1461         InstructionFormat::UnaryGlobalValue => todo!(),
1462         InstructionFormat::UnaryIeee32 => insert_const,
1463         InstructionFormat::UnaryIeee64 => insert_const,
1464         InstructionFormat::UnaryImm => insert_const,
1465 
1466         InstructionFormat::BranchTable
1467         | InstructionFormat::Brif
1468         | InstructionFormat::Jump
1469         | InstructionFormat::MultiAry => {
1470             panic!(
1471                 "Control-flow instructions should be handled by 'insert_terminator': {:?}",
1472                 fmt
1473             )
1474         }
1475     }
1476 }
1477 
1478 pub struct FunctionGenerator<'r, 'data>
1479 where
1480     'data: 'r,
1481 {
1482     u: &'r mut Unstructured<'data>,
1483     config: &'r Config,
1484     resources: Resources,
1485     target_triple: Triple,
1486     name: UserFuncName,
1487     signature: Signature,
1488 }
1489 
1490 #[derive(Debug, Clone)]
1491 enum BlockTerminator {
1492     Return,
1493     Jump(Block),
1494     Br(Block, Block),
1495     BrTable(Block, Vec<Block>),
1496     Switch(Type, Block, HashMap<u128, Block>),
1497 }
1498 
1499 #[derive(Debug, Clone)]
1500 enum BlockTerminatorKind {
1501     Return,
1502     Jump,
1503     Br,
1504     BrTable,
1505     Switch,
1506 }
1507 
1508 #[derive(Default)]
1509 struct Resources {
1510     vars: HashMap<Type, Vec<Variable>>,
1511     blocks: Vec<(Block, BlockSignature)>,
1512     blocks_without_params: Vec<Block>,
1513     block_terminators: Vec<BlockTerminator>,
1514     func_refs: Vec<(Signature, SigRef, FuncRef)>,
1515     stack_slots: Vec<(StackSlot, StackSize)>,
1516     usercalls: Vec<(UserExternalName, Signature)>,
1517     libcalls: Vec<LibCall>,
1518 }
1519 
1520 impl Resources {
1521     /// Partitions blocks at `block`. Only blocks that can be targeted by branches are considered.
1522     ///
1523     /// The first slice includes all blocks up to and including `block`.
1524     /// The second slice includes all remaining blocks.
1525     fn partition_target_blocks(
1526         &self,
1527         block: Block,
1528     ) -> (&[(Block, BlockSignature)], &[(Block, BlockSignature)]) {
1529         // Blocks are stored in-order and have no gaps, this means that we can simply index them by
1530         // their number. We also need to exclude the entry block since it isn't a valid target.
1531         let target_blocks = &self.blocks[1..];
1532         target_blocks.split_at(block.as_u32() as usize)
1533     }
1534 
1535     /// Returns blocks forward of `block`. Only blocks that can be targeted by branches are considered.
1536     fn forward_blocks(&self, block: Block) -> &[(Block, BlockSignature)] {
1537         let (_, forward_blocks) = self.partition_target_blocks(block);
1538         forward_blocks
1539     }
1540 
1541     /// Generates a slice of `blocks_without_params` ahead of `block`
1542     fn forward_blocks_without_params(&self, block: Block) -> &[Block] {
1543         let partition_point = self.blocks_without_params.partition_point(|b| *b <= block);
1544         &self.blocks_without_params[partition_point..]
1545     }
1546 }
1547 
1548 impl<'r, 'data> FunctionGenerator<'r, 'data>
1549 where
1550     'data: 'r,
1551 {
1552     pub fn new(
1553         u: &'r mut Unstructured<'data>,
1554         config: &'r Config,
1555         target_triple: Triple,
1556         name: UserFuncName,
1557         signature: Signature,
1558         usercalls: Vec<(UserExternalName, Signature)>,
1559         libcalls: Vec<LibCall>,
1560     ) -> Self {
1561         Self {
1562             u,
1563             config,
1564             resources: Resources {
1565                 usercalls,
1566                 libcalls,
1567                 ..Resources::default()
1568             },
1569             target_triple,
1570             name,
1571             signature,
1572         }
1573     }
1574 
1575     /// Generates a random value for config `param`
1576     fn param(&mut self, param: &RangeInclusive<usize>) -> Result<usize> {
1577         Ok(self.u.int_in_range(param.clone())?)
1578     }
1579 
1580     fn system_callconv(&mut self) -> CallConv {
1581         // TODO: This currently only runs on linux, so this is the only choice
1582         // We should improve this once we generate flags and targets
1583         CallConv::SystemV
1584     }
1585 
1586     /// Finds a stack slot with size of at least n bytes
1587     fn stack_slot_with_size(&mut self, n: u32) -> Result<(StackSlot, StackSize)> {
1588         let first = self
1589             .resources
1590             .stack_slots
1591             .partition_point(|&(_slot, size)| size < n);
1592         Ok(*self.u.choose(&self.resources.stack_slots[first..])?)
1593     }
1594 
1595     /// Generates an address that should allow for a store or a load.
1596     ///
1597     /// Addresses aren't generated like other values. They are never stored in variables so that
1598     /// we don't run the risk of returning them from a function, which would make the fuzzer
1599     /// complain since they are different from the interpreter to the backend.
1600     ///
1601     /// `min_size`: Controls the amount of space that the address should have.
1602     ///
1603     /// `aligned`: When passed as true, the resulting address is guaranteed to be aligned
1604     /// on an 8 byte boundary.
1605     ///
1606     /// Returns a valid address and the maximum possible offset that still respects `min_size`.
1607     fn generate_load_store_address(
1608         &mut self,
1609         builder: &mut FunctionBuilder,
1610         min_size: u32,
1611         aligned: bool,
1612     ) -> Result<(Value, u32)> {
1613         // TODO: Currently our only source of addresses is stack_addr, but we
1614         // should add global_value, symbol_value eventually
1615         let (addr, available_size) = {
1616             let (ss, slot_size) = self.stack_slot_with_size(min_size)?;
1617 
1618             // stack_slot_with_size guarantees that slot_size >= min_size
1619             let max_offset = slot_size - min_size;
1620             let offset = if aligned {
1621                 self.u.int_in_range(0..=max_offset / min_size)? * min_size
1622             } else {
1623                 self.u.int_in_range(0..=max_offset)?
1624             };
1625 
1626             let base_addr = builder.ins().stack_addr(I64, ss, offset as i32);
1627             let available_size = slot_size.saturating_sub(offset);
1628             (base_addr, available_size)
1629         };
1630 
1631         // TODO: Insert a bunch of amode opcodes here to modify the address!
1632 
1633         // Now that we have an address and a size, we just choose a random offset to return to the
1634         // caller. Preserving min_size bytes.
1635         let max_offset = available_size.saturating_sub(min_size);
1636         Ok((addr, max_offset))
1637     }
1638 
1639     // Generates an address and memflags for a load or store.
1640     fn generate_address_and_memflags(
1641         &mut self,
1642         builder: &mut FunctionBuilder,
1643         min_size: u32,
1644         is_atomic: bool,
1645     ) -> Result<(Value, MemFlags, Offset32)> {
1646         // Should we generate an aligned address
1647         // Some backends have issues with unaligned atomics.
1648         // AArch64: https://github.com/bytecodealliance/wasmtime/issues/5483
1649         // RISCV: https://github.com/bytecodealliance/wasmtime/issues/5882
1650         let requires_aligned_atomics = matches!(
1651             self.target_triple.architecture,
1652             Architecture::Aarch64(_) | Architecture::Riscv64(_)
1653         );
1654         let aligned = if is_atomic && requires_aligned_atomics {
1655             true
1656         } else if min_size > 8 {
1657             // TODO: We currently can't guarantee that a stack_slot will be aligned on a 16 byte
1658             // boundary. We don't have a way to specify alignment when creating stack slots, and
1659             // cranelift only guarantees 8 byte alignment between stack slots.
1660             // See: https://github.com/bytecodealliance/wasmtime/issues/5922#issuecomment-1457926624
1661             false
1662         } else {
1663             bool::arbitrary(self.u)?
1664         };
1665 
1666         let mut flags = MemFlags::new();
1667         // Even if we picked an aligned address, we can always generate unaligned memflags
1668         if aligned && bool::arbitrary(self.u)? {
1669             flags.set_aligned();
1670         }
1671         // If the address is aligned, then we know it won't trap
1672         if aligned && bool::arbitrary(self.u)? {
1673             flags.set_notrap();
1674         }
1675 
1676         let (address, max_offset) = self.generate_load_store_address(builder, min_size, aligned)?;
1677 
1678         // Pick an offset to pass into the load/store.
1679         let offset = if aligned {
1680             0
1681         } else {
1682             self.u.int_in_range(0..=max_offset)? as i32
1683         }
1684         .into();
1685 
1686         Ok((address, flags, offset))
1687     }
1688 
1689     /// Get a variable of type `ty` from the current function
1690     fn get_variable_of_type(&mut self, ty: Type) -> Result<Variable> {
1691         let opts = self.resources.vars.get(&ty).map_or(&[][..], Vec::as_slice);
1692         let var = self.u.choose(opts)?;
1693         Ok(*var)
1694     }
1695 
1696     /// Generates an instruction(`iconst`/`fconst`/etc...) to introduce a constant value
1697     fn generate_const(&mut self, builder: &mut FunctionBuilder, ty: Type) -> Result<Value> {
1698         Ok(match self.u.datavalue(ty)? {
1699             DataValue::I8(i) => builder.ins().iconst(ty, i as i64),
1700             DataValue::I16(i) => builder.ins().iconst(ty, i as i64),
1701             DataValue::I32(i) => builder.ins().iconst(ty, i as i64),
1702             DataValue::I64(i) => builder.ins().iconst(ty, i as i64),
1703             DataValue::I128(i) => {
1704                 let hi = builder.ins().iconst(I64, (i >> 64) as i64);
1705                 let lo = builder.ins().iconst(I64, i as i64);
1706                 builder.ins().iconcat(lo, hi)
1707             }
1708             DataValue::F32(f) => builder.ins().f32const(f),
1709             DataValue::F64(f) => builder.ins().f64const(f),
1710             DataValue::V128(bytes) => {
1711                 let data = bytes.to_vec().into();
1712                 let handle = builder.func.dfg.constants.insert(data);
1713                 builder.ins().vconst(ty, handle)
1714             }
1715             _ => unimplemented!(),
1716         })
1717     }
1718 
1719     /// Chooses a random block which can be targeted by a jump / branch.
1720     /// This means any block that is not the first block.
1721     fn generate_target_block(&mut self, source_block: Block) -> Result<Block> {
1722         // We try to mostly generate forward branches to avoid generating an excessive amount of
1723         // infinite loops. But they are still important, so give them a small chance of existing.
1724         let (backwards_blocks, forward_blocks) =
1725             self.resources.partition_target_blocks(source_block);
1726         let ratio = self.config.backwards_branch_ratio;
1727         let block_targets = if !backwards_blocks.is_empty() && self.u.ratio(ratio.0, ratio.1)? {
1728             backwards_blocks
1729         } else {
1730             forward_blocks
1731         };
1732         assert!(!block_targets.is_empty());
1733 
1734         let (block, _) = self.u.choose(block_targets)?.clone();
1735         Ok(block)
1736     }
1737 
1738     fn generate_values_for_block(
1739         &mut self,
1740         builder: &mut FunctionBuilder,
1741         block: Block,
1742     ) -> Result<Vec<Value>> {
1743         let (_, sig) = self.resources.blocks[block.as_u32() as usize].clone();
1744         self.generate_values_for_signature(builder, sig.iter().copied())
1745     }
1746 
1747     fn generate_values_for_signature<I: Iterator<Item = Type>>(
1748         &mut self,
1749         builder: &mut FunctionBuilder,
1750         signature: I,
1751     ) -> Result<Vec<Value>> {
1752         signature
1753             .map(|ty| {
1754                 let var = self.get_variable_of_type(ty)?;
1755                 let val = builder.use_var(var);
1756                 Ok(val)
1757             })
1758             .collect()
1759     }
1760 
1761     /// The terminator that we need to insert has already been picked ahead of time
1762     /// we just need to build the instructions for it
1763     fn insert_terminator(
1764         &mut self,
1765         builder: &mut FunctionBuilder,
1766         source_block: Block,
1767     ) -> Result<()> {
1768         let terminator = self.resources.block_terminators[source_block.as_u32() as usize].clone();
1769 
1770         match terminator {
1771             BlockTerminator::Return => {
1772                 let types: Vec<Type> = {
1773                     let rets = &builder.func.signature.returns;
1774                     rets.iter().map(|p| p.value_type).collect()
1775                 };
1776                 let vals = self.generate_values_for_signature(builder, types.into_iter())?;
1777 
1778                 builder.ins().return_(&vals[..]);
1779             }
1780             BlockTerminator::Jump(target) => {
1781                 let args = self.generate_values_for_block(builder, target)?;
1782                 builder.ins().jump(target, &args[..]);
1783             }
1784             BlockTerminator::Br(left, right) => {
1785                 let left_args = self.generate_values_for_block(builder, left)?;
1786                 let right_args = self.generate_values_for_block(builder, right)?;
1787 
1788                 let condbr_types = [I8, I16, I32, I64, I128];
1789                 let _type = *self.u.choose(&condbr_types[..])?;
1790                 let val = builder.use_var(self.get_variable_of_type(_type)?);
1791                 builder
1792                     .ins()
1793                     .brif(val, left, &left_args[..], right, &right_args[..]);
1794             }
1795             BlockTerminator::BrTable(default, targets) => {
1796                 // Create jump tables on demand
1797                 let mut jt = Vec::with_capacity(targets.len());
1798                 for block in targets {
1799                     let args = self.generate_values_for_block(builder, block)?;
1800                     jt.push(builder.func.dfg.block_call(block, &args))
1801                 }
1802 
1803                 let args = self.generate_values_for_block(builder, default)?;
1804                 let jt_data = JumpTableData::new(builder.func.dfg.block_call(default, &args), &jt);
1805                 let jt = builder.create_jump_table(jt_data);
1806 
1807                 // br_table only supports I32
1808                 let val = builder.use_var(self.get_variable_of_type(I32)?);
1809 
1810                 builder.ins().br_table(val, jt);
1811             }
1812             BlockTerminator::Switch(_type, default, entries) => {
1813                 let mut switch = Switch::new();
1814                 for (&entry, &block) in entries.iter() {
1815                     switch.set_entry(entry, block);
1816                 }
1817 
1818                 let switch_val = builder.use_var(self.get_variable_of_type(_type)?);
1819 
1820                 switch.emit(builder, switch_val, default);
1821             }
1822         }
1823 
1824         Ok(())
1825     }
1826 
1827     /// Fills the current block with random instructions
1828     fn generate_instructions(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1829         for _ in 0..self.param(&self.config.instructions_per_block)? {
1830             let (op, args, rets) = self.u.choose(&OPCODE_SIGNATURES)?;
1831 
1832             // We filter out instructions that aren't supported by the target at this point instead
1833             // of building a single vector of valid instructions at the beginning of function
1834             // generation, to avoid invalidating the corpus when instructions are enabled/disabled.
1835             if !valid_for_target(&self.target_triple, *op, &args, &rets) {
1836                 return Err(arbitrary::Error::IncorrectFormat.into());
1837             }
1838 
1839             let inserter = inserter_for_format(op.format());
1840             inserter(self, builder, *op, &args, &rets)?;
1841         }
1842 
1843         Ok(())
1844     }
1845 
1846     fn generate_funcrefs(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1847         let usercalls: Vec<(ExternalName, Signature)> = self
1848             .resources
1849             .usercalls
1850             .iter()
1851             .map(|(name, signature)| {
1852                 let user_func_ref = builder.func.declare_imported_user_function(name.clone());
1853                 let name = ExternalName::User(user_func_ref);
1854                 (name, signature.clone())
1855             })
1856             .collect();
1857 
1858         let lib_callconv = self.system_callconv();
1859         let libcalls: Vec<(ExternalName, Signature)> = self
1860             .resources
1861             .libcalls
1862             .iter()
1863             .map(|libcall| {
1864                 let pointer_type = Type::int_with_byte_size(
1865                     self.target_triple.pointer_width().unwrap().bytes().into(),
1866                 )
1867                 .unwrap();
1868                 let signature = libcall.signature(lib_callconv, pointer_type);
1869                 let name = ExternalName::LibCall(*libcall);
1870                 (name, signature)
1871             })
1872             .collect();
1873 
1874         for (name, signature) in usercalls.into_iter().chain(libcalls) {
1875             let sig_ref = builder.import_signature(signature.clone());
1876             let func_ref = builder.import_function(ExtFuncData {
1877                 name,
1878                 signature: sig_ref,
1879                 colocated: self.u.arbitrary()?,
1880             });
1881 
1882             self.resources
1883                 .func_refs
1884                 .push((signature, sig_ref, func_ref));
1885         }
1886 
1887         Ok(())
1888     }
1889 
1890     fn generate_stack_slots(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1891         for _ in 0..self.param(&self.config.static_stack_slots_per_function)? {
1892             let bytes = self.param(&self.config.static_stack_slot_size)? as u32;
1893             let ss_data = StackSlotData::new(StackSlotKind::ExplicitSlot, bytes);
1894             let slot = builder.create_sized_stack_slot(ss_data);
1895             self.resources.stack_slots.push((slot, bytes));
1896         }
1897 
1898         self.resources
1899             .stack_slots
1900             .sort_unstable_by_key(|&(_slot, bytes)| bytes);
1901 
1902         Ok(())
1903     }
1904 
1905     /// Zero initializes the stack slot by inserting `stack_store`'s.
1906     fn initialize_stack_slots(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1907         let i8_zero = builder.ins().iconst(I8, 0);
1908         let i16_zero = builder.ins().iconst(I16, 0);
1909         let i32_zero = builder.ins().iconst(I32, 0);
1910         let i64_zero = builder.ins().iconst(I64, 0);
1911         let i128_zero = builder.ins().uextend(I128, i64_zero);
1912 
1913         for &(slot, init_size) in self.resources.stack_slots.iter() {
1914             let mut size = init_size;
1915 
1916             // Insert the largest available store for the remaining size.
1917             while size != 0 {
1918                 let offset = (init_size - size) as i32;
1919                 let (val, filled) = match size {
1920                     sz if sz / 16 > 0 => (i128_zero, 16),
1921                     sz if sz / 8 > 0 => (i64_zero, 8),
1922                     sz if sz / 4 > 0 => (i32_zero, 4),
1923                     sz if sz / 2 > 0 => (i16_zero, 2),
1924                     _ => (i8_zero, 1),
1925                 };
1926                 builder.ins().stack_store(val, slot, offset);
1927                 size -= filled;
1928             }
1929         }
1930         Ok(())
1931     }
1932 
1933     /// Creates a random amount of blocks in this function
1934     fn generate_blocks(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1935         let extra_block_count = self.param(&self.config.blocks_per_function)?;
1936 
1937         // We must always have at least one block, so we generate the "extra" blocks and add 1 for
1938         // the entry block.
1939         let block_count = 1 + extra_block_count;
1940 
1941         // Blocks need to be sorted in ascending order
1942         self.resources.blocks = (0..block_count)
1943             .map(|i| {
1944                 let is_entry = i == 0;
1945                 let block = builder.create_block();
1946 
1947                 // Optionally mark blocks that are not the entry block as cold
1948                 if !is_entry {
1949                     if bool::arbitrary(self.u)? {
1950                         builder.set_cold_block(block);
1951                     }
1952                 }
1953 
1954                 // The first block has to have the function signature, but for the rest of them we generate
1955                 // a random signature;
1956                 if is_entry {
1957                     builder.append_block_params_for_function_params(block);
1958                     Ok((
1959                         block,
1960                         self.signature.params.iter().map(|a| a.value_type).collect(),
1961                     ))
1962                 } else {
1963                     let sig = self.generate_block_signature()?;
1964                     sig.iter().for_each(|ty| {
1965                         builder.append_block_param(block, *ty);
1966                     });
1967                     Ok((block, sig))
1968                 }
1969             })
1970             .collect::<Result<Vec<_>>>()?;
1971 
1972         // Valid blocks for jump tables have to have no parameters in the signature, and must also
1973         // not be the first block.
1974         self.resources.blocks_without_params = self.resources.blocks[1..]
1975             .iter()
1976             .filter(|(_, sig)| sig.len() == 0)
1977             .map(|(b, _)| *b)
1978             .collect();
1979 
1980         // Compute the block CFG
1981         //
1982         // cranelift-frontend requires us to never generate unreachable blocks
1983         // To ensure this property we start by constructing a main "spine" of blocks. So block1 can
1984         // always jump to block2, and block2 can always jump to block3, etc...
1985         //
1986         // That is not a very interesting CFG, so we introduce variations on that, but always
1987         // ensuring that the property of pointing to the next block is maintained whatever the
1988         // branching mechanism we use.
1989         let blocks = self.resources.blocks.clone();
1990         self.resources.block_terminators = blocks
1991             .iter()
1992             .map(|&(block, _)| {
1993                 let next_block = Block::with_number(block.as_u32() + 1).unwrap();
1994                 let forward_blocks = self.resources.forward_blocks(block);
1995                 let paramless_targets = self.resources.forward_blocks_without_params(block);
1996                 let has_paramless_targets = !paramless_targets.is_empty();
1997                 let next_block_is_paramless = paramless_targets.contains(&next_block);
1998 
1999                 let mut valid_terminators = vec![];
2000 
2001                 if forward_blocks.is_empty() {
2002                     // Return is only valid on the last block.
2003                     valid_terminators.push(BlockTerminatorKind::Return);
2004                 } else {
2005                     // If we have more than one block we can allow terminators that target blocks.
2006                     // TODO: We could add some kind of BrReturn here, to explore edges where we
2007                     // exit in the middle of the function
2008                     valid_terminators.extend_from_slice(&[
2009                         BlockTerminatorKind::Jump,
2010                         BlockTerminatorKind::Br,
2011                         BlockTerminatorKind::BrTable,
2012                     ]);
2013                 }
2014 
2015                 // As the Switch interface only allows targeting blocks without params we need
2016                 // to ensure that the next block has no params, since that one is guaranteed to be
2017                 // picked in either case.
2018                 if has_paramless_targets && next_block_is_paramless {
2019                     valid_terminators.push(BlockTerminatorKind::Switch);
2020                 }
2021 
2022                 let terminator = self.u.choose(&valid_terminators)?;
2023 
2024                 // Choose block targets for the terminators that we picked above
2025                 Ok(match terminator {
2026                     BlockTerminatorKind::Return => BlockTerminator::Return,
2027                     BlockTerminatorKind::Jump => BlockTerminator::Jump(next_block),
2028                     BlockTerminatorKind::Br => {
2029                         BlockTerminator::Br(next_block, self.generate_target_block(block)?)
2030                     }
2031                     // TODO: Allow generating backwards branches here
2032                     BlockTerminatorKind::BrTable => {
2033                         // Make the default the next block, and then we don't have to worry
2034                         // that we can reach it via the targets
2035                         let default = next_block;
2036 
2037                         let target_count = self.param(&self.config.jump_table_entries)?;
2038                         let targets = Result::from_iter(
2039                             (0..target_count).map(|_| self.generate_target_block(block)),
2040                         )?;
2041 
2042                         BlockTerminator::BrTable(default, targets)
2043                     }
2044                     BlockTerminatorKind::Switch => {
2045                         // Make the default the next block, and then we don't have to worry
2046                         // that we can reach it via the entries below
2047                         let default_block = next_block;
2048 
2049                         let _type = *self.u.choose(&[I8, I16, I32, I64, I128][..])?;
2050 
2051                         // Build this into a HashMap since we cannot have duplicate entries.
2052                         let mut entries = HashMap::new();
2053                         for _ in 0..self.param(&self.config.switch_cases)? {
2054                             // The Switch API only allows for entries that are addressable by the index type
2055                             // so we need to limit the range of values that we generate.
2056                             let (ty_min, ty_max) = _type.bounds(false);
2057                             let range_start = self.u.int_in_range(ty_min..=ty_max)?;
2058 
2059                             // We can either insert a contiguous range of blocks or a individual block
2060                             // This is done because the Switch API specializes contiguous ranges.
2061                             let range_size = if bool::arbitrary(self.u)? {
2062                                 1
2063                             } else {
2064                                 self.param(&self.config.switch_max_range_size)?
2065                             } as u128;
2066 
2067                             // Build the switch entries
2068                             for i in 0..range_size {
2069                                 let index = range_start.wrapping_add(i) % ty_max;
2070                                 let block = *self
2071                                     .u
2072                                     .choose(self.resources.forward_blocks_without_params(block))?;
2073 
2074                                 entries.insert(index, block);
2075                             }
2076                         }
2077 
2078                         BlockTerminator::Switch(_type, default_block, entries)
2079                     }
2080                 })
2081             })
2082             .collect::<Result<_>>()?;
2083 
2084         Ok(())
2085     }
2086 
2087     fn generate_block_signature(&mut self) -> Result<BlockSignature> {
2088         let param_count = self.param(&self.config.block_signature_params)?;
2089 
2090         let mut params = Vec::with_capacity(param_count);
2091         for _ in 0..param_count {
2092             params.push(self.u._type(self.target_triple.architecture)?);
2093         }
2094         Ok(params)
2095     }
2096 
2097     fn build_variable_pool(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
2098         let block = builder.current_block().unwrap();
2099 
2100         // Define variables for the function signature
2101         let mut vars: Vec<_> = builder
2102             .func
2103             .signature
2104             .params
2105             .iter()
2106             .map(|param| param.value_type)
2107             .zip(builder.block_params(block).iter().copied())
2108             .collect();
2109 
2110         // Create a pool of vars that are going to be used in this function
2111         for _ in 0..self.param(&self.config.vars_per_function)? {
2112             let ty = self.u._type(self.target_triple.architecture)?;
2113             let value = self.generate_const(builder, ty)?;
2114             vars.push((ty, value));
2115         }
2116 
2117         for (id, (ty, value)) in vars.into_iter().enumerate() {
2118             let var = Variable::new(id);
2119             builder.declare_var(var, ty);
2120             builder.def_var(var, value);
2121             self.resources
2122                 .vars
2123                 .entry(ty)
2124                 .or_insert_with(Vec::new)
2125                 .push(var);
2126         }
2127 
2128         Ok(())
2129     }
2130 
2131     /// We generate a function in multiple stages:
2132     ///
2133     /// * First we generate a random number of empty blocks
2134     /// * Then we generate a random pool of variables to be used throughout the function
2135     /// * We then visit each block and generate random instructions
2136     ///
2137     /// Because we generate all blocks and variables up front we already know everything that
2138     /// we need when generating instructions (i.e. jump targets / variables)
2139     pub fn generate(mut self) -> Result<Function> {
2140         let mut fn_builder_ctx = FunctionBuilderContext::new();
2141         let mut func = Function::with_name_signature(self.name.clone(), self.signature.clone());
2142 
2143         let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx);
2144 
2145         self.generate_blocks(&mut builder)?;
2146 
2147         // Function preamble
2148         self.generate_funcrefs(&mut builder)?;
2149         self.generate_stack_slots(&mut builder)?;
2150 
2151         // Main instruction generation loop
2152         for (block, block_sig) in self.resources.blocks.clone().into_iter() {
2153             let is_block0 = block.as_u32() == 0;
2154             builder.switch_to_block(block);
2155 
2156             if is_block0 {
2157                 // The first block is special because we must create variables both for the
2158                 // block signature and for the variable pool. Additionally, we must also define
2159                 // initial values for all variables that are not the function signature.
2160                 self.build_variable_pool(&mut builder)?;
2161 
2162                 // Stack slots have random bytes at the beginning of the function
2163                 // initialize them to a constant value so that execution stays predictable.
2164                 self.initialize_stack_slots(&mut builder)?;
2165             } else {
2166                 // Define variables for the block params
2167                 for (i, ty) in block_sig.iter().enumerate() {
2168                     let var = self.get_variable_of_type(*ty)?;
2169                     let block_param = builder.block_params(block)[i];
2170                     builder.def_var(var, block_param);
2171                 }
2172             }
2173 
2174             // Generate block instructions
2175             self.generate_instructions(&mut builder)?;
2176 
2177             // Insert a terminator to safely exit the block
2178             self.insert_terminator(&mut builder, block)?;
2179         }
2180 
2181         builder.seal_all_blocks();
2182         builder.finalize();
2183 
2184         Ok(func)
2185     }
2186 }
2187