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