Converts an input binary-encoded WebAssembly module to compilation artifacts and type information. This is where compilation actually happens of WebAssembly modules and translation/parsing/validation of the binary input occurs. The binary artifact represented in the `MmapVec` returned here is an in-memory ELF file in an owned area of virtual linear memory where permissions (such as the executable
(
engine: &Engine,
wasm: &[u8],
dwarf_package: Option<&[u8]>,
obj_state: &T::State,
)
| 58 | /// `Some`, notably compiled metadata about the module in addition to the |
| 59 | /// type information found within. |
| 60 | pub(crate) fn build_module_artifacts<T: FinishedObject>( |
| 61 | engine: &Engine, |
| 62 | wasm: &[u8], |
| 63 | dwarf_package: Option<&[u8]>, |
| 64 | obj_state: &T::State, |
| 65 | ) -> Result<( |
| 66 | T, |
| 67 | Option<(CompiledModuleInfo, CompiledFunctionsTable, ModuleTypes)>, |
| 68 | )> { |
| 69 | let compiler = engine.try_compiler()?; |
| 70 | let tunables = engine.tunables(); |
| 71 | |
| 72 | // First a `ModuleEnvironment` is created which records type information |
| 73 | // about the wasm module. This is where the WebAssembly is parsed and |
| 74 | // validated. Afterwards `types` will have all the type information for |
| 75 | // this module. |
| 76 | let mut parser = wasmparser::Parser::new(0); |
| 77 | let mut validator = wasmparser::Validator::new_with_features(engine.features()); |
| 78 | parser.set_features(*validator.features()); |
| 79 | let mut types = ModuleTypesBuilder::new(&validator); |
| 80 | let mut translation = ModuleEnvironment::new( |
| 81 | tunables, |
| 82 | &mut validator, |
| 83 | &mut types, |
| 84 | StaticModuleIndex::from_u32(0), |
| 85 | ) |
| 86 | .translate(parser, wasm) |
| 87 | .context("failed to parse WebAssembly module")?; |
| 88 | prepare_translation(engine, compiler, &mut translation, &mut types); |
| 89 | let functions = mem::take(&mut translation.function_body_inputs); |
| 90 | |
| 91 | let compile_inputs = CompileInputs::for_module(&types, &translation, functions); |
| 92 | let unlinked_compile_outputs = compile_inputs.compile(engine, &types)?; |
| 93 | let PreLinkOutput { |
| 94 | needs_gc_heap, |
| 95 | compiled_funcs, |
| 96 | indices, |
| 97 | } = unlinked_compile_outputs.pre_link(); |
| 98 | translation.module.needs_gc_heap |= needs_gc_heap; |
| 99 | |
| 100 | // Emplace all compiled functions into the object file with any other |
| 101 | // sections associated with code as well. |
| 102 | let mut object = compiler.object(ObjectKind::Module)?; |
| 103 | // Insert `Engine` and type-level information into the compiled |
| 104 | // artifact so if this module is deserialized later it contains all |
| 105 | // information necessary. |
| 106 | // |
| 107 | // Note that `append_compiler_info` and `append_types` here in theory |
| 108 | // can both be skipped if this module will never get serialized. |
| 109 | // They're only used during deserialization and not during runtime for |
| 110 | // the module itself. Currently there's no need for that, however, so |
| 111 | // it's left as an exercise for later. |
| 112 | engine.append_compiler_info(&mut object)?; |
| 113 | engine.append_bti(&mut object); |
| 114 | |
| 115 | let (mut object, compilation_artifacts) = indices.link_and_append_code( |
| 116 | object, |
| 117 | engine, |
no test coverage detected