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::IaddCout, &([I8, I8] | [I16, I16] | [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::IaddCout, &[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::IaddCout),
641                 (
642                     Opcode::Udiv | Opcode::Sdiv | Opcode::Urem | Opcode::Srem,
643                     &[I128, I128]
644                 ),
645                 (Opcode::Bnot, &[F32 | F64]),
646                 (
647                     Opcode::Band
648                         | Opcode::Bor
649                         | Opcode::Bxor
650                         | Opcode::BandNot
651                         | Opcode::BorNot
652                         | Opcode::BxorNot,
653                     &([F32, F32] | [F64, F64])
654                 ),
655                 (
656                     Opcode::FcvtToUint
657                         | Opcode::FcvtToUintSat
658                         | Opcode::FcvtToSint
659                         | Opcode::FcvtToSintSat,
660                     &[F32 | F64],
661                     &[I128]
662                 ),
663                 (
664                     Opcode::FcvtFromUint | Opcode::FcvtFromSint,
665                     &[I128],
666                     &[F32 | F64]
667                 ),
668                 (Opcode::SsubSat | Opcode::SaddSat, &[I64X2, I64X2]),
669             )
670         }
671 
672         Architecture::Riscv64(_) => {
673             // RISC-V Does not support SIMD at all
674             let is_simd = args.iter().chain(rets).any(|t| t.is_vector());
675             if is_simd {
676                 return false;
677             }
678 
679             exceptions!(
680                 op,
681                 args,
682                 rets,
683                 // TODO
684                 (Opcode::IaddCout),
685                 // TODO
686                 (
687                     Opcode::Udiv | Opcode::Sdiv | Opcode::Urem | Opcode::Srem,
688                     &[I128, I128]
689                 ),
690                 // TODO
691                 (Opcode::Iabs, &[I128]),
692                 // TODO
693                 (Opcode::Bitselect, &[I128, I128, I128]),
694                 // TODO
695                 (Opcode::Bswap),
696                 // https://github.com/bytecodealliance/wasmtime/issues/5528
697                 (
698                     Opcode::FcvtToUint
699                         | Opcode::FcvtToUintSat
700                         | Opcode::FcvtToSint
701                         | Opcode::FcvtToSintSat,
702                     &[F32 | F64],
703                     &[I8 | I16 | I128]
704                 ),
705                 // https://github.com/bytecodealliance/wasmtime/issues/5528
706                 (
707                     Opcode::FcvtFromUint | Opcode::FcvtFromSint,
708                     &[I8 | I16 | I128],
709                     &[F32 | F64]
710                 ),
711                 // TODO
712                 (
713                     Opcode::BandNot | Opcode::BorNot | Opcode::BxorNot,
714                     &([F32, F32] | [F64, F64])
715                 ),
716                 // https://github.com/bytecodealliance/wasmtime/issues/5884
717                 (Opcode::AtomicRmw),
718             )
719         }
720 
721         _ => true,
722     }
723 }
724 
725 type OpcodeSignature = (Opcode, Vec<Type>, Vec<Type>);
726 
727 static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = Lazy::new(|| {
728     let types = &[
729         I8, I16, I32, I64, I128, // Scalar Integers
730         F32, F64, // Scalar Floats
731         I8X16, I16X8, I32X4, I64X2, // SIMD Integers
732         F32X4, F64X2, // SIMD Floats
733     ];
734 
735     Opcode::all()
736         .iter()
737         .filter(|op| {
738             match op {
739                 // Control flow opcodes should not be generated through `generate_instructions`.
740                 Opcode::BrTable | Opcode::Brif | Opcode::Jump | Opcode::Return => false,
741 
742                 // Constants are generated outside of `generate_instructions`
743                 Opcode::Iconst => false,
744 
745                 // TODO: extract_vector raises exceptions during return type generation becuase it
746                 // uses dynamic vectors.
747                 Opcode::ExtractVector => false,
748 
749                 _ => true,
750             }
751         })
752         .flat_map(|op| {
753             let constraints = op.constraints();
754 
755             let ctrl_types = if let Some(ctrls) = constraints.ctrl_typeset() {
756                 Vec::from_iter(types.iter().copied().filter(|ty| ctrls.contains(*ty)))
757             } else {
758                 vec![INVALID]
759             };
760 
761             ctrl_types.into_iter().flat_map(move |ctrl_type| {
762                 let rets = Vec::from_iter(
763                     (0..constraints.num_fixed_results())
764                         .map(|i| constraints.result_type(i, ctrl_type)),
765                 );
766 
767                 // Cols is a vector whose length will match `num_fixed_value_arguments`, and whose
768                 // elements will be vectors of types that are valid for that fixed argument
769                 // position.
770                 let mut cols = vec![];
771 
772                 for i in 0..constraints.num_fixed_value_arguments() {
773                     match constraints.value_argument_constraint(i, ctrl_type) {
774                         ResolvedConstraint::Bound(ty) => cols.push(Vec::from([ty])),
775                         ResolvedConstraint::Free(tys) => cols.push(Vec::from_iter(
776                             types.iter().copied().filter(|ty| tys.contains(*ty)),
777                         )),
778                     }
779                 }
780 
781                 // Generate the cartesian product of cols to produce a vector of argument lists,
782                 // argss. The argss vector is seeded with the empty argument list, so there's an
783                 // initial value to be extended in the loop below.
784                 let mut argss = vec![vec![]];
785                 let mut cols = cols.as_slice();
786                 while let Some((col, rest)) = cols.split_last() {
787                     cols = rest;
788 
789                     let mut next = vec![];
790                     for current in argss.iter() {
791                         // Extend the front of each argument candidate with every type in `col`.
792                         for ty in col {
793                             let mut args = vec![*ty];
794                             args.extend_from_slice(&current);
795                             next.push(args);
796                         }
797                     }
798 
799                     let _ = std::mem::replace(&mut argss, next);
800                 }
801 
802                 argss.into_iter().map(move |args| (*op, args, rets.clone()))
803             })
804         })
805         .filter(|(op, args, rets)| {
806             // These op/signature combinations need to be vetted
807             exceptions!(
808                 op,
809                 args.as_slice(),
810                 rets.as_slice(),
811                 (Opcode::Debugtrap),
812                 (Opcode::Trap),
813                 (Opcode::Trapz),
814                 (Opcode::ResumableTrap),
815                 (Opcode::Trapnz),
816                 (Opcode::ResumableTrapnz),
817                 (Opcode::CallIndirect, &[I32]),
818                 (Opcode::ReturnCall),
819                 (Opcode::ReturnCallIndirect),
820                 (Opcode::FuncAddr),
821                 (Opcode::X86Pshufb),
822                 (Opcode::AvgRound),
823                 (Opcode::Uload8x8),
824                 (Opcode::Sload8x8),
825                 (Opcode::Uload16x4),
826                 (Opcode::Sload16x4),
827                 (Opcode::Uload32x2),
828                 (Opcode::Sload32x2),
829                 (Opcode::StackAddr),
830                 (Opcode::DynamicStackLoad),
831                 (Opcode::DynamicStackStore),
832                 (Opcode::DynamicStackAddr),
833                 (Opcode::GlobalValue),
834                 (Opcode::SymbolValue),
835                 (Opcode::TlsValue),
836                 (Opcode::GetPinnedReg),
837                 (Opcode::SetPinnedReg),
838                 (Opcode::GetFramePointer),
839                 (Opcode::GetStackPointer),
840                 (Opcode::GetReturnAddress),
841                 (Opcode::TableAddr),
842                 (Opcode::Null),
843                 (Opcode::X86Blendv),
844                 (Opcode::VallTrue),
845                 (Opcode::IcmpImm),
846                 (Opcode::X86Pmulhrsw),
847                 (Opcode::IaddImm),
848                 (Opcode::ImulImm),
849                 (Opcode::UdivImm),
850                 (Opcode::SdivImm),
851                 (Opcode::UremImm),
852                 (Opcode::SremImm),
853                 (Opcode::IrsubImm),
854                 (Opcode::IaddCin),
855                 (Opcode::IaddCarry),
856                 (Opcode::UaddOverflowTrap),
857                 (Opcode::IsubBin),
858                 (Opcode::IsubBout),
859                 (Opcode::IsubBorrow),
860                 (Opcode::BandImm),
861                 (Opcode::BorImm),
862                 (Opcode::BxorImm),
863                 (Opcode::RotlImm),
864                 (Opcode::RotrImm),
865                 (Opcode::IshlImm),
866                 (Opcode::UshrImm),
867                 (Opcode::SshrImm),
868                 (Opcode::IsNull),
869                 (Opcode::IsInvalid),
870                 (Opcode::ScalarToVector),
871                 (Opcode::X86Pmaddubsw),
872                 (Opcode::X86Cvtt2dq),
873                 (Opcode::Select, &[I8, F32, F32], &[F32]),
874                 (Opcode::Select, &[I16, F32, F32], &[F32]),
875                 (Opcode::Select, &[I32, F32, F32], &[F32]),
876                 (Opcode::Select, &[I64, F32, F32], &[F32]),
877                 (Opcode::Select, &[I128, F32, F32], &[F32]),
878                 (Opcode::Select, &[I8, F64, F64], &[F64]),
879                 (Opcode::Select, &[I16, F64, F64], &[F64]),
880                 (Opcode::Select, &[I32, F64, F64], &[F64]),
881                 (Opcode::Select, &[I64, F64, F64], &[F64]),
882                 (Opcode::Select, &[I128, F64, F64], &[F64]),
883                 (Opcode::Select, &[I8, I8X16, I8X16], &[I8X16]),
884                 (Opcode::Select, &[I16, I8X16, I8X16], &[I8X16]),
885                 (Opcode::Select, &[I32, I8X16, I8X16], &[I8X16]),
886                 (Opcode::Select, &[I64, I8X16, I8X16], &[I8X16]),
887                 (Opcode::Select, &[I128, I8X16, I8X16], &[I8X16]),
888                 (Opcode::Select, &[I8, I16X8, I16X8], &[I16X8]),
889                 (Opcode::Select, &[I16, I16X8, I16X8], &[I16X8]),
890                 (Opcode::Select, &[I32, I16X8, I16X8], &[I16X8]),
891                 (Opcode::Select, &[I64, I16X8, I16X8], &[I16X8]),
892                 (Opcode::Select, &[I128, I16X8, I16X8], &[I16X8]),
893                 (Opcode::Select, &[I8, I32X4, I32X4], &[I32X4]),
894                 (Opcode::Select, &[I16, I32X4, I32X4], &[I32X4]),
895                 (Opcode::Select, &[I32, I32X4, I32X4], &[I32X4]),
896                 (Opcode::Select, &[I64, I32X4, I32X4], &[I32X4]),
897                 (Opcode::Select, &[I128, I32X4, I32X4], &[I32X4]),
898                 (Opcode::Select, &[I8, I64X2, I64X2], &[I64X2]),
899                 (Opcode::Select, &[I16, I64X2, I64X2], &[I64X2]),
900                 (Opcode::Select, &[I32, I64X2, I64X2], &[I64X2]),
901                 (Opcode::Select, &[I64, I64X2, I64X2], &[I64X2]),
902                 (Opcode::Select, &[I128, I64X2, I64X2], &[I64X2]),
903                 (Opcode::Select, &[I8, F32X4, F32X4], &[F32X4]),
904                 (Opcode::Select, &[I16, F32X4, F32X4], &[F32X4]),
905                 (Opcode::Select, &[I32, F32X4, F32X4], &[F32X4]),
906                 (Opcode::Select, &[I64, F32X4, F32X4], &[F32X4]),
907                 (Opcode::Select, &[I128, F32X4, F32X4], &[F32X4]),
908                 (Opcode::Select, &[I8, F64X2, F64X2], &[F64X2]),
909                 (Opcode::Select, &[I16, F64X2, F64X2], &[F64X2]),
910                 (Opcode::Select, &[I32, F64X2, F64X2], &[F64X2]),
911                 (Opcode::Select, &[I64, F64X2, F64X2], &[F64X2]),
912                 (Opcode::Select, &[I128, F64X2, F64X2], &[F64X2]),
913                 (Opcode::SelectSpectreGuard, &[I8, F32, F32], &[F32]),
914                 (Opcode::SelectSpectreGuard, &[I16, F32, F32], &[F32]),
915                 (Opcode::SelectSpectreGuard, &[I32, F32, F32], &[F32]),
916                 (Opcode::SelectSpectreGuard, &[I64, F32, F32], &[F32]),
917                 (Opcode::SelectSpectreGuard, &[I128, F32, F32], &[F32]),
918                 (Opcode::SelectSpectreGuard, &[I8, F64, F64], &[F64]),
919                 (Opcode::SelectSpectreGuard, &[I16, F64, F64], &[F64]),
920                 (Opcode::SelectSpectreGuard, &[I32, F64, F64], &[F64]),
921                 (Opcode::SelectSpectreGuard, &[I64, F64, F64], &[F64]),
922                 (Opcode::SelectSpectreGuard, &[I128, F64, F64], &[F64]),
923                 (Opcode::SelectSpectreGuard, &[I8, I8X16, I8X16], &[I8X16]),
924                 (Opcode::SelectSpectreGuard, &[I16, I8X16, I8X16], &[I8X16]),
925                 (Opcode::SelectSpectreGuard, &[I32, I8X16, I8X16], &[I8X16]),
926                 (Opcode::SelectSpectreGuard, &[I64, I8X16, I8X16], &[I8X16]),
927                 (Opcode::SelectSpectreGuard, &[I128, I8X16, I8X16], &[I8X16]),
928                 (Opcode::SelectSpectreGuard, &[I8, I16X8, I16X8], &[I16X8]),
929                 (Opcode::SelectSpectreGuard, &[I16, I16X8, I16X8], &[I16X8]),
930                 (Opcode::SelectSpectreGuard, &[I32, I16X8, I16X8], &[I16X8]),
931                 (Opcode::SelectSpectreGuard, &[I64, I16X8, I16X8], &[I16X8]),
932                 (Opcode::SelectSpectreGuard, &[I128, I16X8, I16X8], &[I16X8]),
933                 (Opcode::SelectSpectreGuard, &[I8, I32X4, I32X4], &[I32X4]),
934                 (Opcode::SelectSpectreGuard, &[I16, I32X4, I32X4], &[I32X4]),
935                 (Opcode::SelectSpectreGuard, &[I32, I32X4, I32X4], &[I32X4]),
936                 (Opcode::SelectSpectreGuard, &[I64, I32X4, I32X4], &[I32X4]),
937                 (Opcode::SelectSpectreGuard, &[I128, I32X4, I32X4], &[I32X4]),
938                 (Opcode::SelectSpectreGuard, &[I8, I64X2, I64X2], &[I64X2]),
939                 (Opcode::SelectSpectreGuard, &[I16, I64X2, I64X2], &[I64X2]),
940                 (Opcode::SelectSpectreGuard, &[I32, I64X2, I64X2], &[I64X2]),
941                 (Opcode::SelectSpectreGuard, &[I64, I64X2, I64X2], &[I64X2]),
942                 (Opcode::SelectSpectreGuard, &[I128, I64X2, I64X2], &[I64X2]),
943                 (Opcode::SelectSpectreGuard, &[I8, F32X4, F32X4], &[F32X4]),
944                 (Opcode::SelectSpectreGuard, &[I16, F32X4, F32X4], &[F32X4]),
945                 (Opcode::SelectSpectreGuard, &[I32, F32X4, F32X4], &[F32X4]),
946                 (Opcode::SelectSpectreGuard, &[I64, F32X4, F32X4], &[F32X4]),
947                 (Opcode::SelectSpectreGuard, &[I128, F32X4, F32X4], &[F32X4]),
948                 (Opcode::SelectSpectreGuard, &[I8, F64X2, F64X2], &[F64X2]),
949                 (Opcode::SelectSpectreGuard, &[I16, F64X2, F64X2], &[F64X2]),
950                 (Opcode::SelectSpectreGuard, &[I32, F64X2, F64X2], &[F64X2]),
951                 (Opcode::SelectSpectreGuard, &[I64, F64X2, F64X2], &[F64X2]),
952                 (Opcode::SelectSpectreGuard, &[I128, F64X2, F64X2], &[F64X2]),
953                 (Opcode::Bitselect, &[F32, F32, F32], &[F32]),
954                 (Opcode::Bitselect, &[F64, F64, F64], &[F64]),
955                 (Opcode::Bitselect, &[F32X4, F32X4, F32X4], &[F32X4]),
956                 (Opcode::Bitselect, &[F64X2, F64X2, F64X2], &[F64X2]),
957                 (Opcode::VanyTrue, &[F32X4], &[I8]),
958                 (Opcode::VanyTrue, &[F64X2], &[I8]),
959                 (Opcode::VhighBits, &[F32X4], &[I8]),
960                 (Opcode::VhighBits, &[F64X2], &[I8]),
961                 (Opcode::VhighBits, &[I8X16], &[I16]),
962                 (Opcode::VhighBits, &[I16X8], &[I16]),
963                 (Opcode::VhighBits, &[I32X4], &[I16]),
964                 (Opcode::VhighBits, &[I64X2], &[I16]),
965                 (Opcode::VhighBits, &[F32X4], &[I16]),
966                 (Opcode::VhighBits, &[F64X2], &[I16]),
967                 (Opcode::VhighBits, &[I8X16], &[I32]),
968                 (Opcode::VhighBits, &[I16X8], &[I32]),
969                 (Opcode::VhighBits, &[I32X4], &[I32]),
970                 (Opcode::VhighBits, &[I64X2], &[I32]),
971                 (Opcode::VhighBits, &[F32X4], &[I32]),
972                 (Opcode::VhighBits, &[F64X2], &[I32]),
973                 (Opcode::VhighBits, &[I8X16], &[I64]),
974                 (Opcode::VhighBits, &[I16X8], &[I64]),
975                 (Opcode::VhighBits, &[I32X4], &[I64]),
976                 (Opcode::VhighBits, &[I64X2], &[I64]),
977                 (Opcode::VhighBits, &[F32X4], &[I64]),
978                 (Opcode::VhighBits, &[F64X2], &[I64]),
979                 (Opcode::VhighBits, &[I8X16], &[I128]),
980                 (Opcode::VhighBits, &[I16X8], &[I128]),
981                 (Opcode::VhighBits, &[I32X4], &[I128]),
982                 (Opcode::VhighBits, &[I64X2], &[I128]),
983                 (Opcode::VhighBits, &[F32X4], &[I128]),
984                 (Opcode::VhighBits, &[F64X2], &[I128]),
985                 (Opcode::VhighBits, &[I8X16], &[I8X16]),
986                 (Opcode::VhighBits, &[I16X8], &[I8X16]),
987                 (Opcode::VhighBits, &[I32X4], &[I8X16]),
988                 (Opcode::VhighBits, &[I64X2], &[I8X16]),
989                 (Opcode::VhighBits, &[F32X4], &[I8X16]),
990                 (Opcode::VhighBits, &[F64X2], &[I8X16]),
991                 (Opcode::VhighBits, &[I8X16], &[I16X8]),
992                 (Opcode::VhighBits, &[I16X8], &[I16X8]),
993                 (Opcode::VhighBits, &[I32X4], &[I16X8]),
994                 (Opcode::VhighBits, &[I64X2], &[I16X8]),
995                 (Opcode::VhighBits, &[F32X4], &[I16X8]),
996                 (Opcode::VhighBits, &[F64X2], &[I16X8]),
997                 (Opcode::VhighBits, &[I8X16], &[I32X4]),
998                 (Opcode::VhighBits, &[I16X8], &[I32X4]),
999                 (Opcode::VhighBits, &[I32X4], &[I32X4]),
1000                 (Opcode::VhighBits, &[I64X2], &[I32X4]),
1001                 (Opcode::VhighBits, &[F32X4], &[I32X4]),
1002                 (Opcode::VhighBits, &[F64X2], &[I32X4]),
1003                 (Opcode::VhighBits, &[I8X16], &[I64X2]),
1004                 (Opcode::VhighBits, &[I16X8], &[I64X2]),
1005                 (Opcode::VhighBits, &[I32X4], &[I64X2]),
1006                 (Opcode::VhighBits, &[I64X2], &[I64X2]),
1007                 (Opcode::VhighBits, &[F32X4], &[I64X2]),
1008                 (Opcode::VhighBits, &[F64X2], &[I64X2]),
1009                 (Opcode::Ineg, &[I8X16], &[I8X16]),
1010                 (Opcode::Ineg, &[I16X8], &[I16X8]),
1011                 (Opcode::Ineg, &[I32X4], &[I32X4]),
1012                 (Opcode::Ineg, &[I64X2], &[I64X2]),
1013                 (Opcode::Umulhi, &[I128, I128], &[I128]),
1014                 (Opcode::Smulhi, &[I128, I128], &[I128]),
1015                 // https://github.com/bytecodealliance/wasmtime/issues/6073
1016                 (Opcode::Iconcat, &[I32, I32], &[I64]),
1017                 (Opcode::Iconcat, &[I16, I16], &[I32]),
1018                 (Opcode::Iconcat, &[I8, I8], &[I16]),
1019                 // https://github.com/bytecodealliance/wasmtime/issues/6073
1020                 (Opcode::Isplit, &[I64], &[I32, I32]),
1021                 (Opcode::Isplit, &[I32], &[I16, I16]),
1022                 (Opcode::Isplit, &[I16], &[I8, I8]),
1023                 (Opcode::Rotl, &[I8X16, I8], &[I8X16]),
1024                 (Opcode::Rotl, &[I8X16, I16], &[I8X16]),
1025                 (Opcode::Rotl, &[I8X16, I32], &[I8X16]),
1026                 (Opcode::Rotl, &[I8X16, I64], &[I8X16]),
1027                 (Opcode::Rotl, &[I8X16, I128], &[I8X16]),
1028                 (Opcode::Rotl, &[I16X8, I8], &[I16X8]),
1029                 (Opcode::Rotl, &[I16X8, I16], &[I16X8]),
1030                 (Opcode::Rotl, &[I16X8, I32], &[I16X8]),
1031                 (Opcode::Rotl, &[I16X8, I64], &[I16X8]),
1032                 (Opcode::Rotl, &[I16X8, I128], &[I16X8]),
1033                 (Opcode::Rotl, &[I32X4, I8], &[I32X4]),
1034                 (Opcode::Rotl, &[I32X4, I16], &[I32X4]),
1035                 (Opcode::Rotl, &[I32X4, I32], &[I32X4]),
1036                 (Opcode::Rotl, &[I32X4, I64], &[I32X4]),
1037                 (Opcode::Rotl, &[I32X4, I128], &[I32X4]),
1038                 (Opcode::Rotl, &[I64X2, I8], &[I64X2]),
1039                 (Opcode::Rotl, &[I64X2, I16], &[I64X2]),
1040                 (Opcode::Rotl, &[I64X2, I32], &[I64X2]),
1041                 (Opcode::Rotl, &[I64X2, I64], &[I64X2]),
1042                 (Opcode::Rotl, &[I64X2, I128], &[I64X2]),
1043                 (Opcode::Rotr, &[I8X16, I8], &[I8X16]),
1044                 (Opcode::Rotr, &[I8X16, I16], &[I8X16]),
1045                 (Opcode::Rotr, &[I8X16, I32], &[I8X16]),
1046                 (Opcode::Rotr, &[I8X16, I64], &[I8X16]),
1047                 (Opcode::Rotr, &[I8X16, I128], &[I8X16]),
1048                 (Opcode::Rotr, &[I16X8, I8], &[I16X8]),
1049                 (Opcode::Rotr, &[I16X8, I16], &[I16X8]),
1050                 (Opcode::Rotr, &[I16X8, I32], &[I16X8]),
1051                 (Opcode::Rotr, &[I16X8, I64], &[I16X8]),
1052                 (Opcode::Rotr, &[I16X8, I128], &[I16X8]),
1053                 (Opcode::Rotr, &[I32X4, I8], &[I32X4]),
1054                 (Opcode::Rotr, &[I32X4, I16], &[I32X4]),
1055                 (Opcode::Rotr, &[I32X4, I32], &[I32X4]),
1056                 (Opcode::Rotr, &[I32X4, I64], &[I32X4]),
1057                 (Opcode::Rotr, &[I32X4, I128], &[I32X4]),
1058                 (Opcode::Rotr, &[I64X2, I8], &[I64X2]),
1059                 (Opcode::Rotr, &[I64X2, I16], &[I64X2]),
1060                 (Opcode::Rotr, &[I64X2, I32], &[I64X2]),
1061                 (Opcode::Rotr, &[I64X2, I64], &[I64X2]),
1062                 (Opcode::Rotr, &[I64X2, I128], &[I64X2]),
1063                 (Opcode::Ishl, &[I8X16, I8], &[I8X16]),
1064                 (Opcode::Ishl, &[I8X16, I16], &[I8X16]),
1065                 (Opcode::Ishl, &[I8X16, I32], &[I8X16]),
1066                 (Opcode::Ishl, &[I8X16, I64], &[I8X16]),
1067                 (Opcode::Ishl, &[I8X16, I128], &[I8X16]),
1068                 (Opcode::Ishl, &[I16X8, I8], &[I16X8]),
1069                 (Opcode::Ishl, &[I16X8, I16], &[I16X8]),
1070                 (Opcode::Ishl, &[I16X8, I32], &[I16X8]),
1071                 (Opcode::Ishl, &[I16X8, I64], &[I16X8]),
1072                 (Opcode::Ishl, &[I16X8, I128], &[I16X8]),
1073                 (Opcode::Ishl, &[I32X4, I8], &[I32X4]),
1074                 (Opcode::Ishl, &[I32X4, I16], &[I32X4]),
1075                 (Opcode::Ishl, &[I32X4, I32], &[I32X4]),
1076                 (Opcode::Ishl, &[I32X4, I64], &[I32X4]),
1077                 (Opcode::Ishl, &[I32X4, I128], &[I32X4]),
1078                 (Opcode::Ishl, &[I64X2, I8], &[I64X2]),
1079                 (Opcode::Ishl, &[I64X2, I16], &[I64X2]),
1080                 (Opcode::Ishl, &[I64X2, I32], &[I64X2]),
1081                 (Opcode::Ishl, &[I64X2, I64], &[I64X2]),
1082                 (Opcode::Ishl, &[I64X2, I128], &[I64X2]),
1083                 (Opcode::Ushr, &[I8X16, I8], &[I8X16]),
1084                 (Opcode::Ushr, &[I8X16, I16], &[I8X16]),
1085                 (Opcode::Ushr, &[I8X16, I32], &[I8X16]),
1086                 (Opcode::Ushr, &[I8X16, I64], &[I8X16]),
1087                 (Opcode::Ushr, &[I8X16, I128], &[I8X16]),
1088                 (Opcode::Ushr, &[I16X8, I8], &[I16X8]),
1089                 (Opcode::Ushr, &[I16X8, I16], &[I16X8]),
1090                 (Opcode::Ushr, &[I16X8, I32], &[I16X8]),
1091                 (Opcode::Ushr, &[I16X8, I64], &[I16X8]),
1092                 (Opcode::Ushr, &[I16X8, I128], &[I16X8]),
1093                 (Opcode::Ushr, &[I32X4, I8], &[I32X4]),
1094                 (Opcode::Ushr, &[I32X4, I16], &[I32X4]),
1095                 (Opcode::Ushr, &[I32X4, I32], &[I32X4]),
1096                 (Opcode::Ushr, &[I32X4, I64], &[I32X4]),
1097                 (Opcode::Ushr, &[I32X4, I128], &[I32X4]),
1098                 (Opcode::Ushr, &[I64X2, I8], &[I64X2]),
1099                 (Opcode::Ushr, &[I64X2, I16], &[I64X2]),
1100                 (Opcode::Ushr, &[I64X2, I32], &[I64X2]),
1101                 (Opcode::Ushr, &[I64X2, I64], &[I64X2]),
1102                 (Opcode::Ushr, &[I64X2, I128], &[I64X2]),
1103                 (Opcode::Sshr, &[I8X16, I8], &[I8X16]),
1104                 (Opcode::Sshr, &[I8X16, I16], &[I8X16]),
1105                 (Opcode::Sshr, &[I8X16, I32], &[I8X16]),
1106                 (Opcode::Sshr, &[I8X16, I64], &[I8X16]),
1107                 (Opcode::Sshr, &[I8X16, I128], &[I8X16]),
1108                 (Opcode::Sshr, &[I16X8, I8], &[I16X8]),
1109                 (Opcode::Sshr, &[I16X8, I16], &[I16X8]),
1110                 (Opcode::Sshr, &[I16X8, I32], &[I16X8]),
1111                 (Opcode::Sshr, &[I16X8, I64], &[I16X8]),
1112                 (Opcode::Sshr, &[I16X8, I128], &[I16X8]),
1113                 (Opcode::Sshr, &[I32X4, I8], &[I32X4]),
1114                 (Opcode::Sshr, &[I32X4, I16], &[I32X4]),
1115                 (Opcode::Sshr, &[I32X4, I32], &[I32X4]),
1116                 (Opcode::Sshr, &[I32X4, I64], &[I32X4]),
1117                 (Opcode::Sshr, &[I32X4, I128], &[I32X4]),
1118                 (Opcode::Sshr, &[I64X2, I8], &[I64X2]),
1119                 (Opcode::Sshr, &[I64X2, I16], &[I64X2]),
1120                 (Opcode::Sshr, &[I64X2, I32], &[I64X2]),
1121                 (Opcode::Sshr, &[I64X2, I64], &[I64X2]),
1122                 (Opcode::Sshr, &[I64X2, I128], &[I64X2]),
1123                 (Opcode::Fmin, &[F32X4, F32X4], &[F32X4]),
1124                 (Opcode::Fmin, &[F64X2, F64X2], &[F64X2]),
1125                 (Opcode::FminPseudo, &[F32X4, F32X4], &[F32X4]),
1126                 (Opcode::FminPseudo, &[F64X2, F64X2], &[F64X2]),
1127                 (Opcode::Fmax, &[F32X4, F32X4], &[F32X4]),
1128                 (Opcode::Fmax, &[F64X2, F64X2], &[F64X2]),
1129                 (Opcode::FmaxPseudo, &[F32X4, F32X4], &[F32X4]),
1130                 (Opcode::FmaxPseudo, &[F64X2, F64X2], &[F64X2]),
1131                 (Opcode::Bitcast, &[I8], &[I8]),
1132                 (Opcode::Bitcast, &[I16], &[I8]),
1133                 (Opcode::Bitcast, &[I32], &[I8]),
1134                 (Opcode::Bitcast, &[I64], &[I8]),
1135                 (Opcode::Bitcast, &[I128], &[I8]),
1136                 (Opcode::Bitcast, &[F32], &[I8]),
1137                 (Opcode::Bitcast, &[F64], &[I8]),
1138                 (Opcode::Bitcast, &[I8X16], &[I8]),
1139                 (Opcode::Bitcast, &[I16X8], &[I8]),
1140                 (Opcode::Bitcast, &[I32X4], &[I8]),
1141                 (Opcode::Bitcast, &[I64X2], &[I8]),
1142                 (Opcode::Bitcast, &[F32X4], &[I8]),
1143                 (Opcode::Bitcast, &[F64X2], &[I8]),
1144                 (Opcode::Bitcast, &[I8], &[I16]),
1145                 (Opcode::Bitcast, &[I16], &[I16]),
1146                 (Opcode::Bitcast, &[I32], &[I16]),
1147                 (Opcode::Bitcast, &[I64], &[I16]),
1148                 (Opcode::Bitcast, &[I128], &[I16]),
1149                 (Opcode::Bitcast, &[F32], &[I16]),
1150                 (Opcode::Bitcast, &[F64], &[I16]),
1151                 (Opcode::Bitcast, &[I8X16], &[I16]),
1152                 (Opcode::Bitcast, &[I16X8], &[I16]),
1153                 (Opcode::Bitcast, &[I32X4], &[I16]),
1154                 (Opcode::Bitcast, &[I64X2], &[I16]),
1155                 (Opcode::Bitcast, &[F32X4], &[I16]),
1156                 (Opcode::Bitcast, &[F64X2], &[I16]),
1157                 (Opcode::Bitcast, &[I8], &[I32]),
1158                 (Opcode::Bitcast, &[I16], &[I32]),
1159                 (Opcode::Bitcast, &[I32], &[I32]),
1160                 (Opcode::Bitcast, &[I64], &[I32]),
1161                 (Opcode::Bitcast, &[I128], &[I32]),
1162                 (Opcode::Bitcast, &[F64], &[I32]),
1163                 (Opcode::Bitcast, &[I8X16], &[I32]),
1164                 (Opcode::Bitcast, &[I16X8], &[I32]),
1165                 (Opcode::Bitcast, &[I32X4], &[I32]),
1166                 (Opcode::Bitcast, &[I64X2], &[I32]),
1167                 (Opcode::Bitcast, &[F32X4], &[I32]),
1168                 (Opcode::Bitcast, &[F64X2], &[I32]),
1169                 (Opcode::Bitcast, &[I8], &[I64]),
1170                 (Opcode::Bitcast, &[I16], &[I64]),
1171                 (Opcode::Bitcast, &[I32], &[I64]),
1172                 (Opcode::Bitcast, &[I64], &[I64]),
1173                 (Opcode::Bitcast, &[I128], &[I64]),
1174                 (Opcode::Bitcast, &[F32], &[I64]),
1175                 (Opcode::Bitcast, &[I8X16], &[I64]),
1176                 (Opcode::Bitcast, &[I16X8], &[I64]),
1177                 (Opcode::Bitcast, &[I32X4], &[I64]),
1178                 (Opcode::Bitcast, &[I64X2], &[I64]),
1179                 (Opcode::Bitcast, &[F32X4], &[I64]),
1180                 (Opcode::Bitcast, &[F64X2], &[I64]),
1181                 (Opcode::Bitcast, &[I8], &[I128]),
1182                 (Opcode::Bitcast, &[I16], &[I128]),
1183                 (Opcode::Bitcast, &[I32], &[I128]),
1184                 (Opcode::Bitcast, &[I64], &[I128]),
1185                 (Opcode::Bitcast, &[I128], &[I128]),
1186                 (Opcode::Bitcast, &[F32], &[I128]),
1187                 (Opcode::Bitcast, &[F64], &[I128]),
1188                 (Opcode::Bitcast, &[I8X16], &[I128]),
1189                 (Opcode::Bitcast, &[I16X8], &[I128]),
1190                 (Opcode::Bitcast, &[I32X4], &[I128]),
1191                 (Opcode::Bitcast, &[I64X2], &[I128]),
1192                 (Opcode::Bitcast, &[F32X4], &[I128]),
1193                 (Opcode::Bitcast, &[F64X2], &[I128]),
1194                 (Opcode::Bitcast, &[I8], &[F32]),
1195                 (Opcode::Bitcast, &[I16], &[F32]),
1196                 (Opcode::Bitcast, &[I64], &[F32]),
1197                 (Opcode::Bitcast, &[I128], &[F32]),
1198                 (Opcode::Bitcast, &[F32], &[F32]),
1199                 (Opcode::Bitcast, &[F64], &[F32]),
1200                 (Opcode::Bitcast, &[I8X16], &[F32]),
1201                 (Opcode::Bitcast, &[I16X8], &[F32]),
1202                 (Opcode::Bitcast, &[I32X4], &[F32]),
1203                 (Opcode::Bitcast, &[I64X2], &[F32]),
1204                 (Opcode::Bitcast, &[F32X4], &[F32]),
1205                 (Opcode::Bitcast, &[F64X2], &[F32]),
1206                 (Opcode::Bitcast, &[I8], &[F64]),
1207                 (Opcode::Bitcast, &[I16], &[F64]),
1208                 (Opcode::Bitcast, &[I32], &[F64]),
1209                 (Opcode::Bitcast, &[I128], &[F64]),
1210                 (Opcode::Bitcast, &[F32], &[F64]),
1211                 (Opcode::Bitcast, &[F64], &[F64]),
1212                 (Opcode::Bitcast, &[I8X16], &[F64]),
1213                 (Opcode::Bitcast, &[I16X8], &[F64]),
1214                 (Opcode::Bitcast, &[I32X4], &[F64]),
1215                 (Opcode::Bitcast, &[I64X2], &[F64]),
1216                 (Opcode::Bitcast, &[F32X4], &[F64]),
1217                 (Opcode::Bitcast, &[F64X2], &[F64]),
1218                 (Opcode::Bitcast, &[I8], &[I8X16]),
1219                 (Opcode::Bitcast, &[I16], &[I8X16]),
1220                 (Opcode::Bitcast, &[I32], &[I8X16]),
1221                 (Opcode::Bitcast, &[I64], &[I8X16]),
1222                 (Opcode::Bitcast, &[I128], &[I8X16]),
1223                 (Opcode::Bitcast, &[F32], &[I8X16]),
1224                 (Opcode::Bitcast, &[F64], &[I8X16]),
1225                 (Opcode::Bitcast, &[I8X16], &[I8X16]),
1226                 (Opcode::Bitcast, &[I16X8], &[I8X16]),
1227                 (Opcode::Bitcast, &[I32X4], &[I8X16]),
1228                 (Opcode::Bitcast, &[I64X2], &[I8X16]),
1229                 (Opcode::Bitcast, &[F32X4], &[I8X16]),
1230                 (Opcode::Bitcast, &[F64X2], &[I8X16]),
1231                 (Opcode::Bitcast, &[I8], &[I16X8]),
1232                 (Opcode::Bitcast, &[I16], &[I16X8]),
1233                 (Opcode::Bitcast, &[I32], &[I16X8]),
1234                 (Opcode::Bitcast, &[I64], &[I16X8]),
1235                 (Opcode::Bitcast, &[I128], &[I16X8]),
1236                 (Opcode::Bitcast, &[F32], &[I16X8]),
1237                 (Opcode::Bitcast, &[F64], &[I16X8]),
1238                 (Opcode::Bitcast, &[I8X16], &[I16X8]),
1239                 (Opcode::Bitcast, &[I16X8], &[I16X8]),
1240                 (Opcode::Bitcast, &[I32X4], &[I16X8]),
1241                 (Opcode::Bitcast, &[I64X2], &[I16X8]),
1242                 (Opcode::Bitcast, &[F32X4], &[I16X8]),
1243                 (Opcode::Bitcast, &[F64X2], &[I16X8]),
1244                 (Opcode::Bitcast, &[I8], &[I32X4]),
1245                 (Opcode::Bitcast, &[I16], &[I32X4]),
1246                 (Opcode::Bitcast, &[I32], &[I32X4]),
1247                 (Opcode::Bitcast, &[I64], &[I32X4]),
1248                 (Opcode::Bitcast, &[I128], &[I32X4]),
1249                 (Opcode::Bitcast, &[F32], &[I32X4]),
1250                 (Opcode::Bitcast, &[F64], &[I32X4]),
1251                 (Opcode::Bitcast, &[I8X16], &[I32X4]),
1252                 (Opcode::Bitcast, &[I16X8], &[I32X4]),
1253                 (Opcode::Bitcast, &[I32X4], &[I32X4]),
1254                 (Opcode::Bitcast, &[I64X2], &[I32X4]),
1255                 (Opcode::Bitcast, &[F32X4], &[I32X4]),
1256                 (Opcode::Bitcast, &[F64X2], &[I32X4]),
1257                 (Opcode::Bitcast, &[I8], &[I64X2]),
1258                 (Opcode::Bitcast, &[I16], &[I64X2]),
1259                 (Opcode::Bitcast, &[I32], &[I64X2]),
1260                 (Opcode::Bitcast, &[I64], &[I64X2]),
1261                 (Opcode::Bitcast, &[I128], &[I64X2]),
1262                 (Opcode::Bitcast, &[F32], &[I64X2]),
1263                 (Opcode::Bitcast, &[F64], &[I64X2]),
1264                 (Opcode::Bitcast, &[I8X16], &[I64X2]),
1265                 (Opcode::Bitcast, &[I16X8], &[I64X2]),
1266                 (Opcode::Bitcast, &[I32X4], &[I64X2]),
1267                 (Opcode::Bitcast, &[I64X2], &[I64X2]),
1268                 (Opcode::Bitcast, &[F32X4], &[I64X2]),
1269                 (Opcode::Bitcast, &[F64X2], &[I64X2]),
1270                 (Opcode::Bitcast, &[I8], &[F32X4]),
1271                 (Opcode::Bitcast, &[I16], &[F32X4]),
1272                 (Opcode::Bitcast, &[I32], &[F32X4]),
1273                 (Opcode::Bitcast, &[I64], &[F32X4]),
1274                 (Opcode::Bitcast, &[I128], &[F32X4]),
1275                 (Opcode::Bitcast, &[F32], &[F32X4]),
1276                 (Opcode::Bitcast, &[F64], &[F32X4]),
1277                 (Opcode::Bitcast, &[I8X16], &[F32X4]),
1278                 (Opcode::Bitcast, &[I16X8], &[F32X4]),
1279                 (Opcode::Bitcast, &[I32X4], &[F32X4]),
1280                 (Opcode::Bitcast, &[I64X2], &[F32X4]),
1281                 (Opcode::Bitcast, &[F32X4], &[F32X4]),
1282                 (Opcode::Bitcast, &[F64X2], &[F32X4]),
1283                 (Opcode::Bitcast, &[I8], &[F64X2]),
1284                 (Opcode::Bitcast, &[I16], &[F64X2]),
1285                 (Opcode::Bitcast, &[I32], &[F64X2]),
1286                 (Opcode::Bitcast, &[I64], &[F64X2]),
1287                 (Opcode::Bitcast, &[I128], &[F64X2]),
1288                 (Opcode::Bitcast, &[F32], &[F64X2]),
1289                 (Opcode::Bitcast, &[F64], &[F64X2]),
1290                 (Opcode::Bitcast, &[I8X16], &[F64X2]),
1291                 (Opcode::Bitcast, &[I16X8], &[F64X2]),
1292                 (Opcode::Bitcast, &[I32X4], &[F64X2]),
1293                 (Opcode::Bitcast, &[I64X2], &[F64X2]),
1294                 (Opcode::Bitcast, &[F32X4], &[F64X2]),
1295                 (Opcode::Bitcast, &[F64X2], &[F64X2]),
1296                 (Opcode::FcvtToUintSat, &[F32X4], &[I8]),
1297                 (Opcode::FcvtToUintSat, &[F64X2], &[I8]),
1298                 (Opcode::FcvtToUintSat, &[F32X4], &[I16]),
1299                 (Opcode::FcvtToUintSat, &[F64X2], &[I16]),
1300                 (Opcode::FcvtToUintSat, &[F32X4], &[I32]),
1301                 (Opcode::FcvtToUintSat, &[F64X2], &[I32]),
1302                 (Opcode::FcvtToUintSat, &[F32X4], &[I64]),
1303                 (Opcode::FcvtToUintSat, &[F64X2], &[I64]),
1304                 (Opcode::FcvtToUintSat, &[F32X4], &[I128]),
1305                 (Opcode::FcvtToUintSat, &[F64X2], &[I128]),
1306                 (Opcode::FcvtToUintSat, &[F32], &[I8X16]),
1307                 (Opcode::FcvtToUintSat, &[F64], &[I8X16]),
1308                 (Opcode::FcvtToUintSat, &[F32X4], &[I8X16]),
1309                 (Opcode::FcvtToUintSat, &[F64X2], &[I8X16]),
1310                 (Opcode::FcvtToUintSat, &[F32], &[I16X8]),
1311                 (Opcode::FcvtToUintSat, &[F64], &[I16X8]),
1312                 (Opcode::FcvtToUintSat, &[F32X4], &[I16X8]),
1313                 (Opcode::FcvtToUintSat, &[F64X2], &[I16X8]),
1314                 (Opcode::FcvtToUintSat, &[F32], &[I32X4]),
1315                 (Opcode::FcvtToUintSat, &[F64], &[I32X4]),
1316                 (Opcode::FcvtToUintSat, &[F64X2], &[I32X4]),
1317                 (Opcode::FcvtToUintSat, &[F32], &[I64X2]),
1318                 (Opcode::FcvtToUintSat, &[F64], &[I64X2]),
1319                 (Opcode::FcvtToUintSat, &[F32X4], &[I64X2]),
1320                 (Opcode::FcvtToSintSat, &[F32X4], &[I8]),
1321                 (Opcode::FcvtToSintSat, &[F64X2], &[I8]),
1322                 (Opcode::FcvtToSintSat, &[F32X4], &[I16]),
1323                 (Opcode::FcvtToSintSat, &[F64X2], &[I16]),
1324                 (Opcode::FcvtToSintSat, &[F32X4], &[I32]),
1325                 (Opcode::FcvtToSintSat, &[F64X2], &[I32]),
1326                 (Opcode::FcvtToSintSat, &[F32X4], &[I64]),
1327                 (Opcode::FcvtToSintSat, &[F64X2], &[I64]),
1328                 (Opcode::FcvtToSintSat, &[F32X4], &[I128]),
1329                 (Opcode::FcvtToSintSat, &[F64X2], &[I128]),
1330                 (Opcode::FcvtToSintSat, &[F32], &[I8X16]),
1331                 (Opcode::FcvtToSintSat, &[F64], &[I8X16]),
1332                 (Opcode::FcvtToSintSat, &[F32X4], &[I8X16]),
1333                 (Opcode::FcvtToSintSat, &[F64X2], &[I8X16]),
1334                 (Opcode::FcvtToSintSat, &[F32], &[I16X8]),
1335                 (Opcode::FcvtToSintSat, &[F64], &[I16X8]),
1336                 (Opcode::FcvtToSintSat, &[F32X4], &[I16X8]),
1337                 (Opcode::FcvtToSintSat, &[F64X2], &[I16X8]),
1338                 (Opcode::FcvtToSintSat, &[F32], &[I32X4]),
1339                 (Opcode::FcvtToSintSat, &[F64], &[I32X4]),
1340                 (Opcode::FcvtToSintSat, &[F64X2], &[I32X4]),
1341                 (Opcode::FcvtToSintSat, &[F32], &[I64X2]),
1342                 (Opcode::FcvtToSintSat, &[F64], &[I64X2]),
1343                 (Opcode::FcvtToSintSat, &[F32X4], &[I64X2]),
1344                 (Opcode::FcvtFromUint, &[I8X16], &[F32]),
1345                 (Opcode::FcvtFromUint, &[I16X8], &[F32]),
1346                 (Opcode::FcvtFromUint, &[I32X4], &[F32]),
1347                 (Opcode::FcvtFromUint, &[I64X2], &[F32]),
1348                 (Opcode::FcvtFromUint, &[I8X16], &[F64]),
1349                 (Opcode::FcvtFromUint, &[I16X8], &[F64]),
1350                 (Opcode::FcvtFromUint, &[I32X4], &[F64]),
1351                 (Opcode::FcvtFromUint, &[I64X2], &[F64]),
1352                 (Opcode::FcvtFromUint, &[I8], &[F32X4]),
1353                 (Opcode::FcvtFromUint, &[I16], &[F32X4]),
1354                 (Opcode::FcvtFromUint, &[I32], &[F32X4]),
1355                 (Opcode::FcvtFromUint, &[I64], &[F32X4]),
1356                 (Opcode::FcvtFromUint, &[I128], &[F32X4]),
1357                 (Opcode::FcvtFromUint, &[I8X16], &[F32X4]),
1358                 (Opcode::FcvtFromUint, &[I16X8], &[F32X4]),
1359                 (Opcode::FcvtFromUint, &[I64X2], &[F32X4]),
1360                 (Opcode::FcvtFromUint, &[I8], &[F64X2]),
1361                 (Opcode::FcvtFromUint, &[I16], &[F64X2]),
1362                 (Opcode::FcvtFromUint, &[I32], &[F64X2]),
1363                 (Opcode::FcvtFromUint, &[I64], &[F64X2]),
1364                 (Opcode::FcvtFromUint, &[I128], &[F64X2]),
1365                 (Opcode::FcvtFromUint, &[I8X16], &[F64X2]),
1366                 (Opcode::FcvtFromUint, &[I16X8], &[F64X2]),
1367                 (Opcode::FcvtFromUint, &[I32X4], &[F64X2]),
1368                 (Opcode::FcvtFromSint, &[I8X16], &[F32]),
1369                 (Opcode::FcvtFromSint, &[I16X8], &[F32]),
1370                 (Opcode::FcvtFromSint, &[I32X4], &[F32]),
1371                 (Opcode::FcvtFromSint, &[I64X2], &[F32]),
1372                 (Opcode::FcvtFromSint, &[I8X16], &[F64]),
1373                 (Opcode::FcvtFromSint, &[I16X8], &[F64]),
1374                 (Opcode::FcvtFromSint, &[I32X4], &[F64]),
1375                 (Opcode::FcvtFromSint, &[I64X2], &[F64]),
1376                 (Opcode::FcvtFromSint, &[I8], &[F32X4]),
1377                 (Opcode::FcvtFromSint, &[I16], &[F32X4]),
1378                 (Opcode::FcvtFromSint, &[I32], &[F32X4]),
1379                 (Opcode::FcvtFromSint, &[I64], &[F32X4]),
1380                 (Opcode::FcvtFromSint, &[I128], &[F32X4]),
1381                 (Opcode::FcvtFromSint, &[I8X16], &[F32X4]),
1382                 (Opcode::FcvtFromSint, &[I16X8], &[F32X4]),
1383                 (Opcode::FcvtFromSint, &[I64X2], &[F32X4]),
1384                 (Opcode::FcvtFromSint, &[I8], &[F64X2]),
1385                 (Opcode::FcvtFromSint, &[I16], &[F64X2]),
1386                 (Opcode::FcvtFromSint, &[I32], &[F64X2]),
1387                 (Opcode::FcvtFromSint, &[I64], &[F64X2]),
1388                 (Opcode::FcvtFromSint, &[I128], &[F64X2]),
1389                 (Opcode::FcvtFromSint, &[I8X16], &[F64X2]),
1390                 (Opcode::FcvtFromSint, &[I16X8], &[F64X2]),
1391                 (Opcode::FcvtFromSint, &[I32X4], &[F64X2]),
1392                 (Opcode::FcvtLowFromSint, &[I8], &[F32]),
1393                 (Opcode::FcvtLowFromSint, &[I16], &[F32]),
1394                 (Opcode::FcvtLowFromSint, &[I32], &[F32]),
1395                 (Opcode::FcvtLowFromSint, &[I64], &[F32]),
1396                 (Opcode::FcvtLowFromSint, &[I128], &[F32]),
1397                 (Opcode::FcvtLowFromSint, &[I8X16], &[F32]),
1398                 (Opcode::FcvtLowFromSint, &[I16X8], &[F32]),
1399                 (Opcode::FcvtLowFromSint, &[I32X4], &[F32]),
1400                 (Opcode::FcvtLowFromSint, &[I64X2], &[F32]),
1401                 (Opcode::FcvtLowFromSint, &[I8], &[F64]),
1402                 (Opcode::FcvtLowFromSint, &[I16], &[F64]),
1403                 (Opcode::FcvtLowFromSint, &[I32], &[F64]),
1404                 (Opcode::FcvtLowFromSint, &[I64], &[F64]),
1405                 (Opcode::FcvtLowFromSint, &[I128], &[F64]),
1406                 (Opcode::FcvtLowFromSint, &[I8X16], &[F64]),
1407                 (Opcode::FcvtLowFromSint, &[I16X8], &[F64]),
1408                 (Opcode::FcvtLowFromSint, &[I32X4], &[F64]),
1409                 (Opcode::FcvtLowFromSint, &[I64X2], &[F64]),
1410                 (Opcode::FcvtLowFromSint, &[I8], &[F32X4]),
1411                 (Opcode::FcvtLowFromSint, &[I16], &[F32X4]),
1412                 (Opcode::FcvtLowFromSint, &[I32], &[F32X4]),
1413                 (Opcode::FcvtLowFromSint, &[I64], &[F32X4]),
1414                 (Opcode::FcvtLowFromSint, &[I128], &[F32X4]),
1415                 (Opcode::FcvtLowFromSint, &[I8X16], &[F32X4]),
1416                 (Opcode::FcvtLowFromSint, &[I16X8], &[F32X4]),
1417                 (Opcode::FcvtLowFromSint, &[I32X4], &[F32X4]),
1418                 (Opcode::FcvtLowFromSint, &[I64X2], &[F32X4]),
1419                 (Opcode::FcvtLowFromSint, &[I8], &[F64X2]),
1420                 (Opcode::FcvtLowFromSint, &[I16], &[F64X2]),
1421                 (Opcode::FcvtLowFromSint, &[I32], &[F64X2]),
1422                 (Opcode::FcvtLowFromSint, &[I64], &[F64X2]),
1423                 (Opcode::FcvtLowFromSint, &[I128], &[F64X2]),
1424                 (Opcode::FcvtLowFromSint, &[I8X16], &[F64X2]),
1425                 (Opcode::FcvtLowFromSint, &[I16X8], &[F64X2]),
1426                 (Opcode::FcvtLowFromSint, &[I64X2], &[F64X2]),
1427             )
1428         })
1429         .collect()
1430 });
1431 
1432 fn inserter_for_format(fmt: InstructionFormat) -> OpcodeInserter {
1433     match fmt {
1434         InstructionFormat::AtomicCas => insert_atomic_cas,
1435         InstructionFormat::AtomicRmw => insert_atomic_rmw,
1436         InstructionFormat::Binary => insert_opcode,
1437         InstructionFormat::BinaryImm64 => todo!(),
1438         InstructionFormat::BinaryImm8 => insert_ins_ext_lane,
1439         InstructionFormat::Call => insert_call,
1440         InstructionFormat::CallIndirect => insert_call,
1441         InstructionFormat::CondTrap => todo!(),
1442         InstructionFormat::DynamicStackLoad => todo!(),
1443         InstructionFormat::DynamicStackStore => todo!(),
1444         InstructionFormat::FloatCompare => insert_cmp,
1445         InstructionFormat::FuncAddr => todo!(),
1446         InstructionFormat::IntAddTrap => todo!(),
1447         InstructionFormat::IntCompare => insert_cmp,
1448         InstructionFormat::IntCompareImm => todo!(),
1449         InstructionFormat::Load => insert_load_store,
1450         InstructionFormat::LoadNoOffset => insert_load_store,
1451         InstructionFormat::NullAry => insert_opcode,
1452         InstructionFormat::Shuffle => insert_shuffle,
1453         InstructionFormat::StackLoad => insert_stack_load,
1454         InstructionFormat::StackStore => insert_stack_store,
1455         InstructionFormat::Store => insert_load_store,
1456         InstructionFormat::StoreNoOffset => insert_load_store,
1457         InstructionFormat::TableAddr => todo!(),
1458         InstructionFormat::Ternary => insert_opcode,
1459         InstructionFormat::TernaryImm8 => insert_ins_ext_lane,
1460         InstructionFormat::Trap => todo!(),
1461         InstructionFormat::Unary => insert_opcode,
1462         InstructionFormat::UnaryConst => insert_const,
1463         InstructionFormat::UnaryGlobalValue => todo!(),
1464         InstructionFormat::UnaryIeee32 => insert_const,
1465         InstructionFormat::UnaryIeee64 => insert_const,
1466         InstructionFormat::UnaryImm => insert_const,
1467 
1468         InstructionFormat::BranchTable
1469         | InstructionFormat::Brif
1470         | InstructionFormat::Jump
1471         | InstructionFormat::MultiAry => {
1472             panic!(
1473                 "Control-flow instructions should be handled by 'insert_terminator': {:?}",
1474                 fmt
1475             )
1476         }
1477     }
1478 }
1479 
1480 pub struct FunctionGenerator<'r, 'data>
1481 where
1482     'data: 'r,
1483 {
1484     u: &'r mut Unstructured<'data>,
1485     config: &'r Config,
1486     resources: Resources,
1487     target_triple: Triple,
1488     name: UserFuncName,
1489     signature: Signature,
1490 }
1491 
1492 #[derive(Debug, Clone)]
1493 enum BlockTerminator {
1494     Return,
1495     Jump(Block),
1496     Br(Block, Block),
1497     BrTable(Block, Vec<Block>),
1498     Switch(Type, Block, HashMap<u128, Block>),
1499 }
1500 
1501 #[derive(Debug, Clone)]
1502 enum BlockTerminatorKind {
1503     Return,
1504     Jump,
1505     Br,
1506     BrTable,
1507     Switch,
1508 }
1509 
1510 #[derive(Default)]
1511 struct Resources {
1512     vars: HashMap<Type, Vec<Variable>>,
1513     blocks: Vec<(Block, BlockSignature)>,
1514     blocks_without_params: Vec<Block>,
1515     block_terminators: Vec<BlockTerminator>,
1516     func_refs: Vec<(Signature, SigRef, FuncRef)>,
1517     stack_slots: Vec<(StackSlot, StackSize)>,
1518     usercalls: Vec<(UserExternalName, Signature)>,
1519     libcalls: Vec<LibCall>,
1520 }
1521 
1522 impl Resources {
1523     /// Partitions blocks at `block`. Only blocks that can be targeted by branches are considered.
1524     ///
1525     /// The first slice includes all blocks up to and including `block`.
1526     /// The second slice includes all remaining blocks.
1527     fn partition_target_blocks(
1528         &self,
1529         block: Block,
1530     ) -> (&[(Block, BlockSignature)], &[(Block, BlockSignature)]) {
1531         // Blocks are stored in-order and have no gaps, this means that we can simply index them by
1532         // their number. We also need to exclude the entry block since it isn't a valid target.
1533         let target_blocks = &self.blocks[1..];
1534         target_blocks.split_at(block.as_u32() as usize)
1535     }
1536 
1537     /// Returns blocks forward of `block`. Only blocks that can be targeted by branches are considered.
1538     fn forward_blocks(&self, block: Block) -> &[(Block, BlockSignature)] {
1539         let (_, forward_blocks) = self.partition_target_blocks(block);
1540         forward_blocks
1541     }
1542 
1543     /// Generates a slice of `blocks_without_params` ahead of `block`
1544     fn forward_blocks_without_params(&self, block: Block) -> &[Block] {
1545         let partition_point = self.blocks_without_params.partition_point(|b| *b <= block);
1546         &self.blocks_without_params[partition_point..]
1547     }
1548 }
1549 
1550 impl<'r, 'data> FunctionGenerator<'r, 'data>
1551 where
1552     'data: 'r,
1553 {
1554     pub fn new(
1555         u: &'r mut Unstructured<'data>,
1556         config: &'r Config,
1557         target_triple: Triple,
1558         name: UserFuncName,
1559         signature: Signature,
1560         usercalls: Vec<(UserExternalName, Signature)>,
1561         libcalls: Vec<LibCall>,
1562     ) -> Self {
1563         Self {
1564             u,
1565             config,
1566             resources: Resources {
1567                 usercalls,
1568                 libcalls,
1569                 ..Resources::default()
1570             },
1571             target_triple,
1572             name,
1573             signature,
1574         }
1575     }
1576 
1577     /// Generates a random value for config `param`
1578     fn param(&mut self, param: &RangeInclusive<usize>) -> Result<usize> {
1579         Ok(self.u.int_in_range(param.clone())?)
1580     }
1581 
1582     fn system_callconv(&mut self) -> CallConv {
1583         // TODO: This currently only runs on linux, so this is the only choice
1584         // We should improve this once we generate flags and targets
1585         CallConv::SystemV
1586     }
1587 
1588     /// Finds a stack slot with size of at least n bytes
1589     fn stack_slot_with_size(&mut self, n: u32) -> Result<(StackSlot, StackSize)> {
1590         let first = self
1591             .resources
1592             .stack_slots
1593             .partition_point(|&(_slot, size)| size < n);
1594         Ok(*self.u.choose(&self.resources.stack_slots[first..])?)
1595     }
1596 
1597     /// Generates an address that should allow for a store or a load.
1598     ///
1599     /// Addresses aren't generated like other values. They are never stored in variables so that
1600     /// we don't run the risk of returning them from a function, which would make the fuzzer
1601     /// complain since they are different from the interpreter to the backend.
1602     ///
1603     /// `min_size`: Controls the amount of space that the address should have.
1604     ///
1605     /// `aligned`: When passed as true, the resulting address is guaranteed to be aligned
1606     /// on an 8 byte boundary.
1607     ///
1608     /// Returns a valid address and the maximum possible offset that still respects `min_size`.
1609     fn generate_load_store_address(
1610         &mut self,
1611         builder: &mut FunctionBuilder,
1612         min_size: u32,
1613         aligned: bool,
1614     ) -> Result<(Value, u32)> {
1615         // TODO: Currently our only source of addresses is stack_addr, but we
1616         // should add global_value, symbol_value eventually
1617         let (addr, available_size) = {
1618             let (ss, slot_size) = self.stack_slot_with_size(min_size)?;
1619 
1620             // stack_slot_with_size guarantees that slot_size >= min_size
1621             let max_offset = slot_size - min_size;
1622             let offset = if aligned {
1623                 self.u.int_in_range(0..=max_offset / min_size)? * min_size
1624             } else {
1625                 self.u.int_in_range(0..=max_offset)?
1626             };
1627 
1628             let base_addr = builder.ins().stack_addr(I64, ss, offset as i32);
1629             let available_size = slot_size.saturating_sub(offset);
1630             (base_addr, available_size)
1631         };
1632 
1633         // TODO: Insert a bunch of amode opcodes here to modify the address!
1634 
1635         // Now that we have an address and a size, we just choose a random offset to return to the
1636         // caller. Preserving min_size bytes.
1637         let max_offset = available_size.saturating_sub(min_size);
1638         Ok((addr, max_offset))
1639     }
1640 
1641     // Generates an address and memflags for a load or store.
1642     fn generate_address_and_memflags(
1643         &mut self,
1644         builder: &mut FunctionBuilder,
1645         min_size: u32,
1646         is_atomic: bool,
1647     ) -> Result<(Value, MemFlags, Offset32)> {
1648         // Should we generate an aligned address
1649         // Some backends have issues with unaligned atomics.
1650         // AArch64: https://github.com/bytecodealliance/wasmtime/issues/5483
1651         // RISCV: https://github.com/bytecodealliance/wasmtime/issues/5882
1652         let requires_aligned_atomics = matches!(
1653             self.target_triple.architecture,
1654             Architecture::Aarch64(_) | Architecture::Riscv64(_)
1655         );
1656         let aligned = if is_atomic && requires_aligned_atomics {
1657             true
1658         } else if min_size > 8 {
1659             // TODO: We currently can't guarantee that a stack_slot will be aligned on a 16 byte
1660             // boundary. We don't have a way to specify alignment when creating stack slots, and
1661             // cranelift only guarantees 8 byte alignment between stack slots.
1662             // See: https://github.com/bytecodealliance/wasmtime/issues/5922#issuecomment-1457926624
1663             false
1664         } else {
1665             bool::arbitrary(self.u)?
1666         };
1667 
1668         let mut flags = MemFlags::new();
1669         // Even if we picked an aligned address, we can always generate unaligned memflags
1670         if aligned && bool::arbitrary(self.u)? {
1671             flags.set_aligned();
1672         }
1673         // If the address is aligned, then we know it won't trap
1674         if aligned && bool::arbitrary(self.u)? {
1675             flags.set_notrap();
1676         }
1677 
1678         let (address, max_offset) = self.generate_load_store_address(builder, min_size, aligned)?;
1679 
1680         // Pick an offset to pass into the load/store.
1681         let offset = if aligned {
1682             0
1683         } else {
1684             self.u.int_in_range(0..=max_offset)? as i32
1685         }
1686         .into();
1687 
1688         Ok((address, flags, offset))
1689     }
1690 
1691     /// Get a variable of type `ty` from the current function
1692     fn get_variable_of_type(&mut self, ty: Type) -> Result<Variable> {
1693         let opts = self.resources.vars.get(&ty).map_or(&[][..], Vec::as_slice);
1694         let var = self.u.choose(opts)?;
1695         Ok(*var)
1696     }
1697 
1698     /// Generates an instruction(`iconst`/`fconst`/etc...) to introduce a constant value
1699     fn generate_const(&mut self, builder: &mut FunctionBuilder, ty: Type) -> Result<Value> {
1700         Ok(match self.u.datavalue(ty)? {
1701             DataValue::I8(i) => builder.ins().iconst(ty, i as i64),
1702             DataValue::I16(i) => builder.ins().iconst(ty, i as i64),
1703             DataValue::I32(i) => builder.ins().iconst(ty, i as i64),
1704             DataValue::I64(i) => builder.ins().iconst(ty, i as i64),
1705             DataValue::I128(i) => {
1706                 let hi = builder.ins().iconst(I64, (i >> 64) as i64);
1707                 let lo = builder.ins().iconst(I64, i as i64);
1708                 builder.ins().iconcat(lo, hi)
1709             }
1710             DataValue::F32(f) => builder.ins().f32const(f),
1711             DataValue::F64(f) => builder.ins().f64const(f),
1712             DataValue::V128(bytes) => {
1713                 let data = bytes.to_vec().into();
1714                 let handle = builder.func.dfg.constants.insert(data);
1715                 builder.ins().vconst(ty, handle)
1716             }
1717             _ => unimplemented!(),
1718         })
1719     }
1720 
1721     /// Chooses a random block which can be targeted by a jump / branch.
1722     /// This means any block that is not the first block.
1723     fn generate_target_block(&mut self, source_block: Block) -> Result<Block> {
1724         // We try to mostly generate forward branches to avoid generating an excessive amount of
1725         // infinite loops. But they are still important, so give them a small chance of existing.
1726         let (backwards_blocks, forward_blocks) =
1727             self.resources.partition_target_blocks(source_block);
1728         let ratio = self.config.backwards_branch_ratio;
1729         let block_targets = if !backwards_blocks.is_empty() && self.u.ratio(ratio.0, ratio.1)? {
1730             backwards_blocks
1731         } else {
1732             forward_blocks
1733         };
1734         assert!(!block_targets.is_empty());
1735 
1736         let (block, _) = self.u.choose(block_targets)?.clone();
1737         Ok(block)
1738     }
1739 
1740     fn generate_values_for_block(
1741         &mut self,
1742         builder: &mut FunctionBuilder,
1743         block: Block,
1744     ) -> Result<Vec<Value>> {
1745         let (_, sig) = self.resources.blocks[block.as_u32() as usize].clone();
1746         self.generate_values_for_signature(builder, sig.iter().copied())
1747     }
1748 
1749     fn generate_values_for_signature<I: Iterator<Item = Type>>(
1750         &mut self,
1751         builder: &mut FunctionBuilder,
1752         signature: I,
1753     ) -> Result<Vec<Value>> {
1754         signature
1755             .map(|ty| {
1756                 let var = self.get_variable_of_type(ty)?;
1757                 let val = builder.use_var(var);
1758                 Ok(val)
1759             })
1760             .collect()
1761     }
1762 
1763     /// The terminator that we need to insert has already been picked ahead of time
1764     /// we just need to build the instructions for it
1765     fn insert_terminator(
1766         &mut self,
1767         builder: &mut FunctionBuilder,
1768         source_block: Block,
1769     ) -> Result<()> {
1770         let terminator = self.resources.block_terminators[source_block.as_u32() as usize].clone();
1771 
1772         match terminator {
1773             BlockTerminator::Return => {
1774                 let types: Vec<Type> = {
1775                     let rets = &builder.func.signature.returns;
1776                     rets.iter().map(|p| p.value_type).collect()
1777                 };
1778                 let vals = self.generate_values_for_signature(builder, types.into_iter())?;
1779 
1780                 builder.ins().return_(&vals[..]);
1781             }
1782             BlockTerminator::Jump(target) => {
1783                 let args = self.generate_values_for_block(builder, target)?;
1784                 builder.ins().jump(target, &args[..]);
1785             }
1786             BlockTerminator::Br(left, right) => {
1787                 let left_args = self.generate_values_for_block(builder, left)?;
1788                 let right_args = self.generate_values_for_block(builder, right)?;
1789 
1790                 let condbr_types = [I8, I16, I32, I64, I128];
1791                 let _type = *self.u.choose(&condbr_types[..])?;
1792                 let val = builder.use_var(self.get_variable_of_type(_type)?);
1793                 builder
1794                     .ins()
1795                     .brif(val, left, &left_args[..], right, &right_args[..]);
1796             }
1797             BlockTerminator::BrTable(default, targets) => {
1798                 // Create jump tables on demand
1799                 let mut jt = Vec::with_capacity(targets.len());
1800                 for block in targets {
1801                     let args = self.generate_values_for_block(builder, block)?;
1802                     jt.push(builder.func.dfg.block_call(block, &args))
1803                 }
1804 
1805                 let args = self.generate_values_for_block(builder, default)?;
1806                 let jt_data = JumpTableData::new(builder.func.dfg.block_call(default, &args), &jt);
1807                 let jt = builder.create_jump_table(jt_data);
1808 
1809                 // br_table only supports I32
1810                 let val = builder.use_var(self.get_variable_of_type(I32)?);
1811 
1812                 builder.ins().br_table(val, jt);
1813             }
1814             BlockTerminator::Switch(_type, default, entries) => {
1815                 let mut switch = Switch::new();
1816                 for (&entry, &block) in entries.iter() {
1817                     switch.set_entry(entry, block);
1818                 }
1819 
1820                 let switch_val = builder.use_var(self.get_variable_of_type(_type)?);
1821 
1822                 switch.emit(builder, switch_val, default);
1823             }
1824         }
1825 
1826         Ok(())
1827     }
1828 
1829     /// Fills the current block with random instructions
1830     fn generate_instructions(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1831         for _ in 0..self.param(&self.config.instructions_per_block)? {
1832             let (op, args, rets) = self.u.choose(&OPCODE_SIGNATURES)?;
1833 
1834             // We filter out instructions that aren't supported by the target at this point instead
1835             // of building a single vector of valid instructions at the beginning of function
1836             // generation, to avoid invalidating the corpus when instructions are enabled/disabled.
1837             if !valid_for_target(&self.target_triple, *op, &args, &rets) {
1838                 return Err(arbitrary::Error::IncorrectFormat.into());
1839             }
1840 
1841             let inserter = inserter_for_format(op.format());
1842             inserter(self, builder, *op, &args, &rets)?;
1843         }
1844 
1845         Ok(())
1846     }
1847 
1848     fn generate_funcrefs(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1849         let usercalls: Vec<(ExternalName, Signature)> = self
1850             .resources
1851             .usercalls
1852             .iter()
1853             .map(|(name, signature)| {
1854                 let user_func_ref = builder.func.declare_imported_user_function(name.clone());
1855                 let name = ExternalName::User(user_func_ref);
1856                 (name, signature.clone())
1857             })
1858             .collect();
1859 
1860         let lib_callconv = self.system_callconv();
1861         let libcalls: Vec<(ExternalName, Signature)> = self
1862             .resources
1863             .libcalls
1864             .iter()
1865             .map(|libcall| {
1866                 let signature = libcall.signature(lib_callconv);
1867                 let name = ExternalName::LibCall(*libcall);
1868                 (name, signature)
1869             })
1870             .collect();
1871 
1872         for (name, signature) in usercalls.into_iter().chain(libcalls) {
1873             let sig_ref = builder.import_signature(signature.clone());
1874             let func_ref = builder.import_function(ExtFuncData {
1875                 name,
1876                 signature: sig_ref,
1877                 colocated: self.u.arbitrary()?,
1878             });
1879 
1880             self.resources
1881                 .func_refs
1882                 .push((signature, sig_ref, func_ref));
1883         }
1884 
1885         Ok(())
1886     }
1887 
1888     fn generate_stack_slots(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1889         for _ in 0..self.param(&self.config.static_stack_slots_per_function)? {
1890             let bytes = self.param(&self.config.static_stack_slot_size)? as u32;
1891             let ss_data = StackSlotData::new(StackSlotKind::ExplicitSlot, bytes);
1892             let slot = builder.create_sized_stack_slot(ss_data);
1893             self.resources.stack_slots.push((slot, bytes));
1894         }
1895 
1896         self.resources
1897             .stack_slots
1898             .sort_unstable_by_key(|&(_slot, bytes)| bytes);
1899 
1900         Ok(())
1901     }
1902 
1903     /// Zero initializes the stack slot by inserting `stack_store`'s.
1904     fn initialize_stack_slots(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1905         let i8_zero = builder.ins().iconst(I8, 0);
1906         let i16_zero = builder.ins().iconst(I16, 0);
1907         let i32_zero = builder.ins().iconst(I32, 0);
1908         let i64_zero = builder.ins().iconst(I64, 0);
1909         let i128_zero = builder.ins().uextend(I128, i64_zero);
1910 
1911         for &(slot, init_size) in self.resources.stack_slots.iter() {
1912             let mut size = init_size;
1913 
1914             // Insert the largest available store for the remaining size.
1915             while size != 0 {
1916                 let offset = (init_size - size) as i32;
1917                 let (val, filled) = match size {
1918                     sz if sz / 16 > 0 => (i128_zero, 16),
1919                     sz if sz / 8 > 0 => (i64_zero, 8),
1920                     sz if sz / 4 > 0 => (i32_zero, 4),
1921                     sz if sz / 2 > 0 => (i16_zero, 2),
1922                     _ => (i8_zero, 1),
1923                 };
1924                 builder.ins().stack_store(val, slot, offset);
1925                 size -= filled;
1926             }
1927         }
1928         Ok(())
1929     }
1930 
1931     /// Creates a random amount of blocks in this function
1932     fn generate_blocks(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
1933         let extra_block_count = self.param(&self.config.blocks_per_function)?;
1934 
1935         // We must always have at least one block, so we generate the "extra" blocks and add 1 for
1936         // the entry block.
1937         let block_count = 1 + extra_block_count;
1938 
1939         // Blocks need to be sorted in ascending order
1940         self.resources.blocks = (0..block_count)
1941             .map(|i| {
1942                 let is_entry = i == 0;
1943                 let block = builder.create_block();
1944 
1945                 // Optionally mark blocks that are not the entry block as cold
1946                 if !is_entry {
1947                     if bool::arbitrary(self.u)? {
1948                         builder.set_cold_block(block);
1949                     }
1950                 }
1951 
1952                 // The first block has to have the function signature, but for the rest of them we generate
1953                 // a random signature;
1954                 if is_entry {
1955                     builder.append_block_params_for_function_params(block);
1956                     Ok((
1957                         block,
1958                         self.signature.params.iter().map(|a| a.value_type).collect(),
1959                     ))
1960                 } else {
1961                     let sig = self.generate_block_signature()?;
1962                     sig.iter().for_each(|ty| {
1963                         builder.append_block_param(block, *ty);
1964                     });
1965                     Ok((block, sig))
1966                 }
1967             })
1968             .collect::<Result<Vec<_>>>()?;
1969 
1970         // Valid blocks for jump tables have to have no parameters in the signature, and must also
1971         // not be the first block.
1972         self.resources.blocks_without_params = self.resources.blocks[1..]
1973             .iter()
1974             .filter(|(_, sig)| sig.len() == 0)
1975             .map(|(b, _)| *b)
1976             .collect();
1977 
1978         // Compute the block CFG
1979         //
1980         // cranelift-frontend requires us to never generate unreachable blocks
1981         // To ensure this property we start by constructing a main "spine" of blocks. So block1 can
1982         // always jump to block2, and block2 can always jump to block3, etc...
1983         //
1984         // That is not a very interesting CFG, so we introduce variations on that, but always
1985         // ensuring that the property of pointing to the next block is maintained whatever the
1986         // branching mechanism we use.
1987         let blocks = self.resources.blocks.clone();
1988         self.resources.block_terminators = blocks
1989             .iter()
1990             .map(|&(block, _)| {
1991                 let next_block = Block::with_number(block.as_u32() + 1).unwrap();
1992                 let forward_blocks = self.resources.forward_blocks(block);
1993                 let paramless_targets = self.resources.forward_blocks_without_params(block);
1994                 let has_paramless_targets = !paramless_targets.is_empty();
1995                 let next_block_is_paramless = paramless_targets.contains(&next_block);
1996 
1997                 let mut valid_terminators = vec![];
1998 
1999                 if forward_blocks.is_empty() {
2000                     // Return is only valid on the last block.
2001                     valid_terminators.push(BlockTerminatorKind::Return);
2002                 } else {
2003                     // If we have more than one block we can allow terminators that target blocks.
2004                     // TODO: We could add some kind of BrReturn here, to explore edges where we
2005                     // exit in the middle of the function
2006                     valid_terminators.extend_from_slice(&[
2007                         BlockTerminatorKind::Jump,
2008                         BlockTerminatorKind::Br,
2009                         BlockTerminatorKind::BrTable,
2010                     ]);
2011                 }
2012 
2013                 // As the Switch interface only allows targeting blocks without params we need
2014                 // to ensure that the next block has no params, since that one is guaranteed to be
2015                 // picked in either case.
2016                 if has_paramless_targets && next_block_is_paramless {
2017                     valid_terminators.push(BlockTerminatorKind::Switch);
2018                 }
2019 
2020                 let terminator = self.u.choose(&valid_terminators)?;
2021 
2022                 // Choose block targets for the terminators that we picked above
2023                 Ok(match terminator {
2024                     BlockTerminatorKind::Return => BlockTerminator::Return,
2025                     BlockTerminatorKind::Jump => BlockTerminator::Jump(next_block),
2026                     BlockTerminatorKind::Br => {
2027                         BlockTerminator::Br(next_block, self.generate_target_block(block)?)
2028                     }
2029                     // TODO: Allow generating backwards branches here
2030                     BlockTerminatorKind::BrTable => {
2031                         // Make the default the next block, and then we don't have to worry
2032                         // that we can reach it via the targets
2033                         let default = next_block;
2034 
2035                         let target_count = self.param(&self.config.jump_table_entries)?;
2036                         let targets = Result::from_iter(
2037                             (0..target_count).map(|_| self.generate_target_block(block)),
2038                         )?;
2039 
2040                         BlockTerminator::BrTable(default, targets)
2041                     }
2042                     BlockTerminatorKind::Switch => {
2043                         // Make the default the next block, and then we don't have to worry
2044                         // that we can reach it via the entries below
2045                         let default_block = next_block;
2046 
2047                         let _type = *self.u.choose(&[I8, I16, I32, I64, I128][..])?;
2048 
2049                         // Build this into a HashMap since we cannot have duplicate entries.
2050                         let mut entries = HashMap::new();
2051                         for _ in 0..self.param(&self.config.switch_cases)? {
2052                             // The Switch API only allows for entries that are addressable by the index type
2053                             // so we need to limit the range of values that we generate.
2054                             let (ty_min, ty_max) = _type.bounds(false);
2055                             let range_start = self.u.int_in_range(ty_min..=ty_max)?;
2056 
2057                             // We can either insert a contiguous range of blocks or a individual block
2058                             // This is done because the Switch API specializes contiguous ranges.
2059                             let range_size = if bool::arbitrary(self.u)? {
2060                                 1
2061                             } else {
2062                                 self.param(&self.config.switch_max_range_size)?
2063                             } as u128;
2064 
2065                             // Build the switch entries
2066                             for i in 0..range_size {
2067                                 let index = range_start.wrapping_add(i) % ty_max;
2068                                 let block = *self
2069                                     .u
2070                                     .choose(self.resources.forward_blocks_without_params(block))?;
2071 
2072                                 entries.insert(index, block);
2073                             }
2074                         }
2075 
2076                         BlockTerminator::Switch(_type, default_block, entries)
2077                     }
2078                 })
2079             })
2080             .collect::<Result<_>>()?;
2081 
2082         Ok(())
2083     }
2084 
2085     fn generate_block_signature(&mut self) -> Result<BlockSignature> {
2086         let param_count = self.param(&self.config.block_signature_params)?;
2087 
2088         let mut params = Vec::with_capacity(param_count);
2089         for _ in 0..param_count {
2090             params.push(self.u._type(self.target_triple.architecture)?);
2091         }
2092         Ok(params)
2093     }
2094 
2095     fn build_variable_pool(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
2096         let block = builder.current_block().unwrap();
2097 
2098         // Define variables for the function signature
2099         let mut vars: Vec<_> = builder
2100             .func
2101             .signature
2102             .params
2103             .iter()
2104             .map(|param| param.value_type)
2105             .zip(builder.block_params(block).iter().copied())
2106             .collect();
2107 
2108         // Create a pool of vars that are going to be used in this function
2109         for _ in 0..self.param(&self.config.vars_per_function)? {
2110             let ty = self.u._type(self.target_triple.architecture)?;
2111             let value = self.generate_const(builder, ty)?;
2112             vars.push((ty, value));
2113         }
2114 
2115         for (id, (ty, value)) in vars.into_iter().enumerate() {
2116             let var = Variable::new(id);
2117             builder.declare_var(var, ty);
2118             builder.def_var(var, value);
2119             self.resources
2120                 .vars
2121                 .entry(ty)
2122                 .or_insert_with(Vec::new)
2123                 .push(var);
2124         }
2125 
2126         Ok(())
2127     }
2128 
2129     /// We generate a function in multiple stages:
2130     ///
2131     /// * First we generate a random number of empty blocks
2132     /// * Then we generate a random pool of variables to be used throughout the function
2133     /// * We then visit each block and generate random instructions
2134     ///
2135     /// Because we generate all blocks and variables up front we already know everything that
2136     /// we need when generating instructions (i.e. jump targets / variables)
2137     pub fn generate(mut self) -> Result<Function> {
2138         let mut fn_builder_ctx = FunctionBuilderContext::new();
2139         let mut func = Function::with_name_signature(self.name.clone(), self.signature.clone());
2140 
2141         let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx);
2142 
2143         self.generate_blocks(&mut builder)?;
2144 
2145         // Function preamble
2146         self.generate_funcrefs(&mut builder)?;
2147         self.generate_stack_slots(&mut builder)?;
2148 
2149         // Main instruction generation loop
2150         for (block, block_sig) in self.resources.blocks.clone().into_iter() {
2151             let is_block0 = block.as_u32() == 0;
2152             builder.switch_to_block(block);
2153 
2154             if is_block0 {
2155                 // The first block is special because we must create variables both for the
2156                 // block signature and for the variable pool. Additionally, we must also define
2157                 // initial values for all variables that are not the function signature.
2158                 self.build_variable_pool(&mut builder)?;
2159 
2160                 // Stack slots have random bytes at the beginning of the function
2161                 // initialize them to a constant value so that execution stays predictable.
2162                 self.initialize_stack_slots(&mut builder)?;
2163             } else {
2164                 // Define variables for the block params
2165                 for (i, ty) in block_sig.iter().enumerate() {
2166                     let var = self.get_variable_of_type(*ty)?;
2167                     let block_param = builder.block_params(block)[i];
2168                     builder.def_var(var, block_param);
2169                 }
2170             }
2171 
2172             // Generate block instructions
2173             self.generate_instructions(&mut builder)?;
2174 
2175             // Insert a terminator to safely exit the block
2176             self.insert_terminator(&mut builder, block)?;
2177         }
2178 
2179         builder.seal_all_blocks();
2180         builder.finalize();
2181 
2182         Ok(func)
2183     }
2184 }
2185