Encode a binary Wasm module with a single exported function, `test`, that executes the single instruction.
(&self)
| 53 | /// Encode a binary Wasm module with a single exported function, `test`, |
| 54 | /// that executes the single instruction. |
| 55 | pub fn to_bytes(&self) -> Vec<u8> { |
| 56 | let mut module = Module::new(); |
| 57 | |
| 58 | // Encode the type section. |
| 59 | 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 | // Encode the function section. |
| 67 | let mut functions = FunctionSection::new(); |
| 68 | let type_index = 0; |
| 69 | functions.function(type_index); |
| 70 | module.section(&functions); |
| 71 | |
| 72 | // Encode the export section. |
| 73 | let mut exports = ExportSection::new(); |
| 74 | exports.export(FUNCTION_NAME, ExportKind::Func, 0); |
| 75 | module.section(&exports); |
| 76 | |
| 77 | // Encode the code section. |
| 78 | let mut codes = CodeSection::new(); |
| 79 | |
| 80 | // Set up the single-instruction function. Note that if we have chosen |
| 81 | // to canonicalize NaNs, this function will contain more than one |
| 82 | // instruction and the function will need a scratch local. |
| 83 | 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 | // Retrieve the input values and execute the chosen instruction. |
| 94 | for (index, _) in self.parameters.iter().enumerate() { |
| 95 | f.instruction(&Instruction::LocalGet(index as u32)); |
| 96 | } |
| 97 | f.instruction(&self.instruction); |
| 98 | |
| 99 | // If we have configured to canonicalize NaNs, we add a sequence that |
| 100 | // masks off the NaN payload bits to make them 0s (i.e., a canonical |
| 101 | // NaN). This sequence is adapted from wasm-smiths version; see |
| 102 | // https://github.com/bytecodealliance/wasm-tools/blob/6c127a6/crates/wasm-smith/src/core/code_builder.rs#L927. |
| 103 | if let Some(ty) = &self.canonicalize_nan { |
| 104 | // Save the previous instruction's result into the scratch local. |
| 105 | // This also leaves a value on the stack as for the `select` |
| 106 | // instruction. |
| 107 | let local = self.parameters.len() as u32; |
| 108 | f.instruction(&Instruction::LocalTee(local)); |
| 109 | |
| 110 | // The other input to the `select` below--a canonical NaN. Note how |
| 111 | // the payload bits of the NaN are cleared. |
| 112 | const CANON_32BIT_NAN: u32 = 0b01111111110000000000000000000000; |