1a8ce7f12SAndrew Brown //! Generate Wasm modules that contain a single instruction.
2a8ce7f12SAndrew Brown 
35ec92d59SAndrew Brown use super::ModuleConfig;
45ec92d59SAndrew Brown use arbitrary::Unstructured;
5a8ce7f12SAndrew Brown use wasm_encoder::{
6a8ce7f12SAndrew Brown     CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction, Module,
7a8ce7f12SAndrew Brown     TypeSection, ValType,
8a8ce7f12SAndrew Brown };
9a8ce7f12SAndrew Brown 
10a8ce7f12SAndrew Brown /// The name of the function generated by this module.
11a8ce7f12SAndrew Brown const FUNCTION_NAME: &'static str = "test";
12a8ce7f12SAndrew Brown 
13a8ce7f12SAndrew Brown /// Configure a single instruction module.
14a8ce7f12SAndrew Brown ///
15a8ce7f12SAndrew Brown /// By explicitly defining the parameter and result types (versus generating the
16a8ce7f12SAndrew Brown /// module directly), we can more easily generate values of the right type.
175ec92d59SAndrew Brown #[derive(Clone)]
18a8ce7f12SAndrew Brown pub struct SingleInstModule<'a> {
19a8ce7f12SAndrew Brown     instruction: Instruction<'a>,
20a8ce7f12SAndrew Brown     parameters: &'a [ValType],
21a8ce7f12SAndrew Brown     results: &'a [ValType],
225ec92d59SAndrew Brown     feature: fn(&ModuleConfig) -> bool,
23cd982c5aSAndrew Brown     canonicalize_nan: Option<NanType>,
24cd982c5aSAndrew Brown }
25cd982c5aSAndrew Brown 
26cd982c5aSAndrew Brown /// Valid types for NaN canonicalization.
27cd982c5aSAndrew Brown ///
28cd982c5aSAndrew Brown /// When fuzzing floating point values, a NaN result can have non-deterministic
29cd982c5aSAndrew Brown /// bits in the payload. In order to compare these results, [`SingleInstModule`]
30cd982c5aSAndrew Brown /// can convert any NaN values (or NaN lanes) to a canonical NaN value for any
31cd982c5aSAndrew Brown /// of these types.
32cd982c5aSAndrew Brown #[derive(Clone)]
33cd982c5aSAndrew Brown enum NanType {
3445b60bd6SAlex Crichton     #[expect(dead_code, reason = "expected to be used in the future")]
35cd982c5aSAndrew Brown     F32,
3645b60bd6SAlex Crichton     #[expect(dead_code, reason = "expected to be used in the future")]
37cd982c5aSAndrew Brown     F64,
38cd982c5aSAndrew Brown     F32x4,
39cd982c5aSAndrew Brown     F64x2,
40a8ce7f12SAndrew Brown }
41a8ce7f12SAndrew Brown 
42a8ce7f12SAndrew Brown impl<'a> SingleInstModule<'a> {
435ec92d59SAndrew Brown     /// Choose a single-instruction module that matches `config`.
new(u: &mut Unstructured<'a>, config: &ModuleConfig) -> arbitrary::Result<&'a Self>44543a4879SAlex Crichton     pub fn new(u: &mut Unstructured<'a>, config: &ModuleConfig) -> arbitrary::Result<&'a Self> {
455ec92d59SAndrew Brown         // Only select instructions that match the `ModuleConfig`.
465ec92d59SAndrew Brown         let instructions = &INSTRUCTIONS
475ec92d59SAndrew Brown             .iter()
485ec92d59SAndrew Brown             .filter(|i| (i.feature)(config))
495ec92d59SAndrew Brown             .collect::<Vec<_>>();
505ec92d59SAndrew Brown         u.choose(&instructions[..]).copied()
515ec92d59SAndrew Brown     }
525ec92d59SAndrew Brown 
535ec92d59SAndrew Brown     /// Encode a binary Wasm module with a single exported function, `test`,
54a8ce7f12SAndrew Brown     /// that executes the single instruction.
to_bytes(&self) -> Vec<u8>555ec92d59SAndrew Brown     pub fn to_bytes(&self) -> Vec<u8> {
56a8ce7f12SAndrew Brown         let mut module = Module::new();
57a8ce7f12SAndrew Brown 
58a8ce7f12SAndrew Brown         // Encode the type section.
59a8ce7f12SAndrew Brown         let mut types = TypeSection::new();
606844ed1aSAlex Crichton         types.ty().function(
61a8ce7f12SAndrew Brown             self.parameters.iter().cloned(),
62a8ce7f12SAndrew Brown             self.results.iter().cloned(),
63a8ce7f12SAndrew Brown         );
64a8ce7f12SAndrew Brown         module.section(&types);
65a8ce7f12SAndrew Brown 
66a8ce7f12SAndrew Brown         // Encode the function section.
67a8ce7f12SAndrew Brown         let mut functions = FunctionSection::new();
68a8ce7f12SAndrew Brown         let type_index = 0;
69a8ce7f12SAndrew Brown         functions.function(type_index);
70a8ce7f12SAndrew Brown         module.section(&functions);
71a8ce7f12SAndrew Brown 
72a8ce7f12SAndrew Brown         // Encode the export section.
73a8ce7f12SAndrew Brown         let mut exports = ExportSection::new();
74a8ce7f12SAndrew Brown         exports.export(FUNCTION_NAME, ExportKind::Func, 0);
75a8ce7f12SAndrew Brown         module.section(&exports);
76a8ce7f12SAndrew Brown 
77a8ce7f12SAndrew Brown         // Encode the code section.
78a8ce7f12SAndrew Brown         let mut codes = CodeSection::new();
79cd982c5aSAndrew Brown 
80cd982c5aSAndrew Brown         // Set up the single-instruction function. Note that if we have chosen
81cd982c5aSAndrew Brown         // to canonicalize NaNs, this function will contain more than one
82cd982c5aSAndrew Brown         // instruction and the function will need a scratch local.
83cd982c5aSAndrew Brown         let mut f = if let Some(ty) = &self.canonicalize_nan {
84cd982c5aSAndrew Brown             Function::new(match ty {
85cd982c5aSAndrew Brown                 NanType::F32 => vec![(1, ValType::F32)],
86cd982c5aSAndrew Brown                 NanType::F64 => vec![(1, ValType::F64)],
87cd982c5aSAndrew Brown                 NanType::F32x4 | NanType::F64x2 => vec![(1, ValType::V128)],
88cd982c5aSAndrew Brown             })
89cd982c5aSAndrew Brown         } else {
90cd982c5aSAndrew Brown             Function::new([])
91cd982c5aSAndrew Brown         };
92cd982c5aSAndrew Brown 
93cd982c5aSAndrew Brown         // Retrieve the input values and execute the chosen instruction.
94a8ce7f12SAndrew Brown         for (index, _) in self.parameters.iter().enumerate() {
95a8ce7f12SAndrew Brown             f.instruction(&Instruction::LocalGet(index as u32));
96a8ce7f12SAndrew Brown         }
97a8ce7f12SAndrew Brown         f.instruction(&self.instruction);
98cd982c5aSAndrew Brown 
99cd982c5aSAndrew Brown         // If we have configured to canonicalize NaNs, we add a sequence that
100cd982c5aSAndrew Brown         // masks off the NaN payload bits to make them 0s (i.e., a canonical
101cd982c5aSAndrew Brown         // NaN). This sequence is adapted from wasm-smiths version; see
102cd982c5aSAndrew Brown         // https://github.com/bytecodealliance/wasm-tools/blob/6c127a6/crates/wasm-smith/src/core/code_builder.rs#L927.
103cd982c5aSAndrew Brown         if let Some(ty) = &self.canonicalize_nan {
104cd982c5aSAndrew Brown             // Save the previous instruction's result into the scratch local.
105cd982c5aSAndrew Brown             // This also leaves a value on the stack as for the `select`
106cd982c5aSAndrew Brown             // instruction.
107cd982c5aSAndrew Brown             let local = self.parameters.len() as u32;
108cd982c5aSAndrew Brown             f.instruction(&Instruction::LocalTee(local));
109cd982c5aSAndrew Brown 
110cd982c5aSAndrew Brown             // The other input to the `select` below--a canonical NaN. Note how
111cd982c5aSAndrew Brown             // the payload bits of the NaN are cleared.
112cd982c5aSAndrew Brown             const CANON_32BIT_NAN: u32 = 0b01111111110000000000000000000000;
113cd982c5aSAndrew Brown             const CANON_64BIT_NAN: u64 =
114cd982c5aSAndrew Brown                 0b0111111111111000000000000000000000000000000000000000000000000000;
115cd982c5aSAndrew Brown             let mask = match ty {
116*e682be4eSAlex Crichton                 NanType::F32 => Instruction::F32Const(f32::from_bits(CANON_32BIT_NAN).into()),
117*e682be4eSAlex Crichton                 NanType::F64 => Instruction::F64Const(f64::from_bits(CANON_64BIT_NAN).into()),
118cd982c5aSAndrew Brown                 NanType::F32x4 => {
119cd982c5aSAndrew Brown                     let nan = CANON_32BIT_NAN as i128;
120cd982c5aSAndrew Brown                     Instruction::V128Const(nan | (nan << 32) | (nan << 64) | (nan << 96))
121cd982c5aSAndrew Brown                 }
122cd982c5aSAndrew Brown                 NanType::F64x2 => {
123cd982c5aSAndrew Brown                     let nan = CANON_64BIT_NAN as i128;
124cd982c5aSAndrew Brown                     Instruction::V128Const(nan | (nan << 64))
125cd982c5aSAndrew Brown                 }
126cd982c5aSAndrew Brown             };
127cd982c5aSAndrew Brown             f.instruction(&mask);
128cd982c5aSAndrew Brown 
129cd982c5aSAndrew Brown             // The `select` condition. NaNs never equal each other, so here the
130cd982c5aSAndrew Brown             // result value is compared against itself.
131cd982c5aSAndrew Brown             f.instruction(&Instruction::LocalGet(local));
132cd982c5aSAndrew Brown             f.instruction(&Instruction::LocalGet(local));
133cd982c5aSAndrew Brown             f.instruction(match ty {
134cd982c5aSAndrew Brown                 NanType::F32 => &Instruction::F32Eq,
135cd982c5aSAndrew Brown                 NanType::F64 => &Instruction::F64Eq,
136cd982c5aSAndrew Brown                 NanType::F32x4 => &Instruction::F32x4Eq,
137cd982c5aSAndrew Brown                 NanType::F64x2 => &Instruction::F64x2Eq,
138cd982c5aSAndrew Brown             });
139cd982c5aSAndrew Brown 
140cd982c5aSAndrew Brown             // Select the result. If the condition is nonzero (i.e., the float
141cd982c5aSAndrew Brown             // is equal to itself) it picks the original value; otherwise, if
142cd982c5aSAndrew Brown             // zero (i.e., the float is a NaN) it picks the canonical NaN value.
143cd982c5aSAndrew Brown             f.instruction(match ty {
144cd982c5aSAndrew Brown                 NanType::F32 | NanType::F64 => &Instruction::Select,
145cd982c5aSAndrew Brown                 NanType::F32x4 | NanType::F64x2 => &Instruction::V128Bitselect,
146cd982c5aSAndrew Brown             });
147cd982c5aSAndrew Brown         }
148cd982c5aSAndrew Brown 
149cd982c5aSAndrew Brown         // Wrap up the function and section.
150a8ce7f12SAndrew Brown         f.instruction(&Instruction::End);
151a8ce7f12SAndrew Brown         codes.function(&f);
152a8ce7f12SAndrew Brown         module.section(&codes);
153a8ce7f12SAndrew Brown 
154a8ce7f12SAndrew Brown         // Extract the encoded Wasm bytes for this module.
155a8ce7f12SAndrew Brown         module.finish()
156a8ce7f12SAndrew Brown     }
157a8ce7f12SAndrew Brown }
158a8ce7f12SAndrew Brown 
159a8ce7f12SAndrew Brown // MACROS
160a8ce7f12SAndrew Brown //
161a8ce7f12SAndrew Brown // These macros make it a bit easier to define the instructions available for
162a8ce7f12SAndrew Brown // generation. The idea is that, with these macros, we can define the list of
163a8ce7f12SAndrew Brown // instructions compactly and allow for easier changes to the Rust code (e.g.,
164a8ce7f12SAndrew Brown // `SingleInstModule`).
165a8ce7f12SAndrew Brown 
16672ded108SAlex Crichton macro_rules! valtypes {
16772ded108SAlex Crichton     (@list ($($ty:tt),*)) => {&[$(valtypes!(@one $ty)),*]};
16872ded108SAlex Crichton     (@list $ty:tt) => {&[valtypes!(@one $ty)]};
16972ded108SAlex Crichton     (@one i32) => {
170a8ce7f12SAndrew Brown         ValType::I32
171a8ce7f12SAndrew Brown     };
17272ded108SAlex Crichton     (@one i64) => {
173a8ce7f12SAndrew Brown         ValType::I64
174a8ce7f12SAndrew Brown     };
17572ded108SAlex Crichton     (@one f32) => {
176a8ce7f12SAndrew Brown         ValType::F32
177a8ce7f12SAndrew Brown     };
17872ded108SAlex Crichton     (@one f64) => {
179a8ce7f12SAndrew Brown         ValType::F64
180a8ce7f12SAndrew Brown     };
18172ded108SAlex Crichton     (@one v128) => {
182cd982c5aSAndrew Brown         ValType::V128
183cd982c5aSAndrew Brown     };
184a8ce7f12SAndrew Brown }
185a8ce7f12SAndrew Brown 
186b4c25ef6SAndrew Brown macro_rules! inst {
18772ded108SAlex Crichton     ($inst:ident, $arguments:tt -> $results:tt) => {
18872ded108SAlex Crichton         inst! { $inst, $arguments -> $results, |_| true }
189a8ce7f12SAndrew Brown     };
19072ded108SAlex Crichton     ($inst:ident, $arguments:tt -> $results:tt, $feature:expr) => {
19172ded108SAlex Crichton         inst! { $inst, $arguments -> $results, $feature, None }
192cd982c5aSAndrew Brown     };
19372ded108SAlex Crichton     ($inst:ident, $arguments:tt -> $results:tt, $feature:expr, $nan:expr) => {
194a8ce7f12SAndrew Brown         SingleInstModule {
195a8ce7f12SAndrew Brown             instruction: Instruction::$inst,
19672ded108SAlex Crichton             parameters: valtypes!(@list $arguments),
19772ded108SAlex Crichton             results: valtypes!(@list $results),
1985ec92d59SAndrew Brown             feature: $feature,
199cd982c5aSAndrew Brown             canonicalize_nan: $nan,
200a8ce7f12SAndrew Brown         }
201a8ce7f12SAndrew Brown     };
202a8ce7f12SAndrew Brown }
203a8ce7f12SAndrew Brown 
204cd982c5aSAndrew Brown // INSTRUCTIONS
205cd982c5aSAndrew Brown //
206cd982c5aSAndrew Brown // This list of WebAssembly instructions attempts to roughly follow the
207cd982c5aSAndrew Brown // structure of the W3C specification:
208cd982c5aSAndrew Brown // https://webassembly.github.io/spec/core/appendix/index-instructions.html#index-instr.
209cd982c5aSAndrew Brown // Certain kinds of instructions (e.g., memory access) are skipped for now.
210a8ce7f12SAndrew Brown static INSTRUCTIONS: &[SingleInstModule] = &[
211a8ce7f12SAndrew Brown     // Integer arithmetic.
212a8ce7f12SAndrew Brown     // I32Const
213a8ce7f12SAndrew Brown     // I64Const
214a8ce7f12SAndrew Brown     // F32Const
215a8ce7f12SAndrew Brown     // F64Const
216b4c25ef6SAndrew Brown     inst!(I32Clz, (i32) -> i32),
217b4c25ef6SAndrew Brown     inst!(I64Clz, (i64) -> i64),
218b4c25ef6SAndrew Brown     inst!(I32Ctz, (i32) -> i32),
219b4c25ef6SAndrew Brown     inst!(I64Ctz, (i64) -> i64),
220b4c25ef6SAndrew Brown     inst!(I32Popcnt, (i32) -> i32),
221b4c25ef6SAndrew Brown     inst!(I64Popcnt, (i64) -> i64),
222b4c25ef6SAndrew Brown     inst!(I32Add, (i32, i32) -> i32),
223b4c25ef6SAndrew Brown     inst!(I64Add, (i64, i64) -> i64),
224b4c25ef6SAndrew Brown     inst!(I32Sub, (i32, i32) -> i32),
225b4c25ef6SAndrew Brown     inst!(I64Sub, (i64, i64) -> i64),
226b4c25ef6SAndrew Brown     inst!(I32Mul, (i32, i32) -> i32),
227b4c25ef6SAndrew Brown     inst!(I64Mul, (i64, i64) -> i64),
228b4c25ef6SAndrew Brown     inst!(I32DivS, (i32, i32) -> i32),
229b4c25ef6SAndrew Brown     inst!(I64DivS, (i64, i64) -> i64),
230b4c25ef6SAndrew Brown     inst!(I32DivU, (i32, i32) -> i32),
231b4c25ef6SAndrew Brown     inst!(I64DivU, (i64, i64) -> i64),
232b4c25ef6SAndrew Brown     inst!(I32RemS, (i32, i32) -> i32),
233b4c25ef6SAndrew Brown     inst!(I64RemS, (i64, i64) -> i64),
234b4c25ef6SAndrew Brown     inst!(I32RemU, (i32, i32) -> i32),
235b4c25ef6SAndrew Brown     inst!(I64RemU, (i64, i64) -> i64),
236a8ce7f12SAndrew Brown     // Integer bitwise.
237b4c25ef6SAndrew Brown     inst!(I32And, (i32, i32) -> i32),
238b4c25ef6SAndrew Brown     inst!(I64And, (i64, i64) -> i64),
239b4c25ef6SAndrew Brown     inst!(I32Or, (i32, i32) -> i32),
240b4c25ef6SAndrew Brown     inst!(I64Or, (i64, i64) -> i64),
241b4c25ef6SAndrew Brown     inst!(I32Xor, (i32, i32) -> i32),
242b4c25ef6SAndrew Brown     inst!(I64Xor, (i64, i64) -> i64),
243b4c25ef6SAndrew Brown     inst!(I32Shl, (i32, i32) -> i32),
244b4c25ef6SAndrew Brown     inst!(I64Shl, (i64, i64) -> i64),
245b4c25ef6SAndrew Brown     inst!(I32ShrS, (i32, i32) -> i32),
246b4c25ef6SAndrew Brown     inst!(I64ShrS, (i64, i64) -> i64),
247b4c25ef6SAndrew Brown     inst!(I32ShrU, (i32, i32) -> i32),
248b4c25ef6SAndrew Brown     inst!(I64ShrU, (i64, i64) -> i64),
249b4c25ef6SAndrew Brown     inst!(I32Rotl, (i32, i32) -> i32),
250b4c25ef6SAndrew Brown     inst!(I64Rotl, (i64, i64) -> i64),
251b4c25ef6SAndrew Brown     inst!(I32Rotr, (i32, i32) -> i32),
252b4c25ef6SAndrew Brown     inst!(I64Rotr, (i64, i64) -> i64),
253a8ce7f12SAndrew Brown     // Integer comparison.
254b4c25ef6SAndrew Brown     inst!(I32Eqz, (i32) -> i32),
255b4c25ef6SAndrew Brown     inst!(I64Eqz, (i64) -> i32),
256b4c25ef6SAndrew Brown     inst!(I32Eq, (i32, i32) -> i32),
257b4c25ef6SAndrew Brown     inst!(I64Eq, (i64, i64) -> i32),
258b4c25ef6SAndrew Brown     inst!(I32Ne, (i32, i32) -> i32),
259b4c25ef6SAndrew Brown     inst!(I64Ne, (i64, i64) -> i32),
260b4c25ef6SAndrew Brown     inst!(I32LtS, (i32, i32) -> i32),
261b4c25ef6SAndrew Brown     inst!(I64LtS, (i64, i64) -> i32),
262b4c25ef6SAndrew Brown     inst!(I32LtU, (i32, i32) -> i32),
263b4c25ef6SAndrew Brown     inst!(I64LtU, (i64, i64) -> i32),
264b4c25ef6SAndrew Brown     inst!(I32GtS, (i32, i32) -> i32),
265b4c25ef6SAndrew Brown     inst!(I64GtS, (i64, i64) -> i32),
266b4c25ef6SAndrew Brown     inst!(I32GtU, (i32, i32) -> i32),
267b4c25ef6SAndrew Brown     inst!(I64GtU, (i64, i64) -> i32),
268b4c25ef6SAndrew Brown     inst!(I32LeS, (i32, i32) -> i32),
269b4c25ef6SAndrew Brown     inst!(I64LeS, (i64, i64) -> i32),
270b4c25ef6SAndrew Brown     inst!(I32LeU, (i32, i32) -> i32),
271b4c25ef6SAndrew Brown     inst!(I64LeU, (i64, i64) -> i32),
272b4c25ef6SAndrew Brown     inst!(I32GeS, (i32, i32) -> i32),
273b4c25ef6SAndrew Brown     inst!(I64GeS, (i64, i64) -> i32),
274b4c25ef6SAndrew Brown     inst!(I32GeU, (i32, i32) -> i32),
275b4c25ef6SAndrew Brown     inst!(I64GeU, (i64, i64) -> i32),
276a8ce7f12SAndrew Brown     // Floating-point arithmetic.
277b4c25ef6SAndrew Brown     inst!(F32Abs, (f32) -> f32),
278b4c25ef6SAndrew Brown     inst!(F64Abs, (f64) -> f64),
279b4c25ef6SAndrew Brown     inst!(F32Sqrt, (f32) -> f32),
280b4c25ef6SAndrew Brown     inst!(F64Sqrt, (f64) -> f64),
281b4c25ef6SAndrew Brown     inst!(F32Ceil, (f32) -> f32),
282b4c25ef6SAndrew Brown     inst!(F64Ceil, (f64) -> f64),
283b4c25ef6SAndrew Brown     inst!(F32Floor, (f32) -> f32),
284b4c25ef6SAndrew Brown     inst!(F64Floor, (f64) -> f64),
285b4c25ef6SAndrew Brown     inst!(F32Trunc, (f32) -> f32),
286b4c25ef6SAndrew Brown     inst!(F64Trunc, (f64) -> f64),
287b4c25ef6SAndrew Brown     inst!(F32Nearest, (f32) -> f32),
288b4c25ef6SAndrew Brown     inst!(F64Nearest, (f64) -> f64),
289b4c25ef6SAndrew Brown     inst!(F32Neg, (f32) -> f32),
290b4c25ef6SAndrew Brown     inst!(F64Neg, (f64) -> f64),
291b4c25ef6SAndrew Brown     inst!(F32Add, (f32, f32) -> f32),
292b4c25ef6SAndrew Brown     inst!(F64Add, (f64, f64) -> f64),
293b4c25ef6SAndrew Brown     inst!(F32Sub, (f32, f32) -> f32),
294b4c25ef6SAndrew Brown     inst!(F64Sub, (f64, f64) -> f64),
295b4c25ef6SAndrew Brown     inst!(F32Mul, (f32, f32) -> f32),
296b4c25ef6SAndrew Brown     inst!(F64Mul, (f64, f64) -> f64),
297b4c25ef6SAndrew Brown     inst!(F32Div, (f32, f32) -> f32),
298b4c25ef6SAndrew Brown     inst!(F64Div, (f64, f64) -> f64),
299b4c25ef6SAndrew Brown     inst!(F32Min, (f32, f32) -> f32),
300b4c25ef6SAndrew Brown     inst!(F64Min, (f64, f64) -> f64),
301b4c25ef6SAndrew Brown     inst!(F32Max, (f32, f32) -> f32),
302b4c25ef6SAndrew Brown     inst!(F64Max, (f64, f64) -> f64),
303b4c25ef6SAndrew Brown     inst!(F32Copysign, (f32, f32) -> f32),
304b4c25ef6SAndrew Brown     inst!(F64Copysign, (f64, f64) -> f64),
305a8ce7f12SAndrew Brown     // Floating-point comparison.
306b4c25ef6SAndrew Brown     inst!(F32Eq, (f32, f32) -> i32),
307b4c25ef6SAndrew Brown     inst!(F64Eq, (f64, f64) -> i32),
308b4c25ef6SAndrew Brown     inst!(F32Ne, (f32, f32) -> i32),
309b4c25ef6SAndrew Brown     inst!(F64Ne, (f64, f64) -> i32),
310b4c25ef6SAndrew Brown     inst!(F32Lt, (f32, f32) -> i32),
311b4c25ef6SAndrew Brown     inst!(F64Lt, (f64, f64) -> i32),
312b4c25ef6SAndrew Brown     inst!(F32Gt, (f32, f32) -> i32),
313b4c25ef6SAndrew Brown     inst!(F64Gt, (f64, f64) -> i32),
314b4c25ef6SAndrew Brown     inst!(F32Le, (f32, f32) -> i32),
315b4c25ef6SAndrew Brown     inst!(F64Le, (f64, f64) -> i32),
316b4c25ef6SAndrew Brown     inst!(F32Ge, (f32, f32) -> i32),
317b4c25ef6SAndrew Brown     inst!(F64Ge, (f64, f64) -> i32),
318a8ce7f12SAndrew Brown     // Integer conversions ("to integer").
3195660a88bSAlex Crichton     inst!(I32Extend8S, (i32) -> i32, |c| c.config.sign_extension_ops_enabled),
3205660a88bSAlex Crichton     inst!(I32Extend16S, (i32) -> i32, |c| c.config.sign_extension_ops_enabled),
3215660a88bSAlex Crichton     inst!(I64Extend8S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled),
3225660a88bSAlex Crichton     inst!(I64Extend16S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled),
3235660a88bSAlex Crichton     inst!(I64Extend32S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled),
324b4c25ef6SAndrew Brown     inst!(I32WrapI64, (i64) -> i32),
325b4c25ef6SAndrew Brown     inst!(I64ExtendI32S, (i32) -> i64),
326b4c25ef6SAndrew Brown     inst!(I64ExtendI32U, (i32) -> i64),
327b4c25ef6SAndrew Brown     inst!(I32TruncF32S, (f32) -> i32),
328b4c25ef6SAndrew Brown     inst!(I32TruncF32U, (f32) -> i32),
329b4c25ef6SAndrew Brown     inst!(I32TruncF64S, (f64) -> i32),
330b4c25ef6SAndrew Brown     inst!(I32TruncF64U, (f64) -> i32),
331b4c25ef6SAndrew Brown     inst!(I64TruncF32S, (f32) -> i64),
332b4c25ef6SAndrew Brown     inst!(I64TruncF32U, (f32) -> i64),
333b4c25ef6SAndrew Brown     inst!(I64TruncF64S, (f64) -> i64),
334b4c25ef6SAndrew Brown     inst!(I64TruncF64U, (f64) -> i64),
335b4c25ef6SAndrew Brown     inst!(I32TruncSatF32S, (f32) -> i32, |c| c.config.saturating_float_to_int_enabled),
336b4c25ef6SAndrew Brown     inst!(I32TruncSatF32U, (f32) -> i32, |c| c.config.saturating_float_to_int_enabled),
337b4c25ef6SAndrew Brown     inst!(I32TruncSatF64S, (f64) -> i32, |c| c.config.saturating_float_to_int_enabled),
338b4c25ef6SAndrew Brown     inst!(I32TruncSatF64U, (f64) -> i32, |c| c.config.saturating_float_to_int_enabled),
339b4c25ef6SAndrew Brown     inst!(I64TruncSatF32S, (f32) -> i64, |c| c.config.saturating_float_to_int_enabled),
340b4c25ef6SAndrew Brown     inst!(I64TruncSatF32U, (f32) -> i64, |c| c.config.saturating_float_to_int_enabled),
341b4c25ef6SAndrew Brown     inst!(I64TruncSatF64S, (f64) -> i64, |c| c.config.saturating_float_to_int_enabled),
342b4c25ef6SAndrew Brown     inst!(I64TruncSatF64U, (f64) -> i64, |c| c.config.saturating_float_to_int_enabled),
343b4c25ef6SAndrew Brown     inst!(I32ReinterpretF32, (f32) -> i32),
344b4c25ef6SAndrew Brown     inst!(I64ReinterpretF64, (f64) -> i64),
345a8ce7f12SAndrew Brown     // Floating-point conversions ("to float").
346b4c25ef6SAndrew Brown     inst!(F32DemoteF64, (f64) -> f32),
347b4c25ef6SAndrew Brown     inst!(F64PromoteF32, (f32) -> f64),
348b4c25ef6SAndrew Brown     inst!(F32ConvertI32S, (i32) -> f32),
349b4c25ef6SAndrew Brown     inst!(F32ConvertI32U, (i32) -> f32),
350b4c25ef6SAndrew Brown     inst!(F32ConvertI64S, (i64) -> f32),
351b4c25ef6SAndrew Brown     inst!(F32ConvertI64U, (i64) -> f32),
352b4c25ef6SAndrew Brown     inst!(F64ConvertI32S, (i32) -> f64),
353b4c25ef6SAndrew Brown     inst!(F64ConvertI32U, (i32) -> f64),
354b4c25ef6SAndrew Brown     inst!(F64ConvertI64S, (i64) -> f64),
355b4c25ef6SAndrew Brown     inst!(F64ConvertI64U, (i64) -> f64),
356b4c25ef6SAndrew Brown     inst!(F32ReinterpretI32, (i32) -> f32),
357b4c25ef6SAndrew Brown     inst!(F64ReinterpretI64, (i64) -> f64),
358cd982c5aSAndrew Brown     // SIMD instructions.
359cd982c5aSAndrew Brown     // V128Const
360cd982c5aSAndrew Brown     // I8x16Shuffle
361cd982c5aSAndrew Brown     inst!(I8x16Swizzle, (v128, v128) -> v128, |c| c.config.simd_enabled),
362cd982c5aSAndrew Brown     inst!(I8x16Splat, (i32) -> v128, |c| c.config.simd_enabled),
363cd982c5aSAndrew Brown     inst!(I16x8Splat, (i32) -> v128, |c| c.config.simd_enabled),
364cd982c5aSAndrew Brown     inst!(I32x4Splat, (i32) -> v128, |c| c.config.simd_enabled),
365cd982c5aSAndrew Brown     inst!(I64x2Splat, (i64) -> v128, |c| c.config.simd_enabled),
366cd982c5aSAndrew Brown     inst!(F32x4Splat, (f32) -> v128, |c| c.config.simd_enabled),
367cd982c5aSAndrew Brown     inst!(F64x2Splat, (f64) -> v128, |c| c.config.simd_enabled),
368cd982c5aSAndrew Brown     // I8x16ExtractLaneS
369cd982c5aSAndrew Brown     // I8x16ExtractLaneU
370cd982c5aSAndrew Brown     // I8x16ReplaceLane
371cd982c5aSAndrew Brown     // I16x8ExtractLaneS
372cd982c5aSAndrew Brown     // I16x8ExtractLaneU
373cd982c5aSAndrew Brown     // I16x8ReplaceLane
374cd982c5aSAndrew Brown     // I32x4ExtractLane
375cd982c5aSAndrew Brown     // I32x4ReplaceLane
376cd982c5aSAndrew Brown     // I64x2ExtractLane
377cd982c5aSAndrew Brown     // I64x2ReplaceLane
378cd982c5aSAndrew Brown     // F32x4ExtractLane
379cd982c5aSAndrew Brown     // F32x4ReplaceLane
380cd982c5aSAndrew Brown     // F64x2ExtractLane
381cd982c5aSAndrew Brown     // F64x2ReplaceLane
382cd982c5aSAndrew Brown     inst!(I8x16Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
383cd982c5aSAndrew Brown     inst!(I8x16Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
384cd982c5aSAndrew Brown     inst!(I8x16LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
385cd982c5aSAndrew Brown     inst!(I8x16LtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
386cd982c5aSAndrew Brown     inst!(I8x16GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
387cd982c5aSAndrew Brown     inst!(I8x16GtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
388cd982c5aSAndrew Brown     inst!(I8x16LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
389cd982c5aSAndrew Brown     inst!(I8x16LeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
390cd982c5aSAndrew Brown     inst!(I8x16GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
391cd982c5aSAndrew Brown     inst!(I8x16GeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
392cd982c5aSAndrew Brown     inst!(I16x8Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
393cd982c5aSAndrew Brown     inst!(I16x8Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
394cd982c5aSAndrew Brown     inst!(I16x8LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
395cd982c5aSAndrew Brown     inst!(I16x8LtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
396cd982c5aSAndrew Brown     inst!(I16x8GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
397cd982c5aSAndrew Brown     inst!(I16x8GtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
398cd982c5aSAndrew Brown     inst!(I16x8LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
399cd982c5aSAndrew Brown     inst!(I16x8LeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
400cd982c5aSAndrew Brown     inst!(I16x8GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
401cd982c5aSAndrew Brown     inst!(I16x8GeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
402cd982c5aSAndrew Brown     inst!(I32x4Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
403cd982c5aSAndrew Brown     inst!(I32x4Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
404cd982c5aSAndrew Brown     inst!(I32x4LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
405cd982c5aSAndrew Brown     inst!(I32x4LtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
406cd982c5aSAndrew Brown     inst!(I32x4GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
407cd982c5aSAndrew Brown     inst!(I32x4GtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
408cd982c5aSAndrew Brown     inst!(I32x4LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
409cd982c5aSAndrew Brown     inst!(I32x4LeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
410cd982c5aSAndrew Brown     inst!(I32x4GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
411cd982c5aSAndrew Brown     inst!(I32x4GeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
412cd982c5aSAndrew Brown     inst!(I64x2Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
413cd982c5aSAndrew Brown     inst!(I64x2Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
414cd982c5aSAndrew Brown     inst!(I64x2LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
415cd982c5aSAndrew Brown     inst!(I64x2GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
416cd982c5aSAndrew Brown     inst!(I64x2LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
417cd982c5aSAndrew Brown     inst!(I64x2GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
418cd982c5aSAndrew Brown     inst!(F32x4Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
419cd982c5aSAndrew Brown     inst!(F32x4Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
420cd982c5aSAndrew Brown     inst!(F32x4Lt, (v128, v128) -> v128, |c| c.config.simd_enabled),
421cd982c5aSAndrew Brown     inst!(F32x4Gt, (v128, v128) -> v128, |c| c.config.simd_enabled),
422cd982c5aSAndrew Brown     inst!(F32x4Le, (v128, v128) -> v128, |c| c.config.simd_enabled),
423cd982c5aSAndrew Brown     inst!(F32x4Ge, (v128, v128) -> v128, |c| c.config.simd_enabled),
424cd982c5aSAndrew Brown     inst!(F64x2Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
425cd982c5aSAndrew Brown     inst!(F64x2Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
426cd982c5aSAndrew Brown     inst!(F64x2Lt, (v128, v128) -> v128, |c| c.config.simd_enabled),
427cd982c5aSAndrew Brown     inst!(F64x2Gt, (v128, v128) -> v128, |c| c.config.simd_enabled),
428cd982c5aSAndrew Brown     inst!(F64x2Le, (v128, v128) -> v128, |c| c.config.simd_enabled),
429cd982c5aSAndrew Brown     inst!(F64x2Ge, (v128, v128) -> v128, |c| c.config.simd_enabled),
430cd982c5aSAndrew Brown     inst!(V128Not, (v128) -> v128, |c| c.config.simd_enabled),
431cd982c5aSAndrew Brown     inst!(V128And, (v128, v128) -> v128, |c| c.config.simd_enabled),
432cd982c5aSAndrew Brown     inst!(V128AndNot, (v128, v128) -> v128, |c| c.config.simd_enabled),
433cd982c5aSAndrew Brown     inst!(V128Or, (v128, v128) -> v128, |c| c.config.simd_enabled),
434cd982c5aSAndrew Brown     inst!(V128Xor, (v128, v128) -> v128, |c| c.config.simd_enabled),
435cd982c5aSAndrew Brown     inst!(V128Bitselect, (v128, v128, v128) -> v128, |c| c.config.simd_enabled),
436cd982c5aSAndrew Brown     inst!(V128AnyTrue, (v128) -> i32, |c| c.config.simd_enabled),
437cd982c5aSAndrew Brown     inst!(I8x16Abs, (v128) -> v128, |c| c.config.simd_enabled),
438cd982c5aSAndrew Brown     inst!(I8x16Neg, (v128) -> v128, |c| c.config.simd_enabled),
439cd982c5aSAndrew Brown     inst!(I8x16Popcnt, (v128) -> v128, |c| c.config.simd_enabled),
440cd982c5aSAndrew Brown     inst!(I8x16AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
441cd982c5aSAndrew Brown     inst!(I8x16Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
442cd982c5aSAndrew Brown     inst!(I8x16NarrowI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
443cd982c5aSAndrew Brown     inst!(I8x16NarrowI16x8U, (v128, v128) -> v128, |c| c.config.simd_enabled),
444cd982c5aSAndrew Brown     inst!(I8x16Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
445cd982c5aSAndrew Brown     inst!(I8x16ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
446cd982c5aSAndrew Brown     inst!(I8x16ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
447cd982c5aSAndrew Brown     inst!(I8x16Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
448cd982c5aSAndrew Brown     inst!(I8x16AddSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
449cd982c5aSAndrew Brown     inst!(I8x16AddSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
450cd982c5aSAndrew Brown     inst!(I8x16Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
451cd982c5aSAndrew Brown     inst!(I8x16SubSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
452cd982c5aSAndrew Brown     inst!(I8x16SubSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
453cd982c5aSAndrew Brown     inst!(I8x16MinS, (v128, v128) -> v128, |c| c.config.simd_enabled),
454cd982c5aSAndrew Brown     inst!(I8x16MinU, (v128, v128) -> v128, |c| c.config.simd_enabled),
455cd982c5aSAndrew Brown     inst!(I8x16MaxS, (v128, v128) -> v128, |c| c.config.simd_enabled),
456cd982c5aSAndrew Brown     inst!(I8x16MaxU, (v128, v128) -> v128, |c| c.config.simd_enabled),
457bc3285e8SAlex Crichton     inst!(I8x16AvgrU, (v128, v128) -> v128, |c| c.config.simd_enabled),
458cd982c5aSAndrew Brown     inst!(I16x8ExtAddPairwiseI8x16S, (v128) -> v128, |c| c.config.simd_enabled),
459cd982c5aSAndrew Brown     inst!(I16x8ExtAddPairwiseI8x16U, (v128) -> v128, |c| c.config.simd_enabled),
460cd982c5aSAndrew Brown     inst!(I16x8Abs, (v128) -> v128, |c| c.config.simd_enabled),
461cd982c5aSAndrew Brown     inst!(I16x8Neg, (v128) -> v128, |c| c.config.simd_enabled),
462cd982c5aSAndrew Brown     inst!(I16x8Q15MulrSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
463cd982c5aSAndrew Brown     inst!(I16x8AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
464cd982c5aSAndrew Brown     inst!(I16x8Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
465cd982c5aSAndrew Brown     inst!(I16x8NarrowI32x4S, (v128, v128) -> v128, |c| c.config.simd_enabled),
466cd982c5aSAndrew Brown     inst!(I16x8NarrowI32x4U, (v128, v128) -> v128, |c| c.config.simd_enabled),
467cd982c5aSAndrew Brown     inst!(I16x8ExtendLowI8x16S, (v128) -> v128, |c| c.config.simd_enabled),
468cd982c5aSAndrew Brown     inst!(I16x8ExtendHighI8x16S, (v128) -> v128, |c| c.config.simd_enabled),
469cd982c5aSAndrew Brown     inst!(I16x8ExtendLowI8x16U, (v128) -> v128, |c| c.config.simd_enabled),
470cd982c5aSAndrew Brown     inst!(I16x8ExtendHighI8x16U, (v128) -> v128, |c| c.config.simd_enabled),
471cd982c5aSAndrew Brown     inst!(I16x8Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
472cd982c5aSAndrew Brown     inst!(I16x8ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
473cd982c5aSAndrew Brown     inst!(I16x8ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
474cd982c5aSAndrew Brown     inst!(I16x8Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
475cd982c5aSAndrew Brown     inst!(I16x8AddSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
476cd982c5aSAndrew Brown     inst!(I16x8AddSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
477cd982c5aSAndrew Brown     inst!(I16x8Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
478cd982c5aSAndrew Brown     inst!(I16x8SubSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
479cd982c5aSAndrew Brown     inst!(I16x8SubSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
480cd982c5aSAndrew Brown     inst!(I16x8Mul, (v128, v128) -> v128, |c| c.config.simd_enabled),
481cd982c5aSAndrew Brown     inst!(I16x8MinS, (v128, v128) -> v128, |c| c.config.simd_enabled),
482cd982c5aSAndrew Brown     inst!(I16x8MinU, (v128, v128) -> v128, |c| c.config.simd_enabled),
483cd982c5aSAndrew Brown     inst!(I16x8MaxS, (v128, v128) -> v128, |c| c.config.simd_enabled),
484cd982c5aSAndrew Brown     inst!(I16x8MaxU, (v128, v128) -> v128, |c| c.config.simd_enabled),
485bc3285e8SAlex Crichton     inst!(I16x8AvgrU, (v128, v128) -> v128, |c| c.config.simd_enabled),
486cd982c5aSAndrew Brown     inst!(I16x8ExtMulLowI8x16S, (v128, v128) -> v128, |c| c.config.simd_enabled),
487cd982c5aSAndrew Brown     inst!(I16x8ExtMulHighI8x16S, (v128, v128) -> v128, |c| c.config.simd_enabled),
488cd982c5aSAndrew Brown     inst!(I16x8ExtMulLowI8x16U, (v128, v128) -> v128, |c| c.config.simd_enabled),
489cd982c5aSAndrew Brown     inst!(I16x8ExtMulHighI8x16U, (v128, v128) -> v128, |c| c.config.simd_enabled),
490cd982c5aSAndrew Brown     inst!(I32x4ExtAddPairwiseI16x8S, (v128) -> v128, |c| c.config.simd_enabled),
491cd982c5aSAndrew Brown     inst!(I32x4ExtAddPairwiseI16x8U, (v128) -> v128, |c| c.config.simd_enabled),
492cd982c5aSAndrew Brown     inst!(I32x4Abs, (v128) -> v128, |c| c.config.simd_enabled),
493cd982c5aSAndrew Brown     inst!(I32x4Neg, (v128) -> v128, |c| c.config.simd_enabled),
494cd982c5aSAndrew Brown     inst!(I32x4AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
495cd982c5aSAndrew Brown     inst!(I32x4Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
496cd982c5aSAndrew Brown     inst!(I32x4ExtendLowI16x8S, (v128) -> v128, |c| c.config.simd_enabled),
497cd982c5aSAndrew Brown     inst!(I32x4ExtendHighI16x8S, (v128) -> v128, |c| c.config.simd_enabled),
498cd982c5aSAndrew Brown     inst!(I32x4ExtendLowI16x8U, (v128) -> v128, |c| c.config.simd_enabled),
499cd982c5aSAndrew Brown     inst!(I32x4ExtendHighI16x8U, (v128) -> v128, |c| c.config.simd_enabled),
500cd982c5aSAndrew Brown     inst!(I32x4Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
501cd982c5aSAndrew Brown     inst!(I32x4ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
502cd982c5aSAndrew Brown     inst!(I32x4ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
503cd982c5aSAndrew Brown     inst!(I32x4Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
504cd982c5aSAndrew Brown     inst!(I32x4Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
505cd982c5aSAndrew Brown     inst!(I32x4Mul, (v128, v128) -> v128, |c| c.config.simd_enabled),
506cd982c5aSAndrew Brown     inst!(I32x4MinS, (v128, v128) -> v128, |c| c.config.simd_enabled),
507cd982c5aSAndrew Brown     inst!(I32x4MinU, (v128, v128) -> v128, |c| c.config.simd_enabled),
508cd982c5aSAndrew Brown     inst!(I32x4MaxS, (v128, v128) -> v128, |c| c.config.simd_enabled),
509cd982c5aSAndrew Brown     inst!(I32x4MaxU, (v128, v128) -> v128, |c| c.config.simd_enabled),
510cd982c5aSAndrew Brown     inst!(I32x4DotI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
511cd982c5aSAndrew Brown     inst!(I32x4ExtMulLowI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
512cd982c5aSAndrew Brown     inst!(I32x4ExtMulHighI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
513cd982c5aSAndrew Brown     inst!(I32x4ExtMulLowI16x8U, (v128, v128) -> v128, |c| c.config.simd_enabled),
514cd982c5aSAndrew Brown     inst!(I32x4ExtMulHighI16x8U, (v128, v128) -> v128, |c| c.config.simd_enabled),
515cd982c5aSAndrew Brown     inst!(I64x2Abs, (v128) -> v128, |c| c.config.simd_enabled),
516cd982c5aSAndrew Brown     inst!(I64x2Neg, (v128) -> v128, |c| c.config.simd_enabled),
517cd982c5aSAndrew Brown     inst!(I64x2AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
518cd982c5aSAndrew Brown     inst!(I64x2Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
519cd982c5aSAndrew Brown     inst!(I64x2ExtendLowI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
520cd982c5aSAndrew Brown     inst!(I64x2ExtendHighI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
521cd982c5aSAndrew Brown     inst!(I64x2ExtendLowI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
522cd982c5aSAndrew Brown     inst!(I64x2ExtendHighI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
523cd982c5aSAndrew Brown     inst!(I64x2Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
524cd982c5aSAndrew Brown     inst!(I64x2ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
525cd982c5aSAndrew Brown     inst!(I64x2ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
526cd982c5aSAndrew Brown     inst!(I64x2Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
527cd982c5aSAndrew Brown     inst!(I64x2Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
528cd982c5aSAndrew Brown     inst!(I64x2Mul, (v128, v128) -> v128, |c| c.config.simd_enabled),
529cd982c5aSAndrew Brown     inst!(I64x2ExtMulLowI32x4S, (v128, v128) -> v128, |c| c.config.simd_enabled),
530cd982c5aSAndrew Brown     inst!(I64x2ExtMulHighI32x4S, (v128, v128) -> v128, |c| c.config.simd_enabled),
531cd982c5aSAndrew Brown     inst!(I64x2ExtMulLowI32x4U, (v128, v128) -> v128, |c| c.config.simd_enabled),
532cd982c5aSAndrew Brown     inst!(I64x2ExtMulHighI32x4U, (v128, v128) -> v128, |c| c.config.simd_enabled),
533cd982c5aSAndrew Brown     inst!(F32x4Ceil, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
534cd982c5aSAndrew Brown     inst!(F32x4Floor, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
535cd982c5aSAndrew Brown     inst!(F32x4Trunc, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
536cd982c5aSAndrew Brown     inst!(F32x4Nearest, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
537cd982c5aSAndrew Brown     inst!(F32x4Abs, (v128) -> v128, |c| c.config.simd_enabled),
538cd982c5aSAndrew Brown     inst!(F32x4Neg, (v128) -> v128, |c| c.config.simd_enabled),
539cd982c5aSAndrew Brown     inst!(F32x4Sqrt, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
540cd982c5aSAndrew Brown     inst!(F32x4Add, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
541cd982c5aSAndrew Brown     inst!(F32x4Sub, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
542cd982c5aSAndrew Brown     inst!(F32x4Mul, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
543cd982c5aSAndrew Brown     inst!(F32x4Div, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
544cd982c5aSAndrew Brown     inst!(F32x4Min, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
545cd982c5aSAndrew Brown     inst!(F32x4Max, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
546cd982c5aSAndrew Brown     inst!(F32x4PMin, (v128, v128) -> v128, |c| c.config.simd_enabled),
547cd982c5aSAndrew Brown     inst!(F32x4PMax, (v128, v128) -> v128, |c| c.config.simd_enabled),
548cd982c5aSAndrew Brown     inst!(F64x2Ceil, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
549cd982c5aSAndrew Brown     inst!(F64x2Floor, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
550cd982c5aSAndrew Brown     inst!(F64x2Trunc, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
551cd982c5aSAndrew Brown     inst!(F64x2Nearest, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
552cd982c5aSAndrew Brown     inst!(F64x2Abs, (v128) -> v128, |c| c.config.simd_enabled),
553cd982c5aSAndrew Brown     inst!(F64x2Neg, (v128) -> v128, |c| c.config.simd_enabled),
554cd982c5aSAndrew Brown     inst!(F64x2Sqrt, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
555cd982c5aSAndrew Brown     inst!(F64x2Add, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
556cd982c5aSAndrew Brown     inst!(F64x2Sub, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
557cd982c5aSAndrew Brown     inst!(F64x2Mul, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
558cd982c5aSAndrew Brown     inst!(F64x2Div, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
559cd982c5aSAndrew Brown     inst!(F64x2Min, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
560cd982c5aSAndrew Brown     inst!(F64x2Max, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
561cd982c5aSAndrew Brown     inst!(F64x2PMin, (v128, v128) -> v128, |c| c.config.simd_enabled),
562cd982c5aSAndrew Brown     inst!(F64x2PMax, (v128, v128) -> v128, |c| c.config.simd_enabled),
563cd982c5aSAndrew Brown     inst!(I32x4TruncSatF32x4S, (v128) -> v128, |c| c.config.simd_enabled),
564cd982c5aSAndrew Brown     inst!(I32x4TruncSatF32x4U, (v128) -> v128, |c| c.config.simd_enabled),
565cd982c5aSAndrew Brown     inst!(F32x4ConvertI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
566cd982c5aSAndrew Brown     inst!(F32x4ConvertI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
567cd982c5aSAndrew Brown     inst!(I32x4TruncSatF64x2SZero, (v128) -> v128, |c| c.config.simd_enabled),
568cd982c5aSAndrew Brown     inst!(I32x4TruncSatF64x2UZero, (v128) -> v128, |c| c.config.simd_enabled),
569cd982c5aSAndrew Brown     inst!(F64x2ConvertLowI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
570cd982c5aSAndrew Brown     inst!(F64x2ConvertLowI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
571cd982c5aSAndrew Brown     inst!(F32x4DemoteF64x2Zero, (v128) -> v128, |c| c.config.simd_enabled),
572cd982c5aSAndrew Brown     inst!(F64x2PromoteLowF32x4, (v128) -> v128, |c| c.config.simd_enabled),
57372ded108SAlex Crichton     // wide arithmetic
57472ded108SAlex Crichton     inst!(I64Add128, (i64, i64, i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
57572ded108SAlex Crichton     inst!(I64Sub128, (i64, i64, i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
57672ded108SAlex Crichton     inst!(I64MulWideS, (i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
57772ded108SAlex Crichton     inst!(I64MulWideU, (i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
578a8ce7f12SAndrew Brown ];
579a8ce7f12SAndrew Brown 
580a8ce7f12SAndrew Brown #[cfg(test)]
581a8ce7f12SAndrew Brown mod test {
582a8ce7f12SAndrew Brown     use super::*;
583a8ce7f12SAndrew Brown 
584a8ce7f12SAndrew Brown     #[test]
sanity()585a8ce7f12SAndrew Brown     fn sanity() {
586a8ce7f12SAndrew Brown         let sut = SingleInstModule {
587a8ce7f12SAndrew Brown             instruction: Instruction::I32Add,
588a8ce7f12SAndrew Brown             parameters: &[ValType::I32, ValType::I32],
589a8ce7f12SAndrew Brown             results: &[ValType::I32],
5905ec92d59SAndrew Brown             feature: |_| true,
591cd982c5aSAndrew Brown             canonicalize_nan: None,
592a8ce7f12SAndrew Brown         };
5935ec92d59SAndrew Brown         let wasm = sut.to_bytes();
594a8ce7f12SAndrew Brown         let wat = wasmprinter::print_bytes(wasm).unwrap();
595a8ce7f12SAndrew Brown         assert_eq!(
596a8ce7f12SAndrew Brown             wat,
597a8ce7f12SAndrew Brown             r#"(module
598a8ce7f12SAndrew Brown   (type (;0;) (func (param i32 i32) (result i32)))
5996844ed1aSAlex Crichton   (export "test" (func 0))
600a8ce7f12SAndrew Brown   (func (;0;) (type 0) (param i32 i32) (result i32)
601a8ce7f12SAndrew Brown     local.get 0
602a8ce7f12SAndrew Brown     local.get 1
603a8ce7f12SAndrew Brown     i32.add
604a8ce7f12SAndrew Brown   )
605888bd112SAlex Crichton )
606888bd112SAlex Crichton "#
607a8ce7f12SAndrew Brown         )
608a8ce7f12SAndrew Brown     }
609a8ce7f12SAndrew Brown 
610a8ce7f12SAndrew Brown     #[test]
instructions_encode_to_valid_modules()611a8ce7f12SAndrew Brown     fn instructions_encode_to_valid_modules() {
612a8ce7f12SAndrew Brown         for inst in INSTRUCTIONS {
6135ec92d59SAndrew Brown             assert!(wat::parse_bytes(&inst.to_bytes()).is_ok());
614a8ce7f12SAndrew Brown         }
615a8ce7f12SAndrew Brown     }
616a8ce7f12SAndrew Brown }
617