From 9bf6d73210aab3665102381377a8ffa6ff1445ec Mon Sep 17 00:00:00 2001 From: Jef Date: Fri, 5 Apr 2019 21:42:54 +0200 Subject: [PATCH] Integrate Lightbeam (#51) * Integrate lightbeam --- .gitmodules | 4 + Cargo.toml | 3 + lightbeam | 1 + spec_testsuite | 2 +- src/wasm2obj.rs | 4 +- wasmtime-environ/Cargo.toml | 1 + wasmtime-environ/src/compilation.rs | 69 ++++++++++++-- wasmtime-environ/src/cranelift.rs | 128 +++++++++++++------------ wasmtime-environ/src/func_environ.rs | 136 ++++++++++++++++++++++++++- wasmtime-environ/src/lib.rs | 9 +- wasmtime-environ/src/lightbeam.rs | 55 +++++++++++ wasmtime-jit/Cargo.toml | 1 + wasmtime-jit/src/compiler.rs | 19 ++-- wasmtime-obj/src/function.rs | 4 +- 14 files changed, 351 insertions(+), 85 deletions(-) create mode 160000 lightbeam create mode 100644 wasmtime-environ/src/lightbeam.rs diff --git a/.gitmodules b/.gitmodules index 5e65dc7b8f..841205cbc9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "spec_testsuite"] path = spec_testsuite url = https://github.com/WebAssembly/testsuite +[submodule "lightbeam"] + path = lightbeam + url = https://github.com/CraneStation/lightbeam.git + branch = master diff --git a/Cargo.toml b/Cargo.toml index e2adda09ec..782ac5e242 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,3 +44,6 @@ libc = "0.2.50" errno = "0.2.4" [workspace] + +[features] +lightbeam = ["wasmtime-environ/lightbeam", "wasmtime-jit/lightbeam"] diff --git a/lightbeam b/lightbeam new file mode 160000 index 0000000000..762cd3fb32 --- /dev/null +++ b/lightbeam @@ -0,0 +1 @@ +Subproject commit 762cd3fb323a4755daa29c0282ee08f5e560a35b diff --git a/spec_testsuite b/spec_testsuite index 89cc463fa1..b2800641d6 160000 --- a/spec_testsuite +++ b/spec_testsuite @@ -1 +1 @@ -Subproject commit 89cc463fa1251449d7974086a34ef0dc100b1582 +Subproject commit b2800641d6c6b6a0c462f83e620843c414bea579 diff --git a/src/wasm2obj.rs b/src/wasm2obj.rs index c68ddb50b7..8b7b6de97f 100644 --- a/src/wasm2obj.rs +++ b/src/wasm2obj.rs @@ -49,7 +49,7 @@ use std::str; use std::str::FromStr; use target_lexicon::Triple; use wasmtime_debug::{emit_debugsections, read_debuginfo}; -use wasmtime_environ::{cranelift, ModuleEnvironment, Tunables}; +use wasmtime_environ::{Compiler, Cranelift, ModuleEnvironment, Tunables}; use wasmtime_obj::emit_module; const USAGE: &str = " @@ -159,7 +159,7 @@ fn handle_module( ) }; - let (compilation, relocations, address_transform) = cranelift::compile_module( + let (compilation, relocations, address_transform) = Cranelift::compile_module( &module, lazy_function_body_inputs, &*isa, diff --git a/wasmtime-environ/Cargo.toml b/wasmtime-environ/Cargo.toml index d7bd741e10..c500d961cb 100644 --- a/wasmtime-environ/Cargo.toml +++ b/wasmtime-environ/Cargo.toml @@ -15,6 +15,7 @@ edition = "2018" cranelift-codegen = "0.30.0" cranelift-entity = "0.30.0" cranelift-wasm = "0.30.0" +lightbeam = { path = "../lightbeam", optional = true } cast = { version = "0.2.2", default-features = false } failure = { version = "0.1.3", default-features = false } failure_derive = { version = "0.1.3", default-features = false } diff --git a/wasmtime-environ/src/compilation.rs b/wasmtime-environ/src/compilation.rs index d566051fef..c67a626876 100644 --- a/wasmtime-environ/src/compilation.rs +++ b/wasmtime-environ/src/compilation.rs @@ -1,25 +1,71 @@ //! A `Compilation` contains the compiled function bodies for a WebAssembly //! module. -use cranelift_codegen::binemit; -use cranelift_codegen::ir; -use cranelift_codegen::CodegenError; +use crate::module; +use crate::module_environ::FunctionBodyData; +use cranelift_codegen::{binemit, ir, isa, CodegenError}; use cranelift_entity::PrimaryMap; use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError}; +use std::ops::Range; use std::vec::Vec; +type Functions = PrimaryMap>; + /// The result of compiling a WebAssembly module's functions. #[derive(Debug)] pub struct Compilation { /// Compiled machine code for the function bodies. - pub functions: PrimaryMap>, + functions: Functions, } impl Compilation { - /// Allocates the compilation result with the given function bodies. - pub fn new(functions: PrimaryMap>) -> Self { + /// Creates a compilation artifact from a contiguous function buffer and a set of ranges + pub fn new(functions: Functions) -> Self { Self { functions } } + + /// Allocates the compilation result with the given function bodies. + pub fn from_buffer(buffer: Vec, functions: impl IntoIterator>) -> Self { + Self::new( + functions + .into_iter() + .map(|range| buffer[range].to_vec()) + .collect(), + ) + } + + /// Gets the bytes of a single function + pub fn get(&self, func: DefinedFuncIndex) -> &[u8] { + &self.functions[func] + } + + /// Gets the number of functions defined. + pub fn len(&self) -> usize { + self.functions.len() + } +} + +impl<'a> IntoIterator for &'a Compilation { + type IntoIter = Iter<'a>; + type Item = ::Item; + + fn into_iter(self) -> Self::IntoIter { + Iter { + iterator: self.functions.iter(), + } + } +} + +pub struct Iter<'a> { + iterator: <&'a Functions as IntoIterator>::IntoIter, +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a [u8]; + + fn next(&mut self) -> Option { + self.iterator.next().map(|(_, b)| &b[..]) + } } /// A record of a relocation to perform. @@ -95,3 +141,14 @@ pub struct FunctionAddressTransform { /// Function AddressTransforms collection. pub type AddressTransforms = PrimaryMap; + +/// An implementation of a compiler from parsed WebAssembly module to native code. +pub trait Compiler { + /// Compile a parsed module with the given `TargetIsa`. + fn compile_module<'data, 'module>( + module: &'module module::Module, + function_body_inputs: PrimaryMap>, + isa: &dyn isa::TargetIsa, + generate_debug_info: bool, + ) -> Result<(Compilation, Relocations, AddressTransforms), CompileError>; +} diff --git a/wasmtime-environ/src/cranelift.rs b/wasmtime-environ/src/cranelift.rs index 5c62be4f25..4aadc354b8 100644 --- a/wasmtime-environ/src/cranelift.rs +++ b/wasmtime-environ/src/cranelift.rs @@ -21,9 +21,9 @@ use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use std::vec::Vec; /// Implementation of a relocation sink that just saves all the information for later -struct RelocSink { +pub struct RelocSink { /// Relocations recorded for the function. - func_relocs: Vec, + pub func_relocs: Vec, } impl binemit::RelocSink for RelocSink { @@ -109,69 +109,75 @@ fn get_address_transform( result } -/// Compile the module using Cranelift, producing a compilation result with -/// associated relocations. -pub fn compile_module<'data, 'module>( - module: &'module Module, - function_body_inputs: PrimaryMap>, - isa: &dyn isa::TargetIsa, - generate_debug_info: bool, -) -> Result<(Compilation, Relocations, AddressTransforms), CompileError> { - let mut functions = PrimaryMap::with_capacity(function_body_inputs.len()); - let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len()); - let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len()); +/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR, +/// optimizing it and then translating to assembly. +pub struct Cranelift; - function_body_inputs - .into_iter() - .collect::)>>() - .par_iter() - .map(|(i, input)| { - let func_index = module.func_index(*i); - let mut context = Context::new(); - context.func.name = get_func_name(func_index); - context.func.signature = module.signatures[module.functions[func_index]].clone(); +impl crate::compilation::Compiler for Cranelift { + /// Compile the module using Cranelift, producing a compilation result with + /// associated relocations. + fn compile_module<'data, 'module>( + module: &'module Module, + function_body_inputs: PrimaryMap>, + isa: &dyn isa::TargetIsa, + generate_debug_info: bool, + ) -> Result<(Compilation, Relocations, AddressTransforms), CompileError> { + let mut functions = PrimaryMap::with_capacity(function_body_inputs.len()); + let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len()); + let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len()); - let mut trans = FuncTranslator::new(); - trans - .translate( - input.data, - input.module_offset, - &mut context.func, - &mut FuncEnvironment::new(isa.frontend_config(), module), - ) - .map_err(CompileError::Wasm)?; + function_body_inputs + .into_iter() + .collect::)>>() + .par_iter() + .map(|(i, input)| { + let func_index = module.func_index(*i); + let mut context = Context::new(); + context.func.name = get_func_name(func_index); + context.func.signature = module.signatures[module.functions[func_index]].clone(); - let mut code_buf: Vec = Vec::new(); - let mut reloc_sink = RelocSink::new(); - let mut trap_sink = binemit::NullTrapSink {}; - context - .compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut trap_sink) - .map_err(CompileError::Codegen)?; + let mut trans = FuncTranslator::new(); + trans + .translate( + input.data, + input.module_offset, + &mut context.func, + &mut FuncEnvironment::new(isa.frontend_config(), module), + ) + .map_err(CompileError::Wasm)?; - let address_transform = if generate_debug_info { - let body_len = code_buf.len(); - let at = get_address_transform(&context, isa); - Some(FunctionAddressTransform { - locations: at, - body_offset: 0, - body_len, - }) - } else { - None - }; + let mut code_buf: Vec = Vec::new(); + let mut reloc_sink = RelocSink::new(); + let mut trap_sink = binemit::NullTrapSink {}; + context + .compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut trap_sink) + .map_err(CompileError::Codegen)?; - Ok((code_buf, reloc_sink.func_relocs, address_transform)) - }) - .collect::, CompileError>>()? - .into_iter() - .for_each(|(function, relocs, address_transform)| { - functions.push(function); - relocations.push(relocs); - if let Some(address_transform) = address_transform { - address_transforms.push(address_transform); - } - }); + let address_transform = if generate_debug_info { + let body_len = code_buf.len(); + let at = get_address_transform(&context, isa); + Some(FunctionAddressTransform { + locations: at, + body_offset: 0, + body_len, + }) + } else { + None + }; - // TODO: Reorganize where we create the Vec for the resolved imports. - Ok((Compilation::new(functions), relocations, address_transforms)) + Ok((code_buf, reloc_sink.func_relocs, address_transform)) + }) + .collect::, CompileError>>()? + .into_iter() + .for_each(|(function, relocs, address_transform)| { + functions.push(function); + relocations.push(relocs); + if let Some(address_transform) = address_transform { + address_transforms.push(address_transform); + } + }); + + // TODO: Reorganize where we create the Vec for the resolved imports. + Ok((Compilation::new(functions), relocations, address_transforms)) + } } diff --git a/wasmtime-environ/src/func_environ.rs b/wasmtime-environ/src/func_environ.rs index fefe075501..57f55ab787 100644 --- a/wasmtime-environ/src/func_environ.rs +++ b/wasmtime-environ/src/func_environ.rs @@ -14,8 +14,8 @@ use cranelift_codegen::ir::{ use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_entity::EntityRef; use cranelift_wasm::{ - self, FuncIndex, GlobalIndex, GlobalVariable, MemoryIndex, SignatureIndex, TableIndex, - WasmResult, + self, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, + GlobalIndex, GlobalVariable, MemoryIndex, SignatureIndex, TableIndex, WasmResult, }; use std::vec::Vec; @@ -207,6 +207,138 @@ impl<'module_environment> FuncEnvironment<'module_environment> { } } +#[cfg(feature = "lightbeam")] +impl lightbeam::ModuleContext for FuncEnvironment<'_> { + type Signature = ir::Signature; + type GlobalType = ir::Type; + + fn func_index(&self, defined_func_index: u32) -> u32 { + self.module + .func_index(DefinedFuncIndex::from_u32(defined_func_index)) + .as_u32() + } + + fn defined_func_index(&self, func_index: u32) -> Option { + self.module + .defined_func_index(FuncIndex::from_u32(func_index)) + .map(|i| i.as_u32()) + } + + fn defined_global_index(&self, global_index: u32) -> Option { + self.module + .defined_global_index(GlobalIndex::from_u32(global_index)) + .map(|i| i.as_u32()) + } + + fn global_type(&self, global_index: u32) -> &Self::GlobalType { + &self.module.globals[GlobalIndex::from_u32(global_index)].ty + } + + fn func_type_index(&self, func_idx: u32) -> u32 { + self.module.functions[FuncIndex::from_u32(func_idx)].as_u32() + } + + fn signature(&self, index: u32) -> &Self::Signature { + &self.module.signatures[SignatureIndex::from_u32(index)] + } + + fn defined_table_index(&self, table_index: u32) -> Option { + self.module + .defined_table_index(TableIndex::from_u32(table_index)) + .map(|i| i.as_u32()) + } + + fn defined_memory_index(&self, memory_index: u32) -> Option { + self.module + .defined_memory_index(MemoryIndex::from_u32(memory_index)) + .map(|i| i.as_u32()) + } + + fn vmctx_vmfunction_import_body(&self, func_index: u32) -> u32 { + self.offsets + .vmctx_vmfunction_import_body(FuncIndex::from_u32(func_index)) + } + fn vmctx_vmfunction_import_vmctx(&self, func_index: u32) -> u32 { + self.offsets + .vmctx_vmfunction_import_vmctx(FuncIndex::from_u32(func_index)) + } + + fn vmctx_vmglobal_import_from(&self, global_index: u32) -> u32 { + self.offsets + .vmctx_vmglobal_import_from(GlobalIndex::from_u32(global_index)) + } + fn vmctx_vmglobal_definition(&self, defined_global_index: u32) -> u32 { + self.offsets + .vmctx_vmglobal_definition(DefinedGlobalIndex::from_u32(defined_global_index)) + } + fn vmctx_vmmemory_import_from(&self, memory_index: u32) -> u32 { + self.offsets + .vmctx_vmmemory_import_from(MemoryIndex::from_u32(memory_index)) + } + fn vmctx_vmmemory_definition(&self, defined_memory_index: u32) -> u32 { + self.offsets + .vmctx_vmmemory_definition(DefinedMemoryIndex::from_u32(defined_memory_index)) + } + fn vmctx_vmmemory_definition_base(&self, defined_memory_index: u32) -> u32 { + self.offsets + .vmctx_vmmemory_definition_base(DefinedMemoryIndex::from_u32(defined_memory_index)) + } + fn vmctx_vmmemory_definition_current_length(&self, defined_memory_index: u32) -> u32 { + self.offsets + .vmctx_vmmemory_definition_current_length(DefinedMemoryIndex::from_u32( + defined_memory_index, + )) + } + fn vmmemory_definition_base(&self) -> u8 { + self.offsets.vmmemory_definition_base() + } + fn vmmemory_definition_current_length(&self) -> u8 { + self.offsets.vmmemory_definition_current_length() + } + fn vmctx_vmtable_import_from(&self, table_index: u32) -> u32 { + self.offsets + .vmctx_vmtable_import_from(TableIndex::from_u32(table_index)) + } + fn vmctx_vmtable_definition(&self, defined_table_index: u32) -> u32 { + self.offsets + .vmctx_vmtable_definition(DefinedTableIndex::from_u32(defined_table_index)) + } + fn vmctx_vmtable_definition_base(&self, defined_table_index: u32) -> u32 { + self.offsets + .vmctx_vmtable_definition_base(DefinedTableIndex::from_u32(defined_table_index)) + } + fn vmctx_vmtable_definition_current_elements(&self, defined_table_index: u32) -> u32 { + self.offsets + .vmctx_vmtable_definition_current_elements(DefinedTableIndex::from_u32( + defined_table_index, + )) + } + fn vmtable_definition_base(&self) -> u8 { + self.offsets.vmtable_definition_base() + } + fn vmtable_definition_current_elements(&self) -> u8 { + self.offsets.vmtable_definition_current_elements() + } + fn vmcaller_checked_anyfunc_type_index(&self) -> u8 { + self.offsets.vmcaller_checked_anyfunc_type_index() + } + fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 { + self.offsets.vmcaller_checked_anyfunc_func_ptr() + } + fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 { + self.offsets.vmcaller_checked_anyfunc_vmctx() + } + fn size_of_vmcaller_checked_anyfunc(&self) -> u8 { + self.offsets.size_of_vmcaller_checked_anyfunc() + } + fn vmctx_vmshared_signature_id(&self, signature_idx: u32) -> u32 { + self.offsets + .vmctx_vmshared_signature_id(SignatureIndex::from_u32(signature_idx)) + } + + // TODO: type of a global +} + impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> { fn target_config(&self) -> TargetFrontendConfig { self.target_config diff --git a/wasmtime-environ/src/lib.rs b/wasmtime-environ/src/lib.rs index e5cd6c6643..4c0d214fbf 100644 --- a/wasmtime-environ/src/lib.rs +++ b/wasmtime-environ/src/lib.rs @@ -45,11 +45,16 @@ mod tunables; mod vmoffsets; pub mod cranelift; +#[cfg(feature = "lightbeam")] +pub mod lightbeam; pub use crate::compilation::{ - AddressTransforms, Compilation, CompileError, InstructionAddressTransform, Relocation, - RelocationTarget, Relocations, + AddressTransforms, Compilation, CompileError, Compiler, InstructionAddressTransform, + Relocation, RelocationTarget, Relocations, }; +pub use crate::cranelift::Cranelift; +#[cfg(feature = "lightbeam")] +pub use crate::lightbeam::Lightbeam; pub use crate::module::{ Export, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle, }; diff --git a/wasmtime-environ/src/lightbeam.rs b/wasmtime-environ/src/lightbeam.rs new file mode 100644 index 0000000000..0edd8d9a24 --- /dev/null +++ b/wasmtime-environ/src/lightbeam.rs @@ -0,0 +1,55 @@ +//! Support for compiling with Lightbeam. + +use crate::compilation::{AddressTransforms, Compilation, CompileError, Relocations}; +use crate::func_environ::FuncEnvironment; +use crate::module::Module; +use crate::module_environ::FunctionBodyData; +// TODO: Put this in `compilation` +use crate::cranelift::RelocSink; +use cranelift_codegen::isa; +use cranelift_entity::PrimaryMap; +use cranelift_wasm::DefinedFuncIndex; +use lightbeam; + +/// A compiler that compiles a WebAssembly module with Lightbeam, directly translating the Wasm file. +pub struct Lightbeam; + +impl crate::compilation::Compiler for Lightbeam { + /// Compile the module using Lightbeam, producing a compilation result with + /// associated relocations. + fn compile_module<'data, 'module>( + module: &'module Module, + function_body_inputs: PrimaryMap>, + isa: &dyn isa::TargetIsa, + // TODO + _generate_debug_info: bool, + ) -> Result<(Compilation, Relocations, AddressTransforms), CompileError> { + let env = FuncEnvironment::new(isa.frontend_config(), module); + let mut relocations = PrimaryMap::new(); + let mut codegen_session: lightbeam::CodeGenSession<_> = + lightbeam::CodeGenSession::new(function_body_inputs.len() as u32, &env); + + for (i, function_body) in &function_body_inputs { + let mut reloc_sink = RelocSink::new(); + + lightbeam::translate_function( + &mut codegen_session, + &mut reloc_sink, + i.as_u32(), + &lightbeam::wasmparser::FunctionBody::new(0, function_body.data), + ) + .expect("Failed to translate function. TODO: Stop this from panicking"); + relocations.push(reloc_sink.func_relocs); + } + + let code_section = codegen_session + .into_translated_code_section() + .expect("Failed to generate output code. TODO: Stop this from panicking"); + + Ok(( + Compilation::from_buffer(code_section.buffer().to_vec(), code_section.funcs()), + relocations, + AddressTransforms::new(), + )) + } +} diff --git a/wasmtime-jit/Cargo.toml b/wasmtime-jit/Cargo.toml index 1015019759..644aee66f9 100644 --- a/wasmtime-jit/Cargo.toml +++ b/wasmtime-jit/Cargo.toml @@ -30,6 +30,7 @@ wasmparser = "0.29.2" default = ["std"] std = ["cranelift-codegen/std", "cranelift-wasm/std"] core = ["hashbrown/nightly", "cranelift-codegen/core", "cranelift-wasm/core", "wasmtime-environ/core"] +lightbeam = ["wasmtime-environ/lightbeam"] [badges] maintenance = { status = "experimental" } diff --git a/wasmtime-jit/src/compiler.rs b/wasmtime-jit/src/compiler.rs index 9f7084de06..e100684fd4 100644 --- a/wasmtime-jit/src/compiler.rs +++ b/wasmtime-jit/src/compiler.rs @@ -17,7 +17,7 @@ use std::vec::Vec; use wasmtime_debug::{emit_debugsections_image, DebugInfoData}; use wasmtime_environ::cranelift; use wasmtime_environ::{ - Compilation, CompileError, FunctionBodyData, Module, Relocations, Tunables, + Compilation, CompileError, Compiler as _C, FunctionBodyData, Module, Relocations, Tunables, }; use wasmtime_runtime::{InstantiationError, SignatureRegistry, VMFunctionBody}; @@ -53,6 +53,11 @@ impl Compiler { } } +#[cfg(feature = "lightbeam")] +type DefaultCompiler = wasmtime_environ::lightbeam::Lightbeam; +#[cfg(not(feature = "lightbeam"))] +type DefaultCompiler = wasmtime_environ::cranelift::Cranelift; + impl Compiler { /// Return the target's frontend configuration settings. pub fn frontend_config(&self) -> TargetFrontendConfig { @@ -78,7 +83,7 @@ impl Compiler { ), SetupError, > { - let (compilation, relocations, address_transform) = cranelift::compile_module( + let (compilation, relocations, address_transform) = DefaultCompiler::compile_module( module, function_body_inputs, &*self.isa, @@ -100,7 +105,7 @@ impl Compiler { let mut funcs = Vec::new(); for (i, allocated) in allocated_functions.into_iter() { let ptr = (*allocated) as *const u8; - let body_len = compilation.functions[i].len(); + let body_len = compilation.get(i).len(); funcs.push((ptr, body_len)); } let bytes = emit_debugsections_image( @@ -255,14 +260,10 @@ fn allocate_functions( // Allocate code for all function in one continuous memory block. // First, collect all function bodies into vector to pass to the // allocate_copy_of_byte_slices. - let bodies = compilation - .functions - .values() - .map(|body| body.as_slice()) - .collect::>(); + let bodies = compilation.into_iter().collect::>(); let fat_ptrs = code_memory.allocate_copy_of_byte_slices(&bodies)?; // Second, create a PrimaryMap from result vector of pointers. - let mut result = PrimaryMap::with_capacity(compilation.functions.len()); + let mut result = PrimaryMap::with_capacity(compilation.len()); for i in 0..fat_ptrs.len() { let fat_ptr: *mut [VMFunctionBody] = fat_ptrs[i]; result.push(fat_ptr); diff --git a/wasmtime-obj/src/function.rs b/wasmtime-obj/src/function.rs index 49bd57ce65..fad88c39e8 100644 --- a/wasmtime-obj/src/function.rs +++ b/wasmtime-obj/src/function.rs @@ -62,11 +62,11 @@ pub fn emit_functions( .expect("Missing enable_verifier setting"); for (i, _function_relocs) in relocations.iter() { - let body = &compilation.functions[i]; + let body = compilation.get(i); let func_index = module.func_index(i); let string_name = format!("_wasm_function_{}", func_index.index()); - obj.define(string_name, body.clone()) + obj.define(string_name, body.to_vec()) .map_err(|err| format!("{}", err))?; }