mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-20 20:26:32 +00:00
Get most spectests passing
This commit is contained in:
@ -4,7 +4,6 @@ use cranelift_codegen::{
|
|||||||
ir::{self, InstBuilder},
|
ir::{self, InstBuilder},
|
||||||
isa,
|
isa,
|
||||||
};
|
};
|
||||||
use cranelift_entity::EntityRef;
|
|
||||||
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
|
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
memory::LinearMemory,
|
memory::LinearMemory,
|
||||||
@ -105,7 +104,6 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let offset = imported_global_index.index() * vm::ImportedGlobal::size() as usize;
|
let offset = imported_global_index.index() * vm::ImportedGlobal::size() as usize;
|
||||||
|
|
||||||
let imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
let imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: imported_globals_base_addr,
|
base: imported_globals_base_addr,
|
||||||
offset: (offset as i64).into(),
|
offset: (offset as i64).into(),
|
||||||
@ -282,7 +280,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
LocalOrImport::Import(imported_table_index) => {
|
LocalOrImport::Import(imported_table_index) => {
|
||||||
let imported_tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
let imported_tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: (vm::Ctx::offset_imported_memories() as i32).into(),
|
offset: (vm::Ctx::offset_imported_tables() as i32).into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
});
|
});
|
||||||
@ -525,9 +523,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
fn translate_memory_grow(
|
fn translate_memory_grow(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut pos: FuncCursor,
|
mut pos: FuncCursor,
|
||||||
index: cranelift_wasm::MemoryIndex,
|
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||||
_heap: ir::Heap,
|
_heap: ir::Heap,
|
||||||
val: ir::Value,
|
by_value: ir::Value,
|
||||||
) -> cranelift_wasm::WasmResult<ir::Value> {
|
) -> cranelift_wasm::WasmResult<ir::Value> {
|
||||||
let signature = pos.func.import_signature(ir::Signature {
|
let signature = pos.func.import_signature(ir::Signature {
|
||||||
call_conv: self.target_config().default_call_conv,
|
call_conv: self.target_config().default_call_conv,
|
||||||
@ -539,26 +537,42 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
returns: vec![ir::AbiParam::new(ir::types::I32)],
|
returns: vec![ir::AbiParam::new(ir::types::I32)],
|
||||||
});
|
});
|
||||||
|
|
||||||
let grow_mem_func = pos.func.import_function(ir::ExtFuncData {
|
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
// `ir::ExternalName` for static_grow_memory`
|
|
||||||
name: ir::ExternalName::user(1, 0),
|
let (name, mem_index) = match mem_index.local_or_import(self.env.module) {
|
||||||
|
LocalOrImport::Local(local_mem_index) => {
|
||||||
|
(
|
||||||
|
// local_static_memory_grow
|
||||||
|
ir::ExternalName::user(1, 0),
|
||||||
|
local_mem_index.index(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LocalOrImport::Import(imported_mem_index) => {
|
||||||
|
(
|
||||||
|
// imported_static_memory_grow
|
||||||
|
ir::ExternalName::user(1, 2),
|
||||||
|
imported_mem_index.index(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
|
||||||
|
name,
|
||||||
signature,
|
signature,
|
||||||
colocated: false,
|
colocated: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a memory index value.
|
let const_mem_index = pos.ins().iconst(ir::types::I32, mem_index as i64);
|
||||||
let memory_index = pos.ins().iconst(ir::types::I32, index.index() as i64);
|
|
||||||
|
|
||||||
// Create a VMContext value.
|
|
||||||
let vmctx = pos
|
let vmctx = pos
|
||||||
.func
|
.func
|
||||||
.special_param(ir::ArgumentPurpose::VMContext)
|
.special_param(ir::ArgumentPurpose::VMContext)
|
||||||
.expect("missing vmctx parameter");
|
.expect("missing vmctx parameter");
|
||||||
|
|
||||||
// Insert call instructions for `grow_memory`.
|
let call_inst = pos
|
||||||
let call_inst = pos.ins().call(grow_mem_func, &[memory_index, val, vmctx]);
|
.ins()
|
||||||
|
.call(mem_grow_func, &[const_mem_index, by_value, vmctx]);
|
||||||
|
|
||||||
// Return value.
|
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,9 +584,40 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
fn translate_memory_size(
|
fn translate_memory_size(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut pos: FuncCursor,
|
mut pos: FuncCursor,
|
||||||
index: cranelift_wasm::MemoryIndex,
|
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||||
_heap: ir::Heap,
|
_heap: ir::Heap,
|
||||||
) -> cranelift_wasm::WasmResult<ir::Value> {
|
) -> cranelift_wasm::WasmResult<ir::Value> {
|
||||||
|
// let signature = pos.func.import_signature(ir::Signature {
|
||||||
|
// call_conv: self.target_config().default_call_conv,
|
||||||
|
// params: vec![
|
||||||
|
// ir::AbiParam::new(ir::types::I32),
|
||||||
|
// ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
||||||
|
// ],
|
||||||
|
// returns: vec![ir::AbiParam::new(ir::types::I32)],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let size_mem_func = pos.func.import_function(ir::ExtFuncData {
|
||||||
|
// // `ir::ExternalName` for static_grow_memory`
|
||||||
|
// name: ir::ExternalName::user(1, 1),
|
||||||
|
// signature,
|
||||||
|
// colocated: false,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // Create a memory index value.
|
||||||
|
// let memory_index = pos.ins().iconst(ir::types::I32, index.index() as i64);
|
||||||
|
|
||||||
|
// // Create a VMContext value.
|
||||||
|
// let vmctx = pos
|
||||||
|
// .func
|
||||||
|
// .special_param(ir::ArgumentPurpose::VMContext)
|
||||||
|
// .expect("missing vmctx parameter");
|
||||||
|
|
||||||
|
// // Insert call instructions for `grow_memory`.
|
||||||
|
// let call_inst = pos.ins().call(size_mem_func, &[memory_index, vmctx]);
|
||||||
|
|
||||||
|
// // Return value.
|
||||||
|
// Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
|
|
||||||
let signature = pos.func.import_signature(ir::Signature {
|
let signature = pos.func.import_signature(ir::Signature {
|
||||||
call_conv: self.target_config().default_call_conv,
|
call_conv: self.target_config().default_call_conv,
|
||||||
params: vec![
|
params: vec![
|
||||||
@ -582,26 +627,39 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
returns: vec![ir::AbiParam::new(ir::types::I32)],
|
returns: vec![ir::AbiParam::new(ir::types::I32)],
|
||||||
});
|
});
|
||||||
|
|
||||||
let size_mem_func = pos.func.import_function(ir::ExtFuncData {
|
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
// `ir::ExternalName` for static_grow_memory`
|
|
||||||
name: ir::ExternalName::user(1, 1),
|
let (name, mem_index) = match mem_index.local_or_import(self.env.module) {
|
||||||
|
LocalOrImport::Local(local_mem_index) => {
|
||||||
|
(
|
||||||
|
// local_static_memory_size
|
||||||
|
ir::ExternalName::user(1, 1),
|
||||||
|
local_mem_index.index(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LocalOrImport::Import(imported_mem_index) => {
|
||||||
|
(
|
||||||
|
// imported_static_memory_size
|
||||||
|
ir::ExternalName::user(1, 3),
|
||||||
|
imported_mem_index.index(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mem_grow_func = pos.func.import_function(ir::ExtFuncData {
|
||||||
|
name,
|
||||||
signature,
|
signature,
|
||||||
colocated: false,
|
colocated: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a memory index value.
|
let const_mem_index = pos.ins().iconst(ir::types::I32, mem_index as i64);
|
||||||
let memory_index = pos.ins().iconst(ir::types::I32, index.index() as i64);
|
|
||||||
|
|
||||||
// Create a VMContext value.
|
|
||||||
let vmctx = pos
|
let vmctx = pos
|
||||||
.func
|
.func
|
||||||
.special_param(ir::ArgumentPurpose::VMContext)
|
.special_param(ir::ArgumentPurpose::VMContext)
|
||||||
.expect("missing vmctx parameter");
|
.expect("missing vmctx parameter");
|
||||||
|
|
||||||
// Insert call instructions for `grow_memory`.
|
let call_inst = pos.ins().call(mem_grow_func, &[const_mem_index, vmctx]);
|
||||||
let call_inst = pos.ins().call(size_mem_func, &[memory_index, vmctx]);
|
|
||||||
|
|
||||||
// Return value.
|
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,21 @@ pub struct Relocation {
|
|||||||
pub target: RelocationType,
|
pub target: RelocationType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum VmCall {
|
||||||
|
LocalStaticMemoryGrow,
|
||||||
|
LocalStaticMemorySize,
|
||||||
|
ImportedStaticMemoryGrow,
|
||||||
|
ImportedStaticMemorySize,
|
||||||
|
}
|
||||||
|
|
||||||
/// Specify the type of relocation
|
/// Specify the type of relocation
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum RelocationType {
|
pub enum RelocationType {
|
||||||
Normal(LocalFuncIndex),
|
Normal(LocalFuncIndex),
|
||||||
Intrinsic(String),
|
Intrinsic(String),
|
||||||
LibCall(LibCall),
|
LibCall(LibCall),
|
||||||
StaticGrowMemory,
|
VmCall(VmCall),
|
||||||
StaticCurrentMemory,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of a relocation sink that just saves all the information for later
|
/// Implementation of a relocation sink that just saves all the information for later
|
||||||
@ -69,11 +76,13 @@ impl binemit::RelocSink for RelocSink {
|
|||||||
namespace: 1,
|
namespace: 1,
|
||||||
index,
|
index,
|
||||||
} => {
|
} => {
|
||||||
let target = match index {
|
let target = RelocationType::VmCall(match index {
|
||||||
0 => RelocationType::StaticGrowMemory,
|
0 => VmCall::LocalStaticMemoryGrow,
|
||||||
1 => RelocationType::StaticCurrentMemory,
|
1 => VmCall::LocalStaticMemorySize,
|
||||||
|
2 => VmCall::ImportedStaticMemoryGrow,
|
||||||
|
3 => VmCall::ImportedStaticMemorySize,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
});
|
||||||
self.func_relocs.push(Relocation {
|
self.func_relocs.push(Relocation {
|
||||||
reloc,
|
reloc,
|
||||||
offset,
|
offset,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::libcalls;
|
use crate::libcalls;
|
||||||
use crate::relocation::{Reloc, RelocSink, Relocation, RelocationType, TrapSink};
|
use crate::relocation::{Reloc, RelocSink, Relocation, RelocationType, TrapSink, VmCall};
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use cranelift_codegen::{ir, isa, Context};
|
use cranelift_codegen::{ir, isa, Context};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -87,8 +87,6 @@ impl FuncResolverBuilder {
|
|||||||
// called in this way.
|
// called in this way.
|
||||||
self.resolver.lookup(local_func_index).unwrap().as_ptr() as isize
|
self.resolver.lookup(local_func_index).unwrap().as_ptr() as isize
|
||||||
}
|
}
|
||||||
RelocationType::StaticCurrentMemory => vmcalls::memory_size as isize,
|
|
||||||
RelocationType::StaticGrowMemory => vmcalls::memory_grow_static as isize,
|
|
||||||
RelocationType::LibCall(libcall) => match libcall {
|
RelocationType::LibCall(libcall) => match libcall {
|
||||||
ir::LibCall::CeilF32 => libcalls::ceilf32 as isize,
|
ir::LibCall::CeilF32 => libcalls::ceilf32 as isize,
|
||||||
ir::LibCall::FloorF32 => libcalls::floorf32 as isize,
|
ir::LibCall::FloorF32 => libcalls::floorf32 as isize,
|
||||||
@ -106,6 +104,16 @@ impl FuncResolverBuilder {
|
|||||||
RelocationType::Intrinsic(ref name) => {
|
RelocationType::Intrinsic(ref name) => {
|
||||||
panic!("unexpected intrinsic {}", name);
|
panic!("unexpected intrinsic {}", name);
|
||||||
}
|
}
|
||||||
|
RelocationType::VmCall(vmcall) => match vmcall {
|
||||||
|
VmCall::LocalStaticMemoryGrow => vmcalls::local_static_memory_grow as _,
|
||||||
|
VmCall::LocalStaticMemorySize => vmcalls::local_static_memory_size as _,
|
||||||
|
VmCall::ImportedStaticMemoryGrow => {
|
||||||
|
vmcalls::imported_static_memory_grow as _
|
||||||
|
}
|
||||||
|
VmCall::ImportedStaticMemorySize => {
|
||||||
|
vmcalls::imported_static_memory_size as _
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// We need the address of the current function
|
// We need the address of the current function
|
||||||
|
@ -4,7 +4,7 @@ use wasmer_runtime::{import::Imports, Instance};
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut instance = create_module_1();
|
let mut instance = create_module_1();
|
||||||
let result = instance.call("type-i64", &[]);
|
let result = instance.call("get-0-ref", &[]);
|
||||||
println!("result: {:?}", result);
|
println!("result: {:?}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,21 +18,44 @@ fn main() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
fn create_module_1() -> Instance {
|
fn create_module_1() -> Instance {
|
||||||
let module_str = "(module
|
let module_str = r#"(module
|
||||||
(type (;0;) (func (result i64)))
|
(type (;0;) (func (result i32)))
|
||||||
(func (;0;) (type 0) (result i64)
|
(import "spectest" "global_i32" (global (;0;) i32))
|
||||||
i64.const 356)
|
(func (;0;) (type 0) (result i32)
|
||||||
(func (;1;) (type 0) (result i64)
|
get_global 0)
|
||||||
i32.const 0
|
(func (;1;) (type 0) (result i32)
|
||||||
call_indirect (type 0))
|
get_global 1)
|
||||||
(table (;0;) 2 anyfunc)
|
(global (;1;) i32 (get_global 0))
|
||||||
(export \"type-i64\" (func 1))
|
(export "get-0" (func 0))
|
||||||
(elem (;0;) (i32.const 0) 0 1))
|
(export "get-0-ref" (func 1)))
|
||||||
";
|
"#;
|
||||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||||
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new())
|
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new())
|
||||||
.expect("WASM can't be compiled");
|
.expect("WASM can't be compiled");
|
||||||
module
|
module
|
||||||
.instantiate(&mut Imports::new())
|
.instantiate(&mut generate_imports())
|
||||||
.expect("WASM can't be instantiated")
|
.expect("WASM can't be instantiated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IMPORT_MODULE: &str = r#"
|
||||||
|
(module
|
||||||
|
(type $t0 (func (param i32)))
|
||||||
|
(type $t1 (func))
|
||||||
|
(func $print_i32 (export "print_i32") (type $t0) (param $lhs i32))
|
||||||
|
(func $print (export "print") (type $t1))
|
||||||
|
(table $table (export "table") 10 20 anyfunc)
|
||||||
|
(memory $memory (export "memory") 1 2)
|
||||||
|
(global $global_i32 (export "global_i32") i32 (i32.const 666)))
|
||||||
|
"#;
|
||||||
|
|
||||||
|
pub fn generate_imports() -> Imports {
|
||||||
|
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
||||||
|
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new())
|
||||||
|
.expect("WASM can't be compiled");
|
||||||
|
let instance = module
|
||||||
|
.instantiate(&mut Imports::new())
|
||||||
|
.expect("WASM can't be instantiated");
|
||||||
|
let mut imports = Imports::new();
|
||||||
|
imports.register("spectest", instance);
|
||||||
|
imports
|
||||||
|
}
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
use std::slice;
|
use std::{mem, slice};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LocalBacking {
|
pub struct LocalBacking {
|
||||||
@ -106,20 +106,27 @@ impl LocalBacking {
|
|||||||
assert!((memory_desc.min * LinearMemory::PAGE_SIZE) as usize >= data_top);
|
assert!((memory_desc.min * LinearMemory::PAGE_SIZE) as usize >= data_top);
|
||||||
let mem: &mut LinearMemory = &mut memories[local_memory_index];
|
let mem: &mut LinearMemory = &mut memories[local_memory_index];
|
||||||
|
|
||||||
let to_init = &mut mem[init_base..init_base + init.data.len()];
|
let mem_init_view = &mut mem[init_base..init_base + init.data.len()];
|
||||||
to_init.copy_from_slice(&init.data);
|
mem_init_view.copy_from_slice(&init.data);
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_memory_index) => {
|
LocalOrImport::Import(imported_memory_index) => {
|
||||||
let _ = imported_memory_index;
|
let vm_imported_memory = imports.imported_memory(imported_memory_index);
|
||||||
let _ = imports;
|
unsafe {
|
||||||
unimplemented!()
|
let local_memory = &(*vm_imported_memory.memory);
|
||||||
|
let memory_slice =
|
||||||
|
slice::from_raw_parts_mut(local_memory.base, local_memory.size);
|
||||||
|
|
||||||
|
let mem_init_view =
|
||||||
|
&mut memory_slice[init_base..init_base + init.data.len()];
|
||||||
|
mem_init_view.copy_from_slice(&init.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memories
|
memories
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|(_, mem)| mem.into_vm_memory())
|
.map(|(index, mem)| mem.into_vm_memory(index))
|
||||||
.collect::<Map<_, _>>()
|
.collect::<Map<_, _>>()
|
||||||
.into_boxed_map()
|
.into_boxed_map()
|
||||||
}
|
}
|
||||||
@ -154,24 +161,17 @@ impl LocalBacking {
|
|||||||
}
|
}
|
||||||
} as usize;
|
} as usize;
|
||||||
|
|
||||||
assert!(
|
|
||||||
init_base + init.elements.len()
|
|
||||||
<= match init.table_index.local_or_import(module) {
|
|
||||||
LocalOrImport::Local(local_table_index) => {
|
|
||||||
module.tables[local_table_index].min
|
|
||||||
}
|
|
||||||
LocalOrImport::Import(imported_table_index) => {
|
|
||||||
let (_, table_desc) = module.imported_tables[imported_table_index];
|
|
||||||
table_desc.min
|
|
||||||
}
|
|
||||||
} as usize
|
|
||||||
);
|
|
||||||
|
|
||||||
match init.table_index.local_or_import(module) {
|
match init.table_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_table_index) => {
|
LocalOrImport::Local(local_table_index) => {
|
||||||
let table = &mut tables[local_table_index];
|
let table = &mut tables[local_table_index];
|
||||||
match table.elements {
|
match table.elements {
|
||||||
TableElements::Anyfunc(ref mut elements) => {
|
TableElements::Anyfunc(ref mut elements) => {
|
||||||
|
if elements.len() < init_base + init.elements.len() {
|
||||||
|
// Grow the table if it's too small.
|
||||||
|
elements
|
||||||
|
.resize(init_base + init.elements.len(), vm::Anyfunc::null());
|
||||||
|
}
|
||||||
|
|
||||||
for (i, &func_index) in init.elements.iter().enumerate() {
|
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||||
let sig_index = module.func_assoc[func_index];
|
let sig_index = module.func_assoc[func_index];
|
||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
@ -196,20 +196,33 @@ impl LocalBacking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(imported_table_index) => {
|
LocalOrImport::Import(imported_table_index) => {
|
||||||
let imported_table = &imports.tables[imported_table_index];
|
|
||||||
|
|
||||||
let imported_local_table_slice = unsafe {
|
|
||||||
let imported_local_table = (*imported_table).table;
|
|
||||||
|
|
||||||
slice::from_raw_parts_mut(
|
|
||||||
(*imported_local_table).base as *mut vm::Anyfunc,
|
|
||||||
(*imported_local_table).current_elements,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (_, table_description) = module.imported_tables[imported_table_index];
|
let (_, table_description) = module.imported_tables[imported_table_index];
|
||||||
match table_description.ty {
|
match table_description.ty {
|
||||||
ElementType::Anyfunc => {
|
ElementType::Anyfunc => {
|
||||||
|
let imported_table = &imports.tables[imported_table_index];
|
||||||
|
let imported_local_table = (*imported_table).table;
|
||||||
|
|
||||||
|
let mut elements = unsafe {
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
(*imported_local_table).base as *mut vm::Anyfunc,
|
||||||
|
(*imported_local_table).current_elements,
|
||||||
|
(*imported_local_table).capacity,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if elements.len() < init_base + init.elements.len() {
|
||||||
|
// Grow the table if it's too small.
|
||||||
|
elements
|
||||||
|
.resize(init_base + init.elements.len(), vm::Anyfunc::null());
|
||||||
|
// Since the vector may have changed location after reallocating,
|
||||||
|
// we must fix the base, current_elements, and capacity fields.
|
||||||
|
unsafe {
|
||||||
|
(*imported_local_table).base = elements.as_mut_ptr() as *mut u8;
|
||||||
|
(*imported_local_table).current_elements = elements.len();
|
||||||
|
(*imported_local_table).capacity = elements.capacity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i, &func_index) in init.elements.iter().enumerate() {
|
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||||
let sig_index = module.func_assoc[func_index];
|
let sig_index = module.func_assoc[func_index];
|
||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
@ -228,9 +241,13 @@ impl LocalBacking {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
imported_local_table_slice[init_base + i] =
|
elements[init_base + i] = vm::Anyfunc { func_data, sig_id };
|
||||||
vm::Anyfunc { func_data, sig_id };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// println!("imported elements: {:#?}", elements);
|
||||||
|
|
||||||
|
// THIS IS EXTREMELY IMPORTANT.
|
||||||
|
mem::forget(elements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,10 +294,10 @@ impl LocalBacking {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportBacking {
|
pub struct ImportBacking {
|
||||||
pub functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
pub(crate) functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
||||||
pub memories: BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>,
|
pub(crate) memories: BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>,
|
||||||
pub tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
pub(crate) tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
||||||
pub globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
pub(crate) globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportBacking {
|
impl ImportBacking {
|
||||||
@ -296,6 +313,10 @@ impl ImportBacking {
|
|||||||
globals: import_globals(module, imports)?,
|
globals: import_globals(module, imports)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn imported_memory(&self, memory_index: ImportedMemoryIndex) -> vm::ImportedMemory {
|
||||||
|
self.memories[memory_index].clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_functions(
|
fn import_functions(
|
||||||
|
@ -235,7 +235,7 @@ impl InstanceInner {
|
|||||||
LocalOrImport::Local(local_mem_index) => {
|
LocalOrImport::Local(local_mem_index) => {
|
||||||
let vm_mem = &mut self.backing.memories[local_mem_index];
|
let vm_mem = &mut self.backing.memories[local_mem_index];
|
||||||
(
|
(
|
||||||
unsafe { MemoryPointer::new(&mut vm_mem.into_vm_memory()) },
|
unsafe { MemoryPointer::new(&mut vm_mem.into_vm_memory(local_mem_index)) },
|
||||||
Context::Internal,
|
Context::Internal,
|
||||||
*module
|
*module
|
||||||
.memories
|
.memories
|
||||||
|
@ -2,7 +2,7 @@ use std::ops::{Deref, DerefMut};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mmap::{Mmap, Protect},
|
mmap::{Mmap, Protect},
|
||||||
types::Memory,
|
types::{LocalMemoryIndex, Memory},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,10 +107,11 @@ impl LinearMemory {
|
|||||||
self.max.unwrap_or(Self::MAX_PAGES)
|
self.max.unwrap_or(Self::MAX_PAGES)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_vm_memory(&mut self) -> vm::LocalMemory {
|
pub(crate) fn into_vm_memory(&mut self, index: LocalMemoryIndex) -> vm::LocalMemory {
|
||||||
vm::LocalMemory {
|
vm::LocalMemory {
|
||||||
base: self.base(),
|
base: self.base(),
|
||||||
size: self.size(),
|
size: self.size(),
|
||||||
|
index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use crate::types::{ElementType, Table};
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TableElements {
|
pub enum TableElements {
|
||||||
/// This is intended to be a caller-checked Anyfunc.
|
/// This is intended to be a caller-checked Anyfunc.
|
||||||
Anyfunc(Box<[vm::Anyfunc]>),
|
Anyfunc(Vec<vm::Anyfunc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -16,12 +16,20 @@ pub struct TableBacking {
|
|||||||
impl TableBacking {
|
impl TableBacking {
|
||||||
pub fn new(table: &Table) -> Self {
|
pub fn new(table: &Table) -> Self {
|
||||||
match table.ty {
|
match table.ty {
|
||||||
ElementType::Anyfunc => Self {
|
ElementType::Anyfunc => {
|
||||||
elements: TableElements::Anyfunc(
|
let initial_table_backing_len = match table.max {
|
||||||
vec![vm::Anyfunc::null(); table.min as usize].into_boxed_slice(),
|
Some(max) => max,
|
||||||
),
|
None => table.min,
|
||||||
max: table.max,
|
} as usize;
|
||||||
},
|
|
||||||
|
Self {
|
||||||
|
elements: TableElements::Anyfunc(vec![
|
||||||
|
vm::Anyfunc::null();
|
||||||
|
initial_table_backing_len
|
||||||
|
]),
|
||||||
|
max: table.max,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +38,7 @@ impl TableBacking {
|
|||||||
TableElements::Anyfunc(ref mut funcs) => vm::LocalTable {
|
TableElements::Anyfunc(ref mut funcs) => vm::LocalTable {
|
||||||
base: funcs.as_mut_ptr() as *mut u8,
|
base: funcs.as_mut_ptr() as *mut u8,
|
||||||
current_elements: funcs.len(),
|
current_elements: funcs.len(),
|
||||||
|
capacity: funcs.capacity(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::backing::ImportBacking;
|
pub use crate::backing::{ImportBacking, LocalBacking};
|
||||||
pub use crate::backing::LocalBacking;
|
use crate::types::LocalMemoryIndex;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
@ -29,10 +29,11 @@ pub struct Ctx {
|
|||||||
|
|
||||||
/// The local backing of the instance that created this vmctx.
|
/// The local backing of the instance that created this vmctx.
|
||||||
pub local_backing: *mut LocalBacking,
|
pub local_backing: *mut LocalBacking,
|
||||||
|
/// The import backing of the parent instance.
|
||||||
|
pub import_backing: *mut ImportBacking,
|
||||||
|
|
||||||
/// Host data
|
/// Host data
|
||||||
pub data: *mut c_void,
|
pub data: *mut c_void,
|
||||||
|
|
||||||
/// Host data finalizer
|
/// Host data finalizer
|
||||||
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
|
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
|
||||||
}
|
}
|
||||||
@ -61,6 +62,8 @@ impl Ctx {
|
|||||||
imported_funcs: import_backing.functions.as_mut_ptr(),
|
imported_funcs: import_backing.functions.as_mut_ptr(),
|
||||||
|
|
||||||
local_backing,
|
local_backing,
|
||||||
|
import_backing,
|
||||||
|
|
||||||
data: ptr::null_mut(),
|
data: ptr::null_mut(),
|
||||||
data_finalizer: None,
|
data_finalizer: None,
|
||||||
}
|
}
|
||||||
@ -83,6 +86,8 @@ impl Ctx {
|
|||||||
imported_funcs: import_backing.functions.as_mut_ptr(),
|
imported_funcs: import_backing.functions.as_mut_ptr(),
|
||||||
|
|
||||||
local_backing,
|
local_backing,
|
||||||
|
import_backing,
|
||||||
|
|
||||||
data,
|
data,
|
||||||
data_finalizer,
|
data_finalizer,
|
||||||
}
|
}
|
||||||
@ -156,6 +161,8 @@ pub struct LocalTable {
|
|||||||
pub base: *mut u8,
|
pub base: *mut u8,
|
||||||
/// Number of elements in the table (NOT necessarily the size of the table in bytes!).
|
/// Number of elements in the table (NOT necessarily the size of the table in bytes!).
|
||||||
pub current_elements: usize,
|
pub current_elements: usize,
|
||||||
|
/// The number of elements that can fit into the memory allocated for this table.
|
||||||
|
pub capacity: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalTable {
|
impl LocalTable {
|
||||||
@ -203,6 +210,8 @@ pub struct LocalMemory {
|
|||||||
pub base: *mut u8,
|
pub base: *mut u8,
|
||||||
/// Current size of this linear memory in bytes.
|
/// Current size of this linear memory in bytes.
|
||||||
pub size: usize,
|
pub size: usize,
|
||||||
|
/// The local memory index.
|
||||||
|
pub index: LocalMemoryIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalMemory {
|
impl LocalMemory {
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
use crate::{memory::LinearMemory, structures::TypedIndex, types::LocalMemoryIndex, vm};
|
use crate::{
|
||||||
|
memory::LinearMemory,
|
||||||
|
structures::TypedIndex,
|
||||||
|
types::{ImportedMemoryIndex, LocalMemoryIndex, LocalTableIndex},
|
||||||
|
vm,
|
||||||
|
};
|
||||||
|
|
||||||
pub unsafe extern "C" fn memory_grow_static(
|
// +*****************************+
|
||||||
|
// | LOCAL MEMORIES |
|
||||||
|
// +****************************+
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn local_static_memory_grow(
|
||||||
memory_index: LocalMemoryIndex,
|
memory_index: LocalMemoryIndex,
|
||||||
by_pages: u32,
|
by_pages: u32,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: *mut vm::Ctx,
|
||||||
@ -18,11 +27,14 @@ pub unsafe extern "C" fn memory_grow_static(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn memory_size(memory_index: LocalMemoryIndex, ctx: *mut vm::Ctx) -> u32 {
|
pub unsafe extern "C" fn local_static_memory_size(
|
||||||
|
memory_index: LocalMemoryIndex,
|
||||||
|
ctx: *mut vm::Ctx,
|
||||||
|
) -> u32 {
|
||||||
(*(*ctx).local_backing).memory(memory_index).pages()
|
(*(*ctx).local_backing).memory(memory_index).pages()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn memory_grow_dynamic(
|
pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||||
memory_index: LocalMemoryIndex,
|
memory_index: LocalMemoryIndex,
|
||||||
by_pages: u32,
|
by_pages: u32,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: *mut vm::Ctx,
|
||||||
@ -39,3 +51,68 @@ pub unsafe extern "C" fn memory_grow_dynamic(
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +*****************************+
|
||||||
|
// | IMPORTED MEMORIES |
|
||||||
|
// +****************************+
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn imported_static_memory_grow(
|
||||||
|
imported_mem_index: ImportedMemoryIndex,
|
||||||
|
by_pages: u32,
|
||||||
|
caller_ctx: *mut vm::Ctx,
|
||||||
|
) -> i32 {
|
||||||
|
let import_backing = &*(*caller_ctx).import_backing;
|
||||||
|
let vm_imported_mem = import_backing.imported_memory(imported_mem_index);
|
||||||
|
|
||||||
|
// We can assume that the memory here is local to the callee ctx.
|
||||||
|
let local_mem_index = (*vm_imported_mem.memory).index;
|
||||||
|
|
||||||
|
if let Some(old) = (*(*vm_imported_mem.vmctx).local_backing)
|
||||||
|
.memory(local_mem_index)
|
||||||
|
.grow_dynamic(by_pages)
|
||||||
|
{
|
||||||
|
// Store the new size back into the vmctx.
|
||||||
|
(*(*vm_imported_mem.vmctx)
|
||||||
|
.memories
|
||||||
|
.add(local_mem_index.index()))
|
||||||
|
.size = (old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
||||||
|
old
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn imported_static_memory_size(
|
||||||
|
imported_memory_index: ImportedMemoryIndex,
|
||||||
|
caller_ctx: *mut vm::Ctx,
|
||||||
|
) -> u32 {
|
||||||
|
let import_backing = &*(*caller_ctx).import_backing;
|
||||||
|
let vm_imported_mem = import_backing.imported_memory(imported_memory_index);
|
||||||
|
|
||||||
|
// We can assume that the memory here is local to the callee ctx.
|
||||||
|
let local_mem_index = (*vm_imported_mem.memory).index;
|
||||||
|
(*(*vm_imported_mem.vmctx).local_backing)
|
||||||
|
.memory(local_mem_index)
|
||||||
|
.pages()
|
||||||
|
}
|
||||||
|
|
||||||
|
// +*****************************+
|
||||||
|
// | LOCAL TABLES |
|
||||||
|
// +****************************+
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn local_table_grow(
|
||||||
|
table_index: LocalTableIndex,
|
||||||
|
by_elems: u32,
|
||||||
|
ctx: *mut vm::Ctx,
|
||||||
|
) -> i32 {
|
||||||
|
let _ = table_index;
|
||||||
|
let _ = by_elems;
|
||||||
|
let _ = ctx;
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn local_table_size(table_index: LocalTableIndex, ctx: *mut vm::Ctx) -> u32 {
|
||||||
|
let _ = table_index;
|
||||||
|
let _ = ctx;
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user