mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-21 04:31:33 +00:00
Get most spectests passing
This commit is contained in:
@ -4,7 +4,6 @@ use cranelift_codegen::{
|
||||
ir::{self, InstBuilder},
|
||||
isa,
|
||||
};
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
|
||||
use wasmer_runtime::{
|
||||
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 imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: imported_globals_base_addr,
|
||||
offset: (offset as i64).into(),
|
||||
@ -282,7 +280,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
LocalOrImport::Import(imported_table_index) => {
|
||||
let imported_tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
offset: (vm::Ctx::offset_imported_memories() as i32).into(),
|
||||
offset: (vm::Ctx::offset_imported_tables() as i32).into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
});
|
||||
@ -525,9 +523,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
fn translate_memory_grow(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
index: cranelift_wasm::MemoryIndex,
|
||||
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||
_heap: ir::Heap,
|
||||
val: ir::Value,
|
||||
by_value: ir::Value,
|
||||
) -> cranelift_wasm::WasmResult<ir::Value> {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
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)],
|
||||
});
|
||||
|
||||
let grow_mem_func = pos.func.import_function(ir::ExtFuncData {
|
||||
// `ir::ExternalName` for static_grow_memory`
|
||||
name: ir::ExternalName::user(1, 0),
|
||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||
|
||||
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,
|
||||
colocated: false,
|
||||
});
|
||||
|
||||
// Create a memory index value.
|
||||
let memory_index = pos.ins().iconst(ir::types::I32, index.index() as i64);
|
||||
let const_mem_index = pos.ins().iconst(ir::types::I32, mem_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(grow_mem_func, &[memory_index, val, vmctx]);
|
||||
let call_inst = pos
|
||||
.ins()
|
||||
.call(mem_grow_func, &[const_mem_index, by_value, vmctx]);
|
||||
|
||||
// Return value.
|
||||
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(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
index: cranelift_wasm::MemoryIndex,
|
||||
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||
_heap: ir::Heap,
|
||||
) -> 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 {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
@ -582,26 +627,39 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
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),
|
||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||
|
||||
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,
|
||||
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 const_mem_index = pos.ins().iconst(ir::types::I32, mem_index as i64);
|
||||
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]);
|
||||
let call_inst = pos.ins().call(mem_grow_func, &[const_mem_index, vmctx]);
|
||||
|
||||
// Return value.
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,21 @@ pub struct Relocation {
|
||||
pub target: RelocationType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum VmCall {
|
||||
LocalStaticMemoryGrow,
|
||||
LocalStaticMemorySize,
|
||||
ImportedStaticMemoryGrow,
|
||||
ImportedStaticMemorySize,
|
||||
}
|
||||
|
||||
/// Specify the type of relocation
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RelocationType {
|
||||
Normal(LocalFuncIndex),
|
||||
Intrinsic(String),
|
||||
LibCall(LibCall),
|
||||
StaticGrowMemory,
|
||||
StaticCurrentMemory,
|
||||
VmCall(VmCall),
|
||||
}
|
||||
|
||||
/// Implementation of a relocation sink that just saves all the information for later
|
||||
@ -69,11 +76,13 @@ impl binemit::RelocSink for RelocSink {
|
||||
namespace: 1,
|
||||
index,
|
||||
} => {
|
||||
let target = match index {
|
||||
0 => RelocationType::StaticGrowMemory,
|
||||
1 => RelocationType::StaticCurrentMemory,
|
||||
let target = RelocationType::VmCall(match index {
|
||||
0 => VmCall::LocalStaticMemoryGrow,
|
||||
1 => VmCall::LocalStaticMemorySize,
|
||||
2 => VmCall::ImportedStaticMemoryGrow,
|
||||
3 => VmCall::ImportedStaticMemorySize,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
});
|
||||
self.func_relocs.push(Relocation {
|
||||
reloc,
|
||||
offset,
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 cranelift_codegen::{ir, isa, Context};
|
||||
use std::mem;
|
||||
@ -87,8 +87,6 @@ impl FuncResolverBuilder {
|
||||
// called in this way.
|
||||
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 {
|
||||
ir::LibCall::CeilF32 => libcalls::ceilf32 as isize,
|
||||
ir::LibCall::FloorF32 => libcalls::floorf32 as isize,
|
||||
@ -106,6 +104,16 @@ impl FuncResolverBuilder {
|
||||
RelocationType::Intrinsic(ref 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
|
||||
|
@ -4,7 +4,7 @@ use wasmer_runtime::{import::Imports, Instance};
|
||||
|
||||
fn main() {
|
||||
let mut instance = create_module_1();
|
||||
let result = instance.call("type-i64", &[]);
|
||||
let result = instance.call("get-0-ref", &[]);
|
||||
println!("result: {:?}", result);
|
||||
}
|
||||
|
||||
@ -18,21 +18,44 @@ fn main() {
|
||||
// }
|
||||
|
||||
fn create_module_1() -> Instance {
|
||||
let module_str = "(module
|
||||
(type (;0;) (func (result i64)))
|
||||
(func (;0;) (type 0) (result i64)
|
||||
i64.const 356)
|
||||
(func (;1;) (type 0) (result i64)
|
||||
i32.const 0
|
||||
call_indirect (type 0))
|
||||
(table (;0;) 2 anyfunc)
|
||||
(export \"type-i64\" (func 1))
|
||||
(elem (;0;) (i32.const 0) 0 1))
|
||||
";
|
||||
let module_str = r#"(module
|
||||
(type (;0;) (func (result i32)))
|
||||
(import "spectest" "global_i32" (global (;0;) i32))
|
||||
(func (;0;) (type 0) (result i32)
|
||||
get_global 0)
|
||||
(func (;1;) (type 0) (result i32)
|
||||
get_global 1)
|
||||
(global (;1;) i32 (get_global 0))
|
||||
(export "get-0" (func 0))
|
||||
(export "get-0-ref" (func 1)))
|
||||
"#;
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new())
|
||||
.expect("WASM can't be compiled");
|
||||
module
|
||||
.instantiate(&mut Imports::new())
|
||||
.instantiate(&mut generate_imports())
|
||||
.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,
|
||||
};
|
||||
use std::slice;
|
||||
use std::{mem, slice};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LocalBacking {
|
||||
@ -106,20 +106,27 @@ impl LocalBacking {
|
||||
assert!((memory_desc.min * LinearMemory::PAGE_SIZE) as usize >= data_top);
|
||||
let mem: &mut LinearMemory = &mut memories[local_memory_index];
|
||||
|
||||
let to_init = &mut mem[init_base..init_base + init.data.len()];
|
||||
to_init.copy_from_slice(&init.data);
|
||||
let mem_init_view = &mut mem[init_base..init_base + init.data.len()];
|
||||
mem_init_view.copy_from_slice(&init.data);
|
||||
}
|
||||
LocalOrImport::Import(imported_memory_index) => {
|
||||
let _ = imported_memory_index;
|
||||
let _ = imports;
|
||||
unimplemented!()
|
||||
let vm_imported_memory = imports.imported_memory(imported_memory_index);
|
||||
unsafe {
|
||||
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
|
||||
.iter_mut()
|
||||
.map(|(_, mem)| mem.into_vm_memory())
|
||||
.map(|(index, mem)| mem.into_vm_memory(index))
|
||||
.collect::<Map<_, _>>()
|
||||
.into_boxed_map()
|
||||
}
|
||||
@ -154,24 +161,17 @@ impl LocalBacking {
|
||||
}
|
||||
} 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) {
|
||||
LocalOrImport::Local(local_table_index) => {
|
||||
let table = &mut tables[local_table_index];
|
||||
match table.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() {
|
||||
let sig_index = module.func_assoc[func_index];
|
||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||
@ -196,20 +196,33 @@ impl LocalBacking {
|
||||
}
|
||||
}
|
||||
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];
|
||||
match table_description.ty {
|
||||
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() {
|
||||
let sig_index = module.func_assoc[func_index];
|
||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||
@ -228,9 +241,13 @@ impl LocalBacking {
|
||||
}
|
||||
};
|
||||
|
||||
imported_local_table_slice[init_base + i] =
|
||||
vm::Anyfunc { func_data, sig_id };
|
||||
elements[init_base + i] = 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)]
|
||||
pub struct ImportBacking {
|
||||
pub functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
||||
pub memories: BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>,
|
||||
pub tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
||||
pub globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
||||
pub(crate) functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
||||
pub(crate) memories: BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>,
|
||||
pub(crate) tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
||||
pub(crate) globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
||||
}
|
||||
|
||||
impl ImportBacking {
|
||||
@ -296,6 +313,10 @@ impl ImportBacking {
|
||||
globals: import_globals(module, imports)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn imported_memory(&self, memory_index: ImportedMemoryIndex) -> vm::ImportedMemory {
|
||||
self.memories[memory_index].clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn import_functions(
|
||||
|
@ -235,7 +235,7 @@ impl InstanceInner {
|
||||
LocalOrImport::Local(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,
|
||||
*module
|
||||
.memories
|
||||
|
@ -2,7 +2,7 @@ use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::{
|
||||
mmap::{Mmap, Protect},
|
||||
types::Memory,
|
||||
types::{LocalMemoryIndex, Memory},
|
||||
vm,
|
||||
};
|
||||
|
||||
@ -107,10 +107,11 @@ impl LinearMemory {
|
||||
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 {
|
||||
base: self.base(),
|
||||
size: self.size(),
|
||||
index,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ use crate::types::{ElementType, Table};
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TableElements {
|
||||
/// This is intended to be a caller-checked Anyfunc.
|
||||
Anyfunc(Box<[vm::Anyfunc]>),
|
||||
Anyfunc(Vec<vm::Anyfunc>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -16,12 +16,20 @@ pub struct TableBacking {
|
||||
impl TableBacking {
|
||||
pub fn new(table: &Table) -> Self {
|
||||
match table.ty {
|
||||
ElementType::Anyfunc => Self {
|
||||
elements: TableElements::Anyfunc(
|
||||
vec![vm::Anyfunc::null(); table.min as usize].into_boxed_slice(),
|
||||
),
|
||||
ElementType::Anyfunc => {
|
||||
let initial_table_backing_len = match table.max {
|
||||
Some(max) => max,
|
||||
None => table.min,
|
||||
} 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 {
|
||||
base: funcs.as_mut_ptr() as *mut u8,
|
||||
current_elements: funcs.len(),
|
||||
capacity: funcs.capacity(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::backing::ImportBacking;
|
||||
pub use crate::backing::LocalBacking;
|
||||
pub use crate::backing::{ImportBacking, LocalBacking};
|
||||
use crate::types::LocalMemoryIndex;
|
||||
use std::ffi::c_void;
|
||||
use std::{mem, ptr};
|
||||
|
||||
@ -29,10 +29,11 @@ pub struct Ctx {
|
||||
|
||||
/// The local backing of the instance that created this vmctx.
|
||||
pub local_backing: *mut LocalBacking,
|
||||
/// The import backing of the parent instance.
|
||||
pub import_backing: *mut ImportBacking,
|
||||
|
||||
/// Host data
|
||||
pub data: *mut c_void,
|
||||
|
||||
/// Host data finalizer
|
||||
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(),
|
||||
|
||||
local_backing,
|
||||
import_backing,
|
||||
|
||||
data: ptr::null_mut(),
|
||||
data_finalizer: None,
|
||||
}
|
||||
@ -83,6 +86,8 @@ impl Ctx {
|
||||
imported_funcs: import_backing.functions.as_mut_ptr(),
|
||||
|
||||
local_backing,
|
||||
import_backing,
|
||||
|
||||
data,
|
||||
data_finalizer,
|
||||
}
|
||||
@ -156,6 +161,8 @@ pub struct LocalTable {
|
||||
pub base: *mut u8,
|
||||
/// Number of elements in the table (NOT necessarily the size of the table in bytes!).
|
||||
pub current_elements: usize,
|
||||
/// The number of elements that can fit into the memory allocated for this table.
|
||||
pub capacity: usize,
|
||||
}
|
||||
|
||||
impl LocalTable {
|
||||
@ -203,6 +210,8 @@ pub struct LocalMemory {
|
||||
pub base: *mut u8,
|
||||
/// Current size of this linear memory in bytes.
|
||||
pub size: usize,
|
||||
/// The local memory index.
|
||||
pub index: LocalMemoryIndex,
|
||||
}
|
||||
|
||||
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,
|
||||
by_pages: u32,
|
||||
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()
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn memory_grow_dynamic(
|
||||
pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||
memory_index: LocalMemoryIndex,
|
||||
by_pages: u32,
|
||||
ctx: *mut vm::Ctx,
|
||||
@ -39,3 +51,68 @@ pub unsafe extern "C" fn memory_grow_dynamic(
|
||||
-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