1use super::ModuleConfig;
4use arbitrary::Unstructured;
5use wasm_encoder::{
6 CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction, Module,
7 TypeSection, ValType,
8};
9
10const FUNCTION_NAME: &'static str = "test";
12
13#[derive(Clone)]
18pub struct SingleInstModule<'a> {
19 instruction: Instruction<'a>,
20 parameters: &'a [ValType],
21 results: &'a [ValType],
22 feature: fn(&ModuleConfig) -> bool,
23 canonicalize_nan: Option<NanType>,
24}
25
26#[derive(Clone)]
33enum NanType {
34 #[expect(dead_code, reason = "expected to be used in the future")]
35 F32,
36 #[expect(dead_code, reason = "expected to be used in the future")]
37 F64,
38 F32x4,
39 F64x2,
40}
41
42impl<'a> SingleInstModule<'a> {
43 pub fn new(u: &mut Unstructured<'a>, config: &ModuleConfig) -> arbitrary::Result<&'a Self> {
45 let instructions = &INSTRUCTIONS
47 .iter()
48 .filter(|i| (i.feature)(config))
49 .collect::<Vec<_>>();
50 u.choose(&instructions[..]).copied()
51 }
52
53 pub fn to_bytes(&self) -> Vec<u8> {
56 let mut module = Module::new();
57
58 let mut types = TypeSection::new();
60 types.ty().function(
61 self.parameters.iter().cloned(),
62 self.results.iter().cloned(),
63 );
64 module.section(&types);
65
66 let mut functions = FunctionSection::new();
68 let type_index = 0;
69 functions.function(type_index);
70 module.section(&functions);
71
72 let mut exports = ExportSection::new();
74 exports.export(FUNCTION_NAME, ExportKind::Func, 0);
75 module.section(&exports);
76
77 let mut codes = CodeSection::new();
79
80 let mut f = if let Some(ty) = &self.canonicalize_nan {
84 Function::new(match ty {
85 NanType::F32 => vec![(1, ValType::F32)],
86 NanType::F64 => vec![(1, ValType::F64)],
87 NanType::F32x4 | NanType::F64x2 => vec![(1, ValType::V128)],
88 })
89 } else {
90 Function::new([])
91 };
92
93 for (index, _) in self.parameters.iter().enumerate() {
95 f.instruction(&Instruction::LocalGet(index as u32));
96 }
97 f.instruction(&self.instruction);
98
99 if let Some(ty) = &self.canonicalize_nan {
104 let local = self.parameters.len() as u32;
108 f.instruction(&Instruction::LocalTee(local));
109
110 const CANON_32BIT_NAN: u32 = 0b01111111110000000000000000000000;
113 const CANON_64BIT_NAN: u64 =
114 0b0111111111111000000000000000000000000000000000000000000000000000;
115 let mask = match ty {
116 NanType::F32 => Instruction::F32Const(f32::from_bits(CANON_32BIT_NAN)),
117 NanType::F64 => Instruction::F64Const(f64::from_bits(CANON_64BIT_NAN)),
118 NanType::F32x4 => {
119 let nan = CANON_32BIT_NAN as i128;
120 Instruction::V128Const(nan | (nan << 32) | (nan << 64) | (nan << 96))
121 }
122 NanType::F64x2 => {
123 let nan = CANON_64BIT_NAN as i128;
124 Instruction::V128Const(nan | (nan << 64))
125 }
126 };
127 f.instruction(&mask);
128
129 f.instruction(&Instruction::LocalGet(local));
132 f.instruction(&Instruction::LocalGet(local));
133 f.instruction(match ty {
134 NanType::F32 => &Instruction::F32Eq,
135 NanType::F64 => &Instruction::F64Eq,
136 NanType::F32x4 => &Instruction::F32x4Eq,
137 NanType::F64x2 => &Instruction::F64x2Eq,
138 });
139
140 f.instruction(match ty {
144 NanType::F32 | NanType::F64 => &Instruction::Select,
145 NanType::F32x4 | NanType::F64x2 => &Instruction::V128Bitselect,
146 });
147 }
148
149 f.instruction(&Instruction::End);
151 codes.function(&f);
152 module.section(&codes);
153
154 module.finish()
156 }
157}
158
159macro_rules! valtypes {
167 (@list ($($ty:tt),*)) => {&[$(valtypes!(@one $ty)),*]};
168 (@list $ty:tt) => {&[valtypes!(@one $ty)]};
169 (@one i32) => {
170 ValType::I32
171 };
172 (@one i64) => {
173 ValType::I64
174 };
175 (@one f32) => {
176 ValType::F32
177 };
178 (@one f64) => {
179 ValType::F64
180 };
181 (@one v128) => {
182 ValType::V128
183 };
184}
185
186macro_rules! inst {
187 ($inst:ident, $arguments:tt -> $results:tt) => {
188 inst! { $inst, $arguments -> $results, |_| true }
189 };
190 ($inst:ident, $arguments:tt -> $results:tt, $feature:expr) => {
191 inst! { $inst, $arguments -> $results, $feature, None }
192 };
193 ($inst:ident, $arguments:tt -> $results:tt, $feature:expr, $nan:expr) => {
194 SingleInstModule {
195 instruction: Instruction::$inst,
196 parameters: valtypes!(@list $arguments),
197 results: valtypes!(@list $results),
198 feature: $feature,
199 canonicalize_nan: $nan,
200 }
201 };
202}
203
204static INSTRUCTIONS: &[SingleInstModule] = &[
211 inst!(I32Clz, (i32) -> i32),
217 inst!(I64Clz, (i64) -> i64),
218 inst!(I32Ctz, (i32) -> i32),
219 inst!(I64Ctz, (i64) -> i64),
220 inst!(I32Popcnt, (i32) -> i32),
221 inst!(I64Popcnt, (i64) -> i64),
222 inst!(I32Add, (i32, i32) -> i32),
223 inst!(I64Add, (i64, i64) -> i64),
224 inst!(I32Sub, (i32, i32) -> i32),
225 inst!(I64Sub, (i64, i64) -> i64),
226 inst!(I32Mul, (i32, i32) -> i32),
227 inst!(I64Mul, (i64, i64) -> i64),
228 inst!(I32DivS, (i32, i32) -> i32),
229 inst!(I64DivS, (i64, i64) -> i64),
230 inst!(I32DivU, (i32, i32) -> i32),
231 inst!(I64DivU, (i64, i64) -> i64),
232 inst!(I32RemS, (i32, i32) -> i32),
233 inst!(I64RemS, (i64, i64) -> i64),
234 inst!(I32RemU, (i32, i32) -> i32),
235 inst!(I64RemU, (i64, i64) -> i64),
236 inst!(I32And, (i32, i32) -> i32),
238 inst!(I64And, (i64, i64) -> i64),
239 inst!(I32Or, (i32, i32) -> i32),
240 inst!(I64Or, (i64, i64) -> i64),
241 inst!(I32Xor, (i32, i32) -> i32),
242 inst!(I64Xor, (i64, i64) -> i64),
243 inst!(I32Shl, (i32, i32) -> i32),
244 inst!(I64Shl, (i64, i64) -> i64),
245 inst!(I32ShrS, (i32, i32) -> i32),
246 inst!(I64ShrS, (i64, i64) -> i64),
247 inst!(I32ShrU, (i32, i32) -> i32),
248 inst!(I64ShrU, (i64, i64) -> i64),
249 inst!(I32Rotl, (i32, i32) -> i32),
250 inst!(I64Rotl, (i64, i64) -> i64),
251 inst!(I32Rotr, (i32, i32) -> i32),
252 inst!(I64Rotr, (i64, i64) -> i64),
253 inst!(I32Eqz, (i32) -> i32),
255 inst!(I64Eqz, (i64) -> i32),
256 inst!(I32Eq, (i32, i32) -> i32),
257 inst!(I64Eq, (i64, i64) -> i32),
258 inst!(I32Ne, (i32, i32) -> i32),
259 inst!(I64Ne, (i64, i64) -> i32),
260 inst!(I32LtS, (i32, i32) -> i32),
261 inst!(I64LtS, (i64, i64) -> i32),
262 inst!(I32LtU, (i32, i32) -> i32),
263 inst!(I64LtU, (i64, i64) -> i32),
264 inst!(I32GtS, (i32, i32) -> i32),
265 inst!(I64GtS, (i64, i64) -> i32),
266 inst!(I32GtU, (i32, i32) -> i32),
267 inst!(I64GtU, (i64, i64) -> i32),
268 inst!(I32LeS, (i32, i32) -> i32),
269 inst!(I64LeS, (i64, i64) -> i32),
270 inst!(I32LeU, (i32, i32) -> i32),
271 inst!(I64LeU, (i64, i64) -> i32),
272 inst!(I32GeS, (i32, i32) -> i32),
273 inst!(I64GeS, (i64, i64) -> i32),
274 inst!(I32GeU, (i32, i32) -> i32),
275 inst!(I64GeU, (i64, i64) -> i32),
276 inst!(F32Abs, (f32) -> f32),
278 inst!(F64Abs, (f64) -> f64),
279 inst!(F32Sqrt, (f32) -> f32),
280 inst!(F64Sqrt, (f64) -> f64),
281 inst!(F32Ceil, (f32) -> f32),
282 inst!(F64Ceil, (f64) -> f64),
283 inst!(F32Floor, (f32) -> f32),
284 inst!(F64Floor, (f64) -> f64),
285 inst!(F32Trunc, (f32) -> f32),
286 inst!(F64Trunc, (f64) -> f64),
287 inst!(F32Nearest, (f32) -> f32),
288 inst!(F64Nearest, (f64) -> f64),
289 inst!(F32Neg, (f32) -> f32),
290 inst!(F64Neg, (f64) -> f64),
291 inst!(F32Add, (f32, f32) -> f32),
292 inst!(F64Add, (f64, f64) -> f64),
293 inst!(F32Sub, (f32, f32) -> f32),
294 inst!(F64Sub, (f64, f64) -> f64),
295 inst!(F32Mul, (f32, f32) -> f32),
296 inst!(F64Mul, (f64, f64) -> f64),
297 inst!(F32Div, (f32, f32) -> f32),
298 inst!(F64Div, (f64, f64) -> f64),
299 inst!(F32Min, (f32, f32) -> f32),
300 inst!(F64Min, (f64, f64) -> f64),
301 inst!(F32Max, (f32, f32) -> f32),
302 inst!(F64Max, (f64, f64) -> f64),
303 inst!(F32Copysign, (f32, f32) -> f32),
304 inst!(F64Copysign, (f64, f64) -> f64),
305 inst!(F32Eq, (f32, f32) -> i32),
307 inst!(F64Eq, (f64, f64) -> i32),
308 inst!(F32Ne, (f32, f32) -> i32),
309 inst!(F64Ne, (f64, f64) -> i32),
310 inst!(F32Lt, (f32, f32) -> i32),
311 inst!(F64Lt, (f64, f64) -> i32),
312 inst!(F32Gt, (f32, f32) -> i32),
313 inst!(F64Gt, (f64, f64) -> i32),
314 inst!(F32Le, (f32, f32) -> i32),
315 inst!(F64Le, (f64, f64) -> i32),
316 inst!(F32Ge, (f32, f32) -> i32),
317 inst!(F64Ge, (f64, f64) -> i32),
318 inst!(I32Extend8S, (i32) -> i32, |c| c.config.sign_extension_ops_enabled),
320 inst!(I32Extend16S, (i32) -> i32, |c| c.config.sign_extension_ops_enabled),
321 inst!(I64Extend8S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled),
322 inst!(I64Extend16S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled),
323 inst!(I64Extend32S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled),
324 inst!(I32WrapI64, (i64) -> i32),
325 inst!(I64ExtendI32S, (i32) -> i64),
326 inst!(I64ExtendI32U, (i32) -> i64),
327 inst!(I32TruncF32S, (f32) -> i32),
328 inst!(I32TruncF32U, (f32) -> i32),
329 inst!(I32TruncF64S, (f64) -> i32),
330 inst!(I32TruncF64U, (f64) -> i32),
331 inst!(I64TruncF32S, (f32) -> i64),
332 inst!(I64TruncF32U, (f32) -> i64),
333 inst!(I64TruncF64S, (f64) -> i64),
334 inst!(I64TruncF64U, (f64) -> i64),
335 inst!(I32TruncSatF32S, (f32) -> i32, |c| c.config.saturating_float_to_int_enabled),
336 inst!(I32TruncSatF32U, (f32) -> i32, |c| c.config.saturating_float_to_int_enabled),
337 inst!(I32TruncSatF64S, (f64) -> i32, |c| c.config.saturating_float_to_int_enabled),
338 inst!(I32TruncSatF64U, (f64) -> i32, |c| c.config.saturating_float_to_int_enabled),
339 inst!(I64TruncSatF32S, (f32) -> i64, |c| c.config.saturating_float_to_int_enabled),
340 inst!(I64TruncSatF32U, (f32) -> i64, |c| c.config.saturating_float_to_int_enabled),
341 inst!(I64TruncSatF64S, (f64) -> i64, |c| c.config.saturating_float_to_int_enabled),
342 inst!(I64TruncSatF64U, (f64) -> i64, |c| c.config.saturating_float_to_int_enabled),
343 inst!(I32ReinterpretF32, (f32) -> i32),
344 inst!(I64ReinterpretF64, (f64) -> i64),
345 inst!(F32DemoteF64, (f64) -> f32),
347 inst!(F64PromoteF32, (f32) -> f64),
348 inst!(F32ConvertI32S, (i32) -> f32),
349 inst!(F32ConvertI32U, (i32) -> f32),
350 inst!(F32ConvertI64S, (i64) -> f32),
351 inst!(F32ConvertI64U, (i64) -> f32),
352 inst!(F64ConvertI32S, (i32) -> f64),
353 inst!(F64ConvertI32U, (i32) -> f64),
354 inst!(F64ConvertI64S, (i64) -> f64),
355 inst!(F64ConvertI64U, (i64) -> f64),
356 inst!(F32ReinterpretI32, (i32) -> f32),
357 inst!(F64ReinterpretI64, (i64) -> f64),
358 inst!(I8x16Swizzle, (v128, v128) -> v128, |c| c.config.simd_enabled),
362 inst!(I8x16Splat, (i32) -> v128, |c| c.config.simd_enabled),
363 inst!(I16x8Splat, (i32) -> v128, |c| c.config.simd_enabled),
364 inst!(I32x4Splat, (i32) -> v128, |c| c.config.simd_enabled),
365 inst!(I64x2Splat, (i64) -> v128, |c| c.config.simd_enabled),
366 inst!(F32x4Splat, (f32) -> v128, |c| c.config.simd_enabled),
367 inst!(F64x2Splat, (f64) -> v128, |c| c.config.simd_enabled),
368 inst!(I8x16Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
383 inst!(I8x16Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
384 inst!(I8x16LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
385 inst!(I8x16LtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
386 inst!(I8x16GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
387 inst!(I8x16GtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
388 inst!(I8x16LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
389 inst!(I8x16LeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
390 inst!(I8x16GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
391 inst!(I8x16GeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
392 inst!(I16x8Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
393 inst!(I16x8Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
394 inst!(I16x8LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
395 inst!(I16x8LtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
396 inst!(I16x8GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
397 inst!(I16x8GtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
398 inst!(I16x8LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
399 inst!(I16x8LeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
400 inst!(I16x8GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
401 inst!(I16x8GeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
402 inst!(I32x4Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
403 inst!(I32x4Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
404 inst!(I32x4LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
405 inst!(I32x4LtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
406 inst!(I32x4GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
407 inst!(I32x4GtU, (v128, v128) -> v128, |c| c.config.simd_enabled),
408 inst!(I32x4LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
409 inst!(I32x4LeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
410 inst!(I32x4GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
411 inst!(I32x4GeU, (v128, v128) -> v128, |c| c.config.simd_enabled),
412 inst!(I64x2Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
413 inst!(I64x2Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
414 inst!(I64x2LtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
415 inst!(I64x2GtS, (v128, v128) -> v128, |c| c.config.simd_enabled),
416 inst!(I64x2LeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
417 inst!(I64x2GeS, (v128, v128) -> v128, |c| c.config.simd_enabled),
418 inst!(F32x4Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
419 inst!(F32x4Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
420 inst!(F32x4Lt, (v128, v128) -> v128, |c| c.config.simd_enabled),
421 inst!(F32x4Gt, (v128, v128) -> v128, |c| c.config.simd_enabled),
422 inst!(F32x4Le, (v128, v128) -> v128, |c| c.config.simd_enabled),
423 inst!(F32x4Ge, (v128, v128) -> v128, |c| c.config.simd_enabled),
424 inst!(F64x2Eq, (v128, v128) -> v128, |c| c.config.simd_enabled),
425 inst!(F64x2Ne, (v128, v128) -> v128, |c| c.config.simd_enabled),
426 inst!(F64x2Lt, (v128, v128) -> v128, |c| c.config.simd_enabled),
427 inst!(F64x2Gt, (v128, v128) -> v128, |c| c.config.simd_enabled),
428 inst!(F64x2Le, (v128, v128) -> v128, |c| c.config.simd_enabled),
429 inst!(F64x2Ge, (v128, v128) -> v128, |c| c.config.simd_enabled),
430 inst!(V128Not, (v128) -> v128, |c| c.config.simd_enabled),
431 inst!(V128And, (v128, v128) -> v128, |c| c.config.simd_enabled),
432 inst!(V128AndNot, (v128, v128) -> v128, |c| c.config.simd_enabled),
433 inst!(V128Or, (v128, v128) -> v128, |c| c.config.simd_enabled),
434 inst!(V128Xor, (v128, v128) -> v128, |c| c.config.simd_enabled),
435 inst!(V128Bitselect, (v128, v128, v128) -> v128, |c| c.config.simd_enabled),
436 inst!(V128AnyTrue, (v128) -> i32, |c| c.config.simd_enabled),
437 inst!(I8x16Abs, (v128) -> v128, |c| c.config.simd_enabled),
438 inst!(I8x16Neg, (v128) -> v128, |c| c.config.simd_enabled),
439 inst!(I8x16Popcnt, (v128) -> v128, |c| c.config.simd_enabled),
440 inst!(I8x16AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
441 inst!(I8x16Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
442 inst!(I8x16NarrowI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
443 inst!(I8x16NarrowI16x8U, (v128, v128) -> v128, |c| c.config.simd_enabled),
444 inst!(I8x16Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
445 inst!(I8x16ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
446 inst!(I8x16ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
447 inst!(I8x16Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
448 inst!(I8x16AddSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
449 inst!(I8x16AddSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
450 inst!(I8x16Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
451 inst!(I8x16SubSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
452 inst!(I8x16SubSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
453 inst!(I8x16MinS, (v128, v128) -> v128, |c| c.config.simd_enabled),
454 inst!(I8x16MinU, (v128, v128) -> v128, |c| c.config.simd_enabled),
455 inst!(I8x16MaxS, (v128, v128) -> v128, |c| c.config.simd_enabled),
456 inst!(I8x16MaxU, (v128, v128) -> v128, |c| c.config.simd_enabled),
457 inst!(I8x16AvgrU, (v128, v128) -> v128, |c| c.config.simd_enabled),
458 inst!(I16x8ExtAddPairwiseI8x16S, (v128) -> v128, |c| c.config.simd_enabled),
459 inst!(I16x8ExtAddPairwiseI8x16U, (v128) -> v128, |c| c.config.simd_enabled),
460 inst!(I16x8Abs, (v128) -> v128, |c| c.config.simd_enabled),
461 inst!(I16x8Neg, (v128) -> v128, |c| c.config.simd_enabled),
462 inst!(I16x8Q15MulrSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
463 inst!(I16x8AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
464 inst!(I16x8Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
465 inst!(I16x8NarrowI32x4S, (v128, v128) -> v128, |c| c.config.simd_enabled),
466 inst!(I16x8NarrowI32x4U, (v128, v128) -> v128, |c| c.config.simd_enabled),
467 inst!(I16x8ExtendLowI8x16S, (v128) -> v128, |c| c.config.simd_enabled),
468 inst!(I16x8ExtendHighI8x16S, (v128) -> v128, |c| c.config.simd_enabled),
469 inst!(I16x8ExtendLowI8x16U, (v128) -> v128, |c| c.config.simd_enabled),
470 inst!(I16x8ExtendHighI8x16U, (v128) -> v128, |c| c.config.simd_enabled),
471 inst!(I16x8Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
472 inst!(I16x8ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
473 inst!(I16x8ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
474 inst!(I16x8Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
475 inst!(I16x8AddSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
476 inst!(I16x8AddSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
477 inst!(I16x8Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
478 inst!(I16x8SubSatS, (v128, v128) -> v128, |c| c.config.simd_enabled),
479 inst!(I16x8SubSatU, (v128, v128) -> v128, |c| c.config.simd_enabled),
480 inst!(I16x8Mul, (v128, v128) -> v128, |c| c.config.simd_enabled),
481 inst!(I16x8MinS, (v128, v128) -> v128, |c| c.config.simd_enabled),
482 inst!(I16x8MinU, (v128, v128) -> v128, |c| c.config.simd_enabled),
483 inst!(I16x8MaxS, (v128, v128) -> v128, |c| c.config.simd_enabled),
484 inst!(I16x8MaxU, (v128, v128) -> v128, |c| c.config.simd_enabled),
485 inst!(I16x8AvgrU, (v128, v128) -> v128, |c| c.config.simd_enabled),
486 inst!(I16x8ExtMulLowI8x16S, (v128, v128) -> v128, |c| c.config.simd_enabled),
487 inst!(I16x8ExtMulHighI8x16S, (v128, v128) -> v128, |c| c.config.simd_enabled),
488 inst!(I16x8ExtMulLowI8x16U, (v128, v128) -> v128, |c| c.config.simd_enabled),
489 inst!(I16x8ExtMulHighI8x16U, (v128, v128) -> v128, |c| c.config.simd_enabled),
490 inst!(I32x4ExtAddPairwiseI16x8S, (v128) -> v128, |c| c.config.simd_enabled),
491 inst!(I32x4ExtAddPairwiseI16x8U, (v128) -> v128, |c| c.config.simd_enabled),
492 inst!(I32x4Abs, (v128) -> v128, |c| c.config.simd_enabled),
493 inst!(I32x4Neg, (v128) -> v128, |c| c.config.simd_enabled),
494 inst!(I32x4AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
495 inst!(I32x4Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
496 inst!(I32x4ExtendLowI16x8S, (v128) -> v128, |c| c.config.simd_enabled),
497 inst!(I32x4ExtendHighI16x8S, (v128) -> v128, |c| c.config.simd_enabled),
498 inst!(I32x4ExtendLowI16x8U, (v128) -> v128, |c| c.config.simd_enabled),
499 inst!(I32x4ExtendHighI16x8U, (v128) -> v128, |c| c.config.simd_enabled),
500 inst!(I32x4Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
501 inst!(I32x4ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
502 inst!(I32x4ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
503 inst!(I32x4Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
504 inst!(I32x4Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
505 inst!(I32x4Mul, (v128, v128) -> v128, |c| c.config.simd_enabled),
506 inst!(I32x4MinS, (v128, v128) -> v128, |c| c.config.simd_enabled),
507 inst!(I32x4MinU, (v128, v128) -> v128, |c| c.config.simd_enabled),
508 inst!(I32x4MaxS, (v128, v128) -> v128, |c| c.config.simd_enabled),
509 inst!(I32x4MaxU, (v128, v128) -> v128, |c| c.config.simd_enabled),
510 inst!(I32x4DotI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
511 inst!(I32x4ExtMulLowI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
512 inst!(I32x4ExtMulHighI16x8S, (v128, v128) -> v128, |c| c.config.simd_enabled),
513 inst!(I32x4ExtMulLowI16x8U, (v128, v128) -> v128, |c| c.config.simd_enabled),
514 inst!(I32x4ExtMulHighI16x8U, (v128, v128) -> v128, |c| c.config.simd_enabled),
515 inst!(I64x2Abs, (v128) -> v128, |c| c.config.simd_enabled),
516 inst!(I64x2Neg, (v128) -> v128, |c| c.config.simd_enabled),
517 inst!(I64x2AllTrue, (v128) -> i32, |c| c.config.simd_enabled),
518 inst!(I64x2Bitmask, (v128) -> i32, |c| c.config.simd_enabled),
519 inst!(I64x2ExtendLowI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
520 inst!(I64x2ExtendHighI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
521 inst!(I64x2ExtendLowI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
522 inst!(I64x2ExtendHighI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
523 inst!(I64x2Shl, (v128, i32) -> v128, |c| c.config.simd_enabled),
524 inst!(I64x2ShrS, (v128, i32) -> v128, |c| c.config.simd_enabled),
525 inst!(I64x2ShrU, (v128, i32) -> v128, |c| c.config.simd_enabled),
526 inst!(I64x2Add, (v128, v128) -> v128, |c| c.config.simd_enabled),
527 inst!(I64x2Sub, (v128, v128) -> v128, |c| c.config.simd_enabled),
528 inst!(I64x2Mul, (v128, v128) -> v128, |c| c.config.simd_enabled),
529 inst!(I64x2ExtMulLowI32x4S, (v128, v128) -> v128, |c| c.config.simd_enabled),
530 inst!(I64x2ExtMulHighI32x4S, (v128, v128) -> v128, |c| c.config.simd_enabled),
531 inst!(I64x2ExtMulLowI32x4U, (v128, v128) -> v128, |c| c.config.simd_enabled),
532 inst!(I64x2ExtMulHighI32x4U, (v128, v128) -> v128, |c| c.config.simd_enabled),
533 inst!(F32x4Ceil, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
534 inst!(F32x4Floor, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
535 inst!(F32x4Trunc, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
536 inst!(F32x4Nearest, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
537 inst!(F32x4Abs, (v128) -> v128, |c| c.config.simd_enabled),
538 inst!(F32x4Neg, (v128) -> v128, |c| c.config.simd_enabled),
539 inst!(F32x4Sqrt, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
540 inst!(F32x4Add, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
541 inst!(F32x4Sub, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
542 inst!(F32x4Mul, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
543 inst!(F32x4Div, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
544 inst!(F32x4Min, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
545 inst!(F32x4Max, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F32x4)),
546 inst!(F32x4PMin, (v128, v128) -> v128, |c| c.config.simd_enabled),
547 inst!(F32x4PMax, (v128, v128) -> v128, |c| c.config.simd_enabled),
548 inst!(F64x2Ceil, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
549 inst!(F64x2Floor, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
550 inst!(F64x2Trunc, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
551 inst!(F64x2Nearest, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
552 inst!(F64x2Abs, (v128) -> v128, |c| c.config.simd_enabled),
553 inst!(F64x2Neg, (v128) -> v128, |c| c.config.simd_enabled),
554 inst!(F64x2Sqrt, (v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
555 inst!(F64x2Add, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
556 inst!(F64x2Sub, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
557 inst!(F64x2Mul, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
558 inst!(F64x2Div, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
559 inst!(F64x2Min, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
560 inst!(F64x2Max, (v128, v128) -> v128, |c| c.config.simd_enabled, Some(NanType::F64x2)),
561 inst!(F64x2PMin, (v128, v128) -> v128, |c| c.config.simd_enabled),
562 inst!(F64x2PMax, (v128, v128) -> v128, |c| c.config.simd_enabled),
563 inst!(I32x4TruncSatF32x4S, (v128) -> v128, |c| c.config.simd_enabled),
564 inst!(I32x4TruncSatF32x4U, (v128) -> v128, |c| c.config.simd_enabled),
565 inst!(F32x4ConvertI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
566 inst!(F32x4ConvertI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
567 inst!(I32x4TruncSatF64x2SZero, (v128) -> v128, |c| c.config.simd_enabled),
568 inst!(I32x4TruncSatF64x2UZero, (v128) -> v128, |c| c.config.simd_enabled),
569 inst!(F64x2ConvertLowI32x4S, (v128) -> v128, |c| c.config.simd_enabled),
570 inst!(F64x2ConvertLowI32x4U, (v128) -> v128, |c| c.config.simd_enabled),
571 inst!(F32x4DemoteF64x2Zero, (v128) -> v128, |c| c.config.simd_enabled),
572 inst!(F64x2PromoteLowF32x4, (v128) -> v128, |c| c.config.simd_enabled),
573 inst!(I64Add128, (i64, i64, i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
575 inst!(I64Sub128, (i64, i64, i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
576 inst!(I64MulWideS, (i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
577 inst!(I64MulWideU, (i64, i64) -> (i64, i64), |c| c.config.wide_arithmetic_enabled && c.config.multi_value_enabled),
578];
579
580#[cfg(test)]
581mod test {
582 use super::*;
583
584 #[test]
585 fn sanity() {
586 let sut = SingleInstModule {
587 instruction: Instruction::I32Add,
588 parameters: &[ValType::I32, ValType::I32],
589 results: &[ValType::I32],
590 feature: |_| true,
591 canonicalize_nan: None,
592 };
593 let wasm = sut.to_bytes();
594 let wat = wasmprinter::print_bytes(wasm).unwrap();
595 assert_eq!(
596 wat,
597 r#"(module
598 (type (;0;) (func (param i32 i32) (result i32)))
599 (export "test" (func 0))
600 (func (;0;) (type 0) (param i32 i32) (result i32)
601 local.get 0
602 local.get 1
603 i32.add
604 )
605)
606"#
607 )
608 }
609
610 #[test]
611 fn instructions_encode_to_valid_modules() {
612 for inst in INSTRUCTIONS {
613 assert!(wat::parse_bytes(&inst.to_bytes()).is_ok());
614 }
615 }
616}