Refactor the compilation and instantiation pipeline.

wasmtime-execute is now wasmtime-jit. Move `JITCode` and the TargetIsa
into a new `Compiler` type. `InstancePlus` is no more, with trampoline
functionality now handled by `Compiler`.
This commit is contained in:
Dan Gohman
2019-01-03 06:59:46 -08:00
parent 450a279e18
commit 7592c99f3b
46 changed files with 1225 additions and 1073 deletions

View File

@@ -1,5 +1,6 @@
This is the `wasmtime-environ` crate, which contains the implementations
of the `ModuleEnvironment` and `FuncEnvironment` traits from
[`cranelift-wasm`](https://crates.io/crates/cranelift-wasm). They effectively
implement an ABI for basic wasm compilation, which can be used for JITing,
native object files, or other purposes.
implement an ABI for basic wasm compilation that defines how linear memories
are allocated, how indirect calls work, and other details. They can be used
for JITing, native object files, or other purposes.

View File

@@ -3,16 +3,9 @@
use cranelift_codegen::binemit;
use cranelift_codegen::ir;
use cranelift_codegen::ir::ExternalName;
use cranelift_codegen::isa;
use cranelift_codegen::{CodegenError, Context};
use cranelift_codegen::CodegenError;
use cranelift_entity::PrimaryMap;
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator, WasmError};
use func_environ::{
get_func_name, get_imported_memory32_grow_name, get_imported_memory32_size_name,
get_memory32_grow_name, get_memory32_size_name, FuncEnvironment,
};
use module::Module;
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError};
use std::vec::Vec;
/// The result of compiling a WebAssemby module's functions.
@@ -29,71 +22,6 @@ impl Compilation {
}
}
/// Implementation of a relocation sink that just saves all the information for later
pub struct RelocSink {
/// Relocations recorded for the function.
pub func_relocs: Vec<Relocation>,
}
impl binemit::RelocSink for RelocSink {
fn reloc_ebb(
&mut self,
_offset: binemit::CodeOffset,
_reloc: binemit::Reloc,
_ebb_offset: binemit::CodeOffset,
) {
// This should use the `offsets` field of `ir::Function`.
panic!("ebb headers not yet implemented");
}
fn reloc_external(
&mut self,
offset: binemit::CodeOffset,
reloc: binemit::Reloc,
name: &ExternalName,
addend: binemit::Addend,
) {
let reloc_target = if *name == get_memory32_grow_name() {
RelocationTarget::Memory32Grow
} else if *name == get_imported_memory32_grow_name() {
RelocationTarget::ImportedMemory32Grow
} else if *name == get_memory32_size_name() {
RelocationTarget::Memory32Size
} else if *name == get_imported_memory32_size_name() {
RelocationTarget::ImportedMemory32Size
} else if let ExternalName::User { namespace, index } = *name {
debug_assert!(namespace == 0);
RelocationTarget::UserFunc(FuncIndex::from_u32(index))
} else if let ExternalName::LibCall(libcall) = *name {
RelocationTarget::LibCall(libcall)
} else {
panic!("unrecognized external name")
};
self.func_relocs.push(Relocation {
reloc,
reloc_target,
offset,
addend,
});
}
fn reloc_jt(
&mut self,
_offset: binemit::CodeOffset,
_reloc: binemit::Reloc,
_jt: ir::JumpTable,
) {
panic!("jump tables not yet implemented");
}
}
impl RelocSink {
/// Return a new `RelocSink` instance.
pub fn new() -> Self {
Self {
func_relocs: Vec::new(),
}
}
}
/// A record of a relocation to perform.
#[derive(Debug, Clone)]
pub struct Relocation {
@@ -127,44 +55,6 @@ pub enum RelocationTarget {
/// Relocations to apply to function bodies.
pub type Relocations = PrimaryMap<DefinedFuncIndex, Vec<Relocation>>;
/// Compile the module, producing a compilation result with associated
/// relocations.
pub fn compile_module<'data, 'module>(
module: &'module Module,
function_body_inputs: &PrimaryMap<DefinedFuncIndex, &'data [u8]>,
isa: &isa::TargetIsa,
) -> Result<(Compilation, Relocations), CompileError> {
let mut functions = PrimaryMap::new();
let mut relocations = PrimaryMap::new();
for (i, input) in function_body_inputs.iter() {
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 trans = FuncTranslator::new();
trans
.translate(
input,
&mut context.func,
&mut FuncEnvironment::new(isa, module),
)
.map_err(CompileError::Wasm)?;
let mut code_buf: Vec<u8> = 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)?;
functions.push(code_buf);
relocations.push(reloc_sink.func_relocs);
}
// TODO: Reorganize where we create the Vec for the resolved imports.
Ok((Compilation::new(functions), relocations))
}
/// An error while compiling WebAssembly to machine code.
#[derive(Fail, Debug)]
pub enum CompileError {

View File

@@ -0,0 +1,119 @@
//! Support for compiling with Cranelift.
use compilation::{Compilation, CompileError, Relocation, RelocationTarget, Relocations};
use cranelift_codegen::binemit;
use cranelift_codegen::ir;
use cranelift_codegen::ir::ExternalName;
use cranelift_codegen::isa;
use cranelift_codegen::Context;
use cranelift_entity::PrimaryMap;
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator};
use func_environ::{
get_func_name, get_imported_memory32_grow_name, get_imported_memory32_size_name,
get_memory32_grow_name, get_memory32_size_name, FuncEnvironment,
};
use module::Module;
use std::vec::Vec;
/// Implementation of a relocation sink that just saves all the information for later
struct RelocSink {
/// Relocations recorded for the function.
func_relocs: Vec<Relocation>,
}
impl binemit::RelocSink for RelocSink {
fn reloc_ebb(
&mut self,
_offset: binemit::CodeOffset,
_reloc: binemit::Reloc,
_ebb_offset: binemit::CodeOffset,
) {
// This should use the `offsets` field of `ir::Function`.
panic!("ebb headers not yet implemented");
}
fn reloc_external(
&mut self,
offset: binemit::CodeOffset,
reloc: binemit::Reloc,
name: &ExternalName,
addend: binemit::Addend,
) {
let reloc_target = if *name == get_memory32_grow_name() {
RelocationTarget::Memory32Grow
} else if *name == get_imported_memory32_grow_name() {
RelocationTarget::ImportedMemory32Grow
} else if *name == get_memory32_size_name() {
RelocationTarget::Memory32Size
} else if *name == get_imported_memory32_size_name() {
RelocationTarget::ImportedMemory32Size
} else if let ExternalName::User { namespace, index } = *name {
debug_assert!(namespace == 0);
RelocationTarget::UserFunc(FuncIndex::from_u32(index))
} else if let ExternalName::LibCall(libcall) = *name {
RelocationTarget::LibCall(libcall)
} else {
panic!("unrecognized external name")
};
self.func_relocs.push(Relocation {
reloc,
reloc_target,
offset,
addend,
});
}
fn reloc_jt(
&mut self,
_offset: binemit::CodeOffset,
_reloc: binemit::Reloc,
_jt: ir::JumpTable,
) {
panic!("jump tables not yet implemented");
}
}
impl RelocSink {
/// Return a new `RelocSink` instance.
pub fn new() -> Self {
Self {
func_relocs: Vec::new(),
}
}
}
/// 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<DefinedFuncIndex, &'data [u8]>,
isa: &isa::TargetIsa,
) -> Result<(Compilation, Relocations), CompileError> {
let mut functions = PrimaryMap::new();
let mut relocations = PrimaryMap::new();
for (i, input) in function_body_inputs.into_iter() {
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 trans = FuncTranslator::new();
trans
.translate(
input,
&mut context.func,
&mut FuncEnvironment::new(isa.frontend_config(), module),
)
.map_err(CompileError::Wasm)?;
let mut code_buf: Vec<u8> = 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)?;
functions.push(code_buf);
relocations.push(reloc_sink.func_relocs);
}
// TODO: Reorganize where we create the Vec for the resolved imports.
Ok((Compilation::new(functions), relocations))
}

