Update to Cranelift 0.22.
This commit is contained in:
@@ -18,8 +18,8 @@ name = "wasm2obj"
|
|||||||
path = "src/wasm2obj.rs"
|
path = "src/wasm2obj.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-codegen = "0.20.0"
|
cranelift-codegen = "0.22.0"
|
||||||
cranelift-native = "0.20.0"
|
cranelift-native = "0.22.0"
|
||||||
wasmtime-environ = { path = "lib/environ" }
|
wasmtime-environ = { path = "lib/environ" }
|
||||||
wasmtime-execute = { path = "lib/execute" }
|
wasmtime-execute = { path = "lib/execute" }
|
||||||
wasmtime-obj = { path = "lib/obj" }
|
wasmtime-obj = { path = "lib/obj" }
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ cargo-fuzz = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime-environ = { path = "../lib/environ" }
|
wasmtime-environ = { path = "../lib/environ" }
|
||||||
wasmtime-execute = { path = "../lib/execute" }
|
wasmtime-execute = { path = "../lib/execute" }
|
||||||
cranelift-codegen = "0.20.0"
|
cranelift-codegen = "0.22.0"
|
||||||
cranelift-wasm = "0.20.1"
|
cranelift-wasm = "0.22.0"
|
||||||
cranelift-native = "0.20.0"
|
cranelift-native = "0.22.0"
|
||||||
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
|
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
|
||||||
wasmparser = { version = "0.17.2", default-features = false }
|
wasmparser = { version = "0.17.2", default-features = false }
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ license = "Apache-2.0 WITH LLVM-exception"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-codegen = "0.20.0"
|
cranelift-codegen = "0.22.0"
|
||||||
cranelift-entity = "0.20.1"
|
cranelift-entity = "0.22.0"
|
||||||
cranelift-wasm = "0.20.1"
|
cranelift-wasm = "0.22.0"
|
||||||
target-lexicon = "0.0.3"
|
target-lexicon = "0.0.3"
|
||||||
|
memoffset = "0.2.1"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "experimental" }
|
maintenance = { status = "experimental" }
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ use cranelift_codegen::ir::{
|
|||||||
AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, Function, InstBuilder, Signature,
|
AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, Function, InstBuilder, Signature,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::isa;
|
use cranelift_codegen::isa;
|
||||||
use cranelift_codegen::settings;
|
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::EntityRef;
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
self, translate_module, FuncIndex, Global, GlobalIndex, GlobalVariable, Memory, MemoryIndex,
|
self, translate_module, FuncIndex, Global, GlobalIndex, GlobalVariable, Memory, MemoryIndex,
|
||||||
SignatureIndex, Table, TableIndex, WasmResult,
|
SignatureIndex, Table, TableIndex, WasmResult,
|
||||||
};
|
};
|
||||||
use module::{DataInitializer, Export, LazyContents, Module, TableElements};
|
use module::{DataInitializer, Export, LazyContents, Module, TableElements};
|
||||||
use target_lexicon::Triple;
|
use std::mem;
|
||||||
|
use vmcontext;
|
||||||
|
|
||||||
/// Compute a `ir::ExternalName` for a given wasm function index.
|
/// Compute a `ir::ExternalName` for a given wasm function index.
|
||||||
pub fn get_func_name(func_index: FuncIndex) -> ir::ExternalName {
|
pub fn get_func_name(func_index: FuncIndex) -> ir::ExternalName {
|
||||||
@@ -32,6 +32,9 @@ pub struct ModuleEnvironment<'data, 'module> {
|
|||||||
|
|
||||||
/// References to information to be decoded later.
|
/// References to information to be decoded later.
|
||||||
pub lazy: LazyContents<'data>,
|
pub lazy: LazyContents<'data>,
|
||||||
|
|
||||||
|
/// The ISA's target front-end configuration.
|
||||||
|
frontend_config: isa::TargetFrontendConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'data, 'module> ModuleEnvironment<'data, 'module> {
|
impl<'data, 'module> ModuleEnvironment<'data, 'module> {
|
||||||
@@ -41,6 +44,7 @@ impl<'data, 'module> ModuleEnvironment<'data, 'module> {
|
|||||||
isa,
|
isa,
|
||||||
module,
|
module,
|
||||||
lazy: LazyContents::new(),
|
lazy: LazyContents::new(),
|
||||||
|
frontend_config: isa.frontend_config(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +80,15 @@ pub struct FuncEnvironment<'module_environment> {
|
|||||||
/// The module-level environment which this function-level environment belongs to.
|
/// The module-level environment which this function-level environment belongs to.
|
||||||
pub module: &'module_environment Module,
|
pub module: &'module_environment Module,
|
||||||
|
|
||||||
|
/// The Cranelift global holding the vmctx address.
|
||||||
|
pub vmctx: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
/// The Cranelift global holding the base address of the memories vector.
|
/// The Cranelift global holding the base address of the memories vector.
|
||||||
pub memories_base: Option<ir::GlobalValue>,
|
pub memories_base: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
|
/// The Cranelift global holding the base address of the tables vector.
|
||||||
|
pub tables_base: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
/// The Cranelift global holding the base address of the globals vector.
|
/// The Cranelift global holding the base address of the globals vector.
|
||||||
pub globals_base: Option<ir::GlobalValue>,
|
pub globals_base: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
@@ -97,7 +107,9 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
Self {
|
Self {
|
||||||
isa,
|
isa,
|
||||||
module,
|
module,
|
||||||
|
vmctx: None,
|
||||||
memories_base: None,
|
memories_base: None,
|
||||||
|
tables_base: None,
|
||||||
globals_base: None,
|
globals_base: None,
|
||||||
current_memory_extfunc: None,
|
current_memory_extfunc: None,
|
||||||
grow_memory_extfunc: None,
|
grow_memory_extfunc: None,
|
||||||
@@ -115,6 +127,14 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
fn pointer_bytes(&self) -> usize {
|
fn pointer_bytes(&self) -> usize {
|
||||||
usize::from(self.isa.pointer_bytes())
|
usize::from(self.isa.pointer_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vmctx(&mut self, func: &mut Function) -> ir::GlobalValue {
|
||||||
|
self.vmctx.unwrap_or_else(|| {
|
||||||
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
|
self.vmctx = Some(vmctx);
|
||||||
|
vmctx
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait is useful for `translate_module` because it tells how to translate
|
/// This trait is useful for `translate_module` because it tells how to translate
|
||||||
@@ -126,8 +146,8 @@ impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
|
|||||||
get_func_name(func_index)
|
get_func_name(func_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> &settings::Flags {
|
fn target_config(&self) -> &isa::TargetFrontendConfig {
|
||||||
self.isa.flags()
|
&self.frontend_config
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||||
@@ -253,30 +273,29 @@ impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> {
|
impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> {
|
||||||
fn flags(&self) -> &settings::Flags {
|
fn target_config(&self) -> isa::TargetFrontendConfig {
|
||||||
&self.isa.flags()
|
self.isa.frontend_config()
|
||||||
}
|
|
||||||
|
|
||||||
fn triple(&self) -> &Triple {
|
|
||||||
self.isa.triple()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
||||||
let pointer_bytes = self.pointer_bytes();
|
let vmctx = self.vmctx(func);
|
||||||
let globals_base = self.globals_base.unwrap_or_else(|| {
|
let globals_base = self.globals_base.unwrap_or_else(|| {
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::VMContext {
|
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
offset: Offset32::new(0),
|
base: vmctx,
|
||||||
|
offset: Offset32::new(offset_of!(vmcontext::VMContext, globals) as i32),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: true,
|
||||||
});
|
});
|
||||||
self.globals_base = Some(new_base);
|
self.globals_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
});
|
});
|
||||||
let offset = index * pointer_bytes;
|
// For now, give each global gets a pointer-sized region of
|
||||||
let offset32 = offset as i32;
|
// storage, regardless of its type.
|
||||||
debug_assert_eq!(offset32 as usize, offset);
|
let offset = index.index() * mem::size_of::<*mut u8>();
|
||||||
let gv = func.create_global_value(ir::GlobalValueData::Deref {
|
let gv = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: globals_base,
|
base: globals_base,
|
||||||
offset: Offset32::new(offset32),
|
offset: Imm64::new(offset as i64),
|
||||||
memory_type: self.pointer_type(),
|
global_type: self.pointer_type(),
|
||||||
});
|
});
|
||||||
GlobalVariable::Memory {
|
GlobalVariable::Memory {
|
||||||
gv,
|
gv,
|
||||||
@@ -285,55 +304,91 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap {
|
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap {
|
||||||
let pointer_bytes = self.pointer_bytes();
|
let vmctx = self.vmctx(func);
|
||||||
let memories_base = self.memories_base.unwrap_or_else(|| {
|
let memories_base = self.memories_base.unwrap_or_else(|| {
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::VMContext {
|
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
offset: Offset32::new(pointer_bytes as i32),
|
base: vmctx,
|
||||||
|
offset: Offset32::new(offset_of!(vmcontext::VMContext, memories) as i32),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: true,
|
||||||
});
|
});
|
||||||
self.memories_base = Some(new_base);
|
self.memories_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
});
|
});
|
||||||
let offset = index * pointer_bytes;
|
let offset = index.index() * mem::size_of::<vmcontext::VMMemory>();
|
||||||
let offset32 = offset as i32;
|
let offset32 = offset as i32;
|
||||||
debug_assert_eq!(offset32 as usize, offset);
|
debug_assert_eq!(offset32 as usize, offset);
|
||||||
let heap_base_addr = func.create_global_value(ir::GlobalValueData::Deref {
|
// If we have a declared maximum, we can make this a "static" heap, which is
|
||||||
|
// allocated up front and never moved.
|
||||||
|
let (guard_size, heap_style, readonly_base) =
|
||||||
|
if self.module.memories[index].maximum.is_some() {
|
||||||
|
(
|
||||||
|
0x8000_0000.into(),
|
||||||
|
ir::HeapStyle::Static {
|
||||||
|
bound: 0x1_0000_0000.into(),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let heap_bound = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: memories_base,
|
base: memories_base,
|
||||||
offset: Offset32::new(offset32),
|
offset: Offset32::new(
|
||||||
memory_type: self.pointer_type(),
|
offset32 + offset_of!(vmcontext::VMMemory, current_length) as i32,
|
||||||
|
),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: false,
|
||||||
});
|
});
|
||||||
let heap_base = func.create_global_value(ir::GlobalValueData::Deref {
|
(
|
||||||
base: heap_base_addr,
|
0.into(),
|
||||||
offset: Offset32::new(0),
|
ir::HeapStyle::Dynamic {
|
||||||
memory_type: self.pointer_type(),
|
bound_gv: heap_bound,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let heap_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: memories_base,
|
||||||
|
offset: Offset32::new(offset32 + offset_of!(vmcontext::VMMemory, base) as i32),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: readonly_base,
|
||||||
});
|
});
|
||||||
func.create_heap(ir::HeapData {
|
func.create_heap(ir::HeapData {
|
||||||
base: heap_base,
|
base: heap_base,
|
||||||
min_size: 0.into(),
|
min_size: 0.into(),
|
||||||
guard_size: 0x8000_0000.into(),
|
guard_size,
|
||||||
style: ir::HeapStyle::Static {
|
style: heap_style,
|
||||||
bound: 0x1_0000_0000.into(),
|
|
||||||
},
|
|
||||||
index_type: I32,
|
index_type: I32,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_table(&mut self, func: &mut ir::Function, _index: TableIndex) -> ir::Table {
|
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> ir::Table {
|
||||||
let pointer_bytes = self.pointer_bytes();
|
let vmctx = self.vmctx(func);
|
||||||
let base_gv_addr = func.create_global_value(ir::GlobalValueData::VMContext {
|
let tables_base = self.tables_base.unwrap_or_else(|| {
|
||||||
offset: Offset32::new(pointer_bytes as i32 * 2),
|
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: vmctx,
|
||||||
|
offset: Offset32::new(offset_of!(vmcontext::VMContext, tables) as i32),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: true,
|
||||||
});
|
});
|
||||||
let base_gv = func.create_global_value(ir::GlobalValueData::Deref {
|
self.tables_base = Some(new_base);
|
||||||
base: base_gv_addr,
|
new_base
|
||||||
offset: 0.into(),
|
|
||||||
memory_type: self.pointer_type(),
|
|
||||||
});
|
});
|
||||||
let bound_gv_addr = func.create_global_value(ir::GlobalValueData::VMContext {
|
let offset = index.index() * mem::size_of::<vmcontext::VMTable>();
|
||||||
offset: Offset32::new(pointer_bytes as i32 * 3),
|
let offset32 = offset as i32;
|
||||||
|
debug_assert_eq!(offset32 as usize, offset);
|
||||||
|
let base_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: tables_base,
|
||||||
|
offset: Offset32::new(offset32 + offset_of!(vmcontext::VMTable, base) as i32),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: false,
|
||||||
});
|
});
|
||||||
let bound_gv = func.create_global_value(ir::GlobalValueData::Deref {
|
let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: bound_gv_addr,
|
base: tables_base,
|
||||||
offset: 0.into(),
|
offset: Offset32::new(
|
||||||
memory_type: I32,
|
offset32 + offset_of!(vmcontext::VMTable, current_num_elements) as i32,
|
||||||
|
),
|
||||||
|
global_type: I32,
|
||||||
|
readonly: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
func.create_table(ir::TableData {
|
func.create_table(ir::TableData {
|
||||||
@@ -375,7 +430,11 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
) -> WasmResult<ir::Inst> {
|
) -> WasmResult<ir::Inst> {
|
||||||
// TODO: Cranelift's call_indirect doesn't implement signature checking,
|
// TODO: Cranelift's call_indirect doesn't implement signature checking,
|
||||||
// so we need to implement it ourselves.
|
// so we need to implement it ourselves.
|
||||||
debug_assert_eq!(table_index, 0, "non-default tables not supported yet");
|
debug_assert_eq!(
|
||||||
|
table_index.index(),
|
||||||
|
0,
|
||||||
|
"non-default tables not supported yet"
|
||||||
|
);
|
||||||
|
|
||||||
let table_entry_addr = pos.ins().table_addr(I64, table, callee, 0);
|
let table_entry_addr = pos.ins().table_addr(I64, table, callee, 0);
|
||||||
|
|
||||||
@@ -411,7 +470,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
let grow_mem_func = self.grow_memory_extfunc.unwrap_or_else(|| {
|
let grow_mem_func = self.grow_memory_extfunc.unwrap_or_else(|| {
|
||||||
let sig_ref = pos.func.import_signature(Signature {
|
let sig_ref = pos.func.import_signature(Signature {
|
||||||
call_conv: self.isa.flags().call_conv(),
|
call_conv: self.isa.frontend_config().default_call_conv,
|
||||||
params: vec![
|
params: vec![
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
@@ -430,7 +489,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
self.grow_memory_extfunc = Some(grow_mem_func);
|
self.grow_memory_extfunc = Some(grow_mem_func);
|
||||||
let memory_index = pos.ins().iconst(I32, index as i64);
|
let memory_index = pos.ins().iconst(I32, index.index() as i64);
|
||||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||||
let call_inst = pos.ins().call(grow_mem_func, &[val, memory_index, vmctx]);
|
let call_inst = pos.ins().call(grow_mem_func, &[val, memory_index, vmctx]);
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
@@ -444,7 +503,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
let cur_mem_func = self.current_memory_extfunc.unwrap_or_else(|| {
|
let cur_mem_func = self.current_memory_extfunc.unwrap_or_else(|| {
|
||||||
let sig_ref = pos.func.import_signature(Signature {
|
let sig_ref = pos.func.import_signature(Signature {
|
||||||
call_conv: self.isa.flags().call_conv(),
|
call_conv: self.isa.frontend_config().default_call_conv,
|
||||||
params: vec![
|
params: vec![
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
||||||
@@ -462,7 +521,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
self.current_memory_extfunc = Some(cur_mem_func);
|
self.current_memory_extfunc = Some(cur_mem_func);
|
||||||
let memory_index = pos.ins().iconst(I32, index as i64);
|
let memory_index = pos.ins().iconst(I32, index.index() as i64);
|
||||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||||
let call_inst = pos.ins().call(cur_mem_func, &[memory_index, vmctx]);
|
let call_inst = pos.ins().call(cur_mem_func, &[memory_index, vmctx]);
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
|
|||||||
@@ -36,10 +36,13 @@ extern crate cranelift_codegen;
|
|||||||
extern crate cranelift_entity;
|
extern crate cranelift_entity;
|
||||||
extern crate cranelift_wasm;
|
extern crate cranelift_wasm;
|
||||||
extern crate target_lexicon;
|
extern crate target_lexicon;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate memoffset;
|
||||||
|
|
||||||
mod compilation;
|
mod compilation;
|
||||||
mod environ;
|
mod environ;
|
||||||
mod module;
|
mod module;
|
||||||
|
mod vmcontext;
|
||||||
|
|
||||||
pub use compilation::{compile_module, Compilation, Relocation, RelocationTarget, Relocations};
|
pub use compilation::{compile_module, Compilation, Relocation, RelocationTarget, Relocations};
|
||||||
pub use environ::{ModuleEnvironment, ModuleTranslation};
|
pub use environ::{ModuleEnvironment, ModuleTranslation};
|
||||||
|
|||||||
33
lib/environ/src/vmcontext.rs
Normal file
33
lib/environ/src/vmcontext.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/// The main fields a JIT needs to access to utilize a WebAssembly linear,
|
||||||
|
/// memory, namely the start address and the size in bytes.
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct VMMemory {
|
||||||
|
pub base: *mut u8,
|
||||||
|
pub current_length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main fields a JIT needs to access to utilize a WebAssembly table,
|
||||||
|
/// namely the start address and the number of elements.
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct VMTable {
|
||||||
|
pub base: *mut u8,
|
||||||
|
pub current_num_elements: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The VM "context", which is pointed to by the `vmctx` arg in Cranelift.
|
||||||
|
/// This has pointers to the globals, memories, tables, and other runtime
|
||||||
|
/// state associated with the current instance.
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct VMContext {
|
||||||
|
/// A pointer to an array of globals.
|
||||||
|
pub globals: *mut u8,
|
||||||
|
/// A pointer to an array of `VMMemory` instances, indexed by
|
||||||
|
/// WebAssembly memory index.
|
||||||
|
pub memories: *mut VMMemory,
|
||||||
|
/// A pointer to an array of `VMTable` instances, indexed by
|
||||||
|
/// WebAssembly table index.
|
||||||
|
pub tables: *mut VMTable,
|
||||||
|
/// A pointer to extra runtime state that isn't directly accessed
|
||||||
|
/// from JIT code.
|
||||||
|
pub instance: *mut u8,
|
||||||
|
}
|
||||||
@@ -9,9 +9,9 @@ repository = "https://github.com/CraneStation/wasmtime"
|
|||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-codegen = "0.20.0"
|
cranelift-codegen = "0.22.0"
|
||||||
cranelift-entity = "0.20.1"
|
cranelift-entity = "0.22.0"
|
||||||
cranelift-wasm = "0.20.1"
|
cranelift-wasm = "0.22.0"
|
||||||
region = "0.3.0"
|
region = "0.3.0"
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ" }
|
||||||
memmap = "0.6.2"
|
memmap = "0.7.0"
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ fn relocate<F>(
|
|||||||
|
|
||||||
extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: *mut *mut u8) -> u32 {
|
extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: *mut *mut u8) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// FIXME: update the VMMemory's size
|
||||||
let instance = (*vmctx.offset(4)) as *mut Instance;
|
let instance = (*vmctx.offset(4)) as *mut Instance;
|
||||||
(*instance)
|
(*instance)
|
||||||
.memory_mut(memory_index as MemoryIndex)
|
.memory_mut(memory_index as MemoryIndex)
|
||||||
@@ -94,6 +95,7 @@ extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: *mut *mut u8) ->
|
|||||||
|
|
||||||
extern "C" fn current_memory(memory_index: u32, vmctx: *mut *mut u8) -> u32 {
|
extern "C" fn current_memory(memory_index: u32, vmctx: *mut *mut u8) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// FIXME: read the VMMemory's size instead
|
||||||
let instance = (*vmctx.offset(4)) as *mut Instance;
|
let instance = (*vmctx.offset(4)) as *mut Instance;
|
||||||
(*instance)
|
(*instance)
|
||||||
.memory_mut(memory_index as MemoryIndex)
|
.memory_mut(memory_index as MemoryIndex)
|
||||||
@@ -115,9 +117,12 @@ fn make_vmctx(instance: &mut Instance, mem_base_addrs: &mut [*mut u8]) -> Vec<*m
|
|||||||
.map(|table| (table.as_mut_ptr() as *mut u8, table.len()))
|
.map(|table| (table.as_mut_ptr() as *mut u8, table.len()))
|
||||||
.unwrap_or((ptr::null_mut(), 0));
|
.unwrap_or((ptr::null_mut(), 0));
|
||||||
|
|
||||||
|
// FIXME: Actually use environ's VMContext struct
|
||||||
let mut vmctx = Vec::new();
|
let mut vmctx = Vec::new();
|
||||||
vmctx.push(instance.globals.as_mut_ptr());
|
vmctx.push(instance.globals.as_mut_ptr());
|
||||||
|
// FIXME: These need to be VMMemory now
|
||||||
vmctx.push(mem_base_addrs.as_mut_ptr() as *mut u8);
|
vmctx.push(mem_base_addrs.as_mut_ptr() as *mut u8);
|
||||||
|
// FIXME: These need to be VMTable now
|
||||||
vmctx.push(default_table_ptr);
|
vmctx.push(default_table_ptr);
|
||||||
vmctx.push(default_table_len as *mut u8);
|
vmctx.push(default_table_len as *mut u8);
|
||||||
vmctx.push(instance as *mut Instance as *mut u8);
|
vmctx.push(instance as *mut Instance as *mut u8);
|
||||||
@@ -134,7 +139,7 @@ pub fn execute(
|
|||||||
let start_index = module
|
let start_index = module
|
||||||
.start_func
|
.start_func
|
||||||
.ok_or_else(|| String::from("No start function defined, aborting execution"))?;
|
.ok_or_else(|| String::from("No start function defined, aborting execution"))?;
|
||||||
// TODO: Put all the function bodies into a page-aligned memory region, and
|
// FIXME: Put all the function bodies into a page-aligned memory region, and
|
||||||
// then make them ReadExecute rather than ReadWriteExecute.
|
// then make them ReadExecute rather than ReadWriteExecute.
|
||||||
for code_buf in compilation.functions.values() {
|
for code_buf in compilation.functions.values() {
|
||||||
match unsafe {
|
match unsafe {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ categories = ["wasm"]
|
|||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-codegen = "0.20.0"
|
cranelift-codegen = "0.22.0"
|
||||||
cranelift-entity = "0.20.1"
|
cranelift-entity = "0.22.0"
|
||||||
wasmtime-environ = { path = "../environ" }
|
wasmtime-environ = { path = "../environ" }
|
||||||
faerie = "0.5.0"
|
faerie = "0.5.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user