Get most spectests passing

This commit is contained in:
Lachlan Sneff
2019-01-17 13:09:05 -08:00
parent c74eed8a06
commit 1dbbaa30b6
10 changed files with 316 additions and 101 deletions

View File

@ -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())
} }
} }

View File

@ -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,

View File

@ -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

View File

@ -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
}

View File

@ -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(

View File

@ -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

View File

@ -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,
} }
} }

View File

@ -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(),
}, },
} }
} }

View File

@ -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 {

View File

@ -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!()
}