View File

@@ -7,7 +7,7 @@ use cranelift_codegen::ir::types::*;
use cranelift_codegen::ir::{
AbiParam, ArgumentPurpose, ExtFuncData, FuncRef, Function, InstBuilder, Signature,
};
use cranelift_codegen::isa;
use cranelift_codegen::isa::TargetFrontendConfig;
use cranelift_entity::EntityRef;
use cranelift_wasm::{
self, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex,
@@ -50,8 +50,8 @@ pub fn get_imported_memory32_size_name() -> ir::ExternalName {
/// The FuncEnvironment implementation for use by the `ModuleEnvironment`.
pub struct FuncEnvironment<'module_environment> {
/// Compilation setting flags.
isa: &'module_environment isa::TargetIsa,
/// Target-specified configuration.
target_config: TargetFrontendConfig,
/// The module-level environment which this function-level environment belongs to.
module: &'module_environment Module,
@@ -104,12 +104,9 @@ pub struct FuncEnvironment<'module_environment> {
}
impl<'module_environment> FuncEnvironment<'module_environment> {
pub fn new(
isa: &'module_environment isa::TargetIsa,
module: &'module_environment Module,
) -> Self {
pub fn new(target_config: TargetFrontendConfig, module: &'module_environment Module) -> Self {
Self {
isa,
target_config,
module,
vmctx: None,
imported_functions_base: None,
@@ -124,12 +121,12 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
imported_memory32_size_extfunc: None,
memory_grow_extfunc: None,
imported_memory_grow_extfunc: None,
offsets: VMOffsets::new(isa.pointer_bytes()),
offsets: VMOffsets::new(target_config.pointer_bytes()),
}
}
fn pointer_type(&self) -> ir::Type {
self.isa.frontend_config().pointer_type()
self.target_config.pointer_type()
}
fn vmctx(&mut self, func: &mut Function) -> ir::GlobalValue {
@@ -253,7 +250,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
],
returns: vec![AbiParam::new(I32)],
call_conv: self.isa.frontend_config().default_call_conv,
call_conv: self.target_config.default_call_conv,
})
}
@@ -303,7 +300,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
],
returns: vec![AbiParam::new(I32)],
call_conv: self.isa.frontend_config().default_call_conv,
call_conv: self.target_config.default_call_conv,
})
}
@@ -348,8 +345,8 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
}
impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> {
fn target_config(&self) -> isa::TargetFrontendConfig {
self.isa.frontend_config()
fn target_config(&self) -> TargetFrontendConfig {
self.target_config
}
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> ir::Table {

View File

@@ -45,12 +45,13 @@ mod module_environ;
mod tunables;
mod vmoffsets;
pub use compilation::{
compile_module, Compilation, CompileError, RelocSink, Relocation, RelocationTarget, Relocations,
};
pub mod cranelift;
pub use compilation::{Compilation, CompileError, Relocation, RelocationTarget, Relocations};
pub use module::{Export, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle};
pub use module_environ::{
translate_signature, DataInitializer, ModuleEnvironment, ModuleTranslation,
translate_signature, DataInitializer, DataInitializerLocation, ModuleEnvironment,
ModuleTranslation,
};
pub use tunables::Tunables;
pub use vmoffsets::VMOffsets;

View File

@@ -6,7 +6,6 @@ use cranelift_wasm::{
DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global,
GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
};
use std::cmp;
use std::collections::HashMap;
use std::string::String;
use std::vec::Vec;

View File

@@ -1,6 +1,6 @@
use cranelift_codegen::ir;
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
use cranelift_codegen::isa;
use cranelift_codegen::isa::TargetFrontendConfig;
use cranelift_entity::PrimaryMap;
use cranelift_wasm::{
self, translate_module, DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
@@ -13,139 +13,149 @@ use std::string::String;
use std::vec::Vec;
use tunables::Tunables;
/// Object containing the standalone environment information. To be passed after creation as
/// argument to `compile_module`.
pub struct ModuleEnvironment<'data, 'module> {
/// The result of translating via `ModuleEnvironment`. Function bodies are not
/// yet translated, and data initializers have not yet been copied out of the
/// original buffer.
pub struct ModuleTranslation<'data> {
/// Compilation setting flags.
isa: &'module isa::TargetIsa,
pub target_config: TargetFrontendConfig,
/// Module information.
module: &'module mut Module,
pub module: Module,
/// References to information to be decoded later.
lazy: LazyContents<'data>,
/// References to the function bodies.
pub function_body_inputs: PrimaryMap<DefinedFuncIndex, &'data [u8]>,
/// References to the data initializers.
pub data_initializers: Vec<DataInitializer<'data>>,
/// Tunable parameters.
tunables: Tunables,
pub tunables: Tunables,
}
impl<'data, 'module> ModuleEnvironment<'data, 'module> {
/// Allocates the enironment data structures with the given isa.
pub fn new(
isa: &'module isa::TargetIsa,
module: &'module mut Module,
tunables: Tunables,
) -> Self {
impl<'data> ModuleTranslation<'data> {
/// Return a new `FuncEnvironment` for translating a function.
pub fn func_env(&self) -> FuncEnvironment {
FuncEnvironment::new(self.target_config, &self.module)
}
}
/// Object containing the standalone environment information.
pub struct ModuleEnvironment<'data> {
/// The result to be filled in.
result: ModuleTranslation<'data>,
}
impl<'data> ModuleEnvironment<'data> {
/// Allocates the enironment data structures.
pub fn new(target_config: TargetFrontendConfig, tunables: Tunables) -> Self {
Self {
isa,
module,
lazy: LazyContents::new(),
tunables,
result: ModuleTranslation {
target_config,
module: Module::new(),
function_body_inputs: PrimaryMap::new(),
data_initializers: Vec::new(),
tunables,
},
}
}
fn pointer_type(&self) -> ir::Type {
self.isa.frontend_config().pointer_type()
self.result.target_config.pointer_type()
}
/// Translate the given wasm module data using this environment. This consumes the
/// `ModuleEnvironment` with its mutable reference to the `Module` and produces a
/// `ModuleTranslation` with an immutable reference to the `Module` (which has
/// become fully populated).
pub fn translate(mut self, data: &'data [u8]) -> WasmResult<ModuleTranslation<'data, 'module>> {
/// Translate a wasm module using this environment. This consumes the
/// `ModuleEnvironment` and produces a `ModuleTranslation`.
pub fn translate(mut self, data: &'data [u8]) -> WasmResult<ModuleTranslation<'data>> {
translate_module(data, &mut self)?;
Ok(ModuleTranslation {
isa: self.isa,
module: self.module,
lazy: self.lazy,
tunables: self.tunables,
})
Ok(self.result)
}
}
/// This trait is useful for `translate_module` because it tells how to translate
/// enironment-dependent wasm instructions. These functions should not be called by the user.
impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
for ModuleEnvironment<'data, 'module>
{
fn target_config(&self) -> isa::TargetFrontendConfig {
self.isa.frontend_config()
impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data> {
fn target_config(&self) -> TargetFrontendConfig {
self.result.target_config
}
fn declare_signature(&mut self, sig: &ir::Signature) {
let sig = translate_signature(sig.clone(), self.pointer_type());
// TODO: Deduplicate signatures.
self.module.signatures.push(sig);
self.result.module.signatures.push(sig);
}
fn get_signature(&self, sig_index: SignatureIndex) -> &ir::Signature {
&self.module.signatures[sig_index]
&self.result.module.signatures[sig_index]
}
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &str, field: &str) {
debug_assert_eq!(
self.module.functions.len(),
self.module.imported_funcs.len(),
self.result.module.functions.len(),
self.result.module.imported_funcs.len(),
"Imported functions must be declared first"
);
self.module.functions.push(sig_index);
self.result.module.functions.push(sig_index);
self.module
self.result
.module
.imported_funcs
.push((String::from(module), String::from(field)));
}
fn get_num_func_imports(&self) -> usize {
self.module.imported_funcs.len()
self.result.module.imported_funcs.len()
}
fn declare_func_type(&mut self, sig_index: SignatureIndex) {
self.module.functions.push(sig_index);
self.result.module.functions.push(sig_index);
}
fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex {
self.module.functions[func_index]
self.result.module.functions[func_index]
}
fn declare_global_import(&mut self, global: Global, module: &str, field: &str) {
debug_assert_eq!(
self.module.globals.len(),
self.module.imported_globals.len(),
self.result.module.globals.len(),
self.result.module.imported_globals.len(),
"Imported globals must be declared first"
);
self.module.globals.push(global);
self.result.module.globals.push(global);
self.module
self.result
.module
.imported_globals
.push((String::from(module), String::from(field)));
}
fn declare_global(&mut self, global: Global) {
self.module.globals.push(global);
self.result.module.globals.push(global);
}
fn get_global(&self, global_index: GlobalIndex) -> &Global {
&self.module.globals[global_index]
&self.result.module.globals[global_index]
}
fn declare_table_import(&mut self, table: Table, module: &str, field: &str) {
debug_assert_eq!(
self.module.table_plans.len(),
self.module.imported_tables.len(),
self.result.module.table_plans.len(),
self.result.module.imported_tables.len(),
"Imported tables must be declared first"
);
let plan = TablePlan::for_table(table, &self.tunables);
self.module.table_plans.push(plan);
let plan = TablePlan::for_table(table, &self.result.tunables);
self.result.module.table_plans.push(plan);
self.module
self.result
.module
.imported_tables
.push((String::from(module), String::from(field)));
}
fn declare_table(&mut self, table: Table) {
let plan = TablePlan::for_table(table, &self.tunables);
self.module.table_plans.push(plan);
let plan = TablePlan::for_table(table, &self.result.tunables);
self.result.module.table_plans.push(plan);
}
fn declare_table_elements(
@@ -155,7 +165,7 @@ impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
offset: usize,
elements: Vec<FuncIndex>,
) {
self.module.table_elements.push(TableElements {
self.result.module.table_elements.push(TableElements {
table_index,
base,
offset,
@@ -165,21 +175,22 @@ impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
fn declare_memory_import(&mut self, memory: Memory, module: &str, field: &str) {
debug_assert_eq!(
self.module.memory_plans.len(),
self.module.imported_memories.len(),
self.result.module.memory_plans.len(),
self.result.module.imported_memories.len(),
"Imported memories must be declared first"
);
let plan = MemoryPlan::for_memory(memory, &self.tunables);
self.module.memory_plans.push(plan);
let plan = MemoryPlan::for_memory(memory, &self.result.tunables);
self.result.module.memory_plans.push(plan);
self.module
self.result
.module
.imported_memories
.push((String::from(module), String::from(field)));
}
fn declare_memory(&mut self, memory: Memory) {
let plan = MemoryPlan::for_memory(memory, &self.tunables);
self.module.memory_plans.push(plan);
let plan = MemoryPlan::for_memory(memory, &self.result.tunables);
self.result.module.memory_plans.push(plan);
}
fn declare_data_initialization(
@@ -189,71 +200,55 @@ impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
offset: usize,
data: &'data [u8],
) {
self.lazy.data_initializers.push(DataInitializer {
memory_index,
base,
offset,
self.result.data_initializers.push(DataInitializer {
location: DataInitializerLocation {
memory_index,
base,
offset,
},
data,
});
}
fn declare_func_export(&mut self, func_index: FuncIndex, name: &str) {
self.module
self.result
.module
.exports
.insert(String::from(name), Export::Function(func_index));
}
fn declare_table_export(&mut self, table_index: TableIndex, name: &str) {
self.module
self.result
.module
.exports
.insert(String::from(name), Export::Table(table_index));
}
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &str) {
self.module
self.result
.module
.exports
.insert(String::from(name), Export::Memory(memory_index));
}
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &str) {
self.module
self.result
.module
.exports
.insert(String::from(name), Export::Global(global_index));
}
fn declare_start_func(&mut self, func_index: FuncIndex) {
debug_assert!(self.module.start_func.is_none());
self.module.start_func = Some(func_index);
debug_assert!(self.result.module.start_func.is_none());
self.result.module.start_func = Some(func_index);
}
fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()> {
self.lazy.function_body_inputs.push(body_bytes);
self.result.function_body_inputs.push(body_bytes);
Ok(())
}
}
/// The result of translating via `ModuleEnvironment`.
pub struct ModuleTranslation<'data, 'module> {
/// Compilation setting flags.
pub isa: &'module isa::TargetIsa,
/// Module information.
pub module: &'module Module,
/// Pointers into the raw data buffer.
pub lazy: LazyContents<'data>,
/// Tunable parameters.
pub tunables: Tunables,
}
impl<'data, 'module> ModuleTranslation<'data, 'module> {
/// Return a new `FuncEnvironment` for translating a function.
pub fn func_env(&self) -> FuncEnvironment {
FuncEnvironment::new(self.isa, &self.module)
}
}
/// Add environment-specific function parameters.
pub fn translate_signature(mut sig: ir::Signature, pointer_type: ir::Type) -> ir::Signature {
sig.params
@@ -261,33 +256,25 @@ pub fn translate_signature(mut sig: ir::Signature, pointer_type: ir::Type) -> ir
sig
}
/// A data initializer for linear memory.
pub struct DataInitializer<'data> {
/// A memory index and offset within that memory where a data initialization
/// should is to be performed.
#[derive(Clone)]
pub struct DataInitializerLocation {
/// The index of the memory to initialize.
pub memory_index: MemoryIndex,
/// Optionally a globalvar base to initialize at.
pub base: Option<GlobalIndex>,
/// A constant offset to initialize at.
pub offset: usize,
}
/// A data initializer for linear memory.
pub struct DataInitializer<'data> {
/// The location where the initialization is to be performed.
pub location: DataInitializerLocation,
/// The initialization data.
pub data: &'data [u8],
}
/// References to the input wasm data buffer to be decoded and processed later,
/// separately from the main module translation.
pub struct LazyContents<'data> {
/// References to the function bodies.
pub function_body_inputs: PrimaryMap<DefinedFuncIndex, &'data [u8]>,
/// References to the data initializers.
pub data_initializers: Vec<DataInitializer<'data>>,
}
impl<'data> LazyContents<'data> {
pub fn new() -> Self {
Self {
function_body_inputs: PrimaryMap::new(),
data_initializers: Vec::new(),
}
}
}

View File

@@ -1,4 +1,4 @@
//! Offsets and sizes of various structs in wasmtime-execute's vmcontext
//! Offsets and sizes of various structs in wasmtime-runtime's vmcontext
//! module.
use cranelift_codegen::ir;