mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 21:51:32 +00:00
Get table imports working
This commit is contained in:
@ -6,6 +6,7 @@ pub use self::recovery::{call_protected, HandlerData};
|
||||
use crate::trampoline::Trampolines;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use std::sync::Arc;
|
||||
use wasmer_runtime_core::{
|
||||
backend::{ProtectedCaller, Token},
|
||||
error::RuntimeResult,
|
||||
@ -62,11 +63,14 @@ impl ProtectedCaller for Caller {
|
||||
assert!(self.func_export_set.contains(&func_index));
|
||||
|
||||
assert!(
|
||||
signature.returns.len() <= 1,
|
||||
signature.returns().len() <= 1,
|
||||
"multi-value returns not yet supported"
|
||||
);
|
||||
|
||||
assert!(signature.check_sig(params), "incorrect signature");
|
||||
assert!(
|
||||
signature.check_param_value_types(params),
|
||||
"incorrect signature"
|
||||
);
|
||||
|
||||
let param_vec: Vec<u64> = params
|
||||
.iter()
|
||||
@ -78,7 +82,7 @@ impl ProtectedCaller for Caller {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut return_vec = vec![0; signature.returns.len()];
|
||||
let mut return_vec = vec![0; signature.returns().len()];
|
||||
|
||||
let trampoline = self
|
||||
.trampolines
|
||||
@ -97,7 +101,7 @@ impl ProtectedCaller for Caller {
|
||||
|
||||
Ok(return_vec
|
||||
.iter()
|
||||
.zip(signature.returns.iter())
|
||||
.zip(signature.returns().iter())
|
||||
.map(|(&x, ty)| match ty {
|
||||
Type::I32 => Value::I32(x as i32),
|
||||
Type::I64 => Value::I64(x as i64),
|
||||
@ -108,11 +112,11 @@ impl ProtectedCaller for Caller {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_func_from_index<'a>(
|
||||
module: &'a ModuleInner,
|
||||
fn get_func_from_index(
|
||||
module: &ModuleInner,
|
||||
import_backing: &ImportBacking,
|
||||
func_index: FuncIndex,
|
||||
) -> (*const vm::Func, Context, &'a FuncSig, SigIndex) {
|
||||
) -> (*const vm::Func, Context, Arc<FuncSig>, SigIndex) {
|
||||
let sig_index = *module
|
||||
.func_assoc
|
||||
.get(func_index)
|
||||
@ -137,7 +141,7 @@ fn get_func_from_index<'a>(
|
||||
}
|
||||
};
|
||||
|
||||
let signature = module.sig_registry.lookup_func_sig(sig_index);
|
||||
let signature = module.sig_registry.lookup_signature(sig_index);
|
||||
|
||||
(func_ptr, ctx, signature, sig_index)
|
||||
}
|
||||
|
@ -25,9 +25,12 @@ impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> {
|
||||
}
|
||||
|
||||
/// Creates a signature with VMContext as the last param
|
||||
pub fn generate_signature(&self, sig_index: cranelift_wasm::SignatureIndex) -> ir::Signature {
|
||||
pub fn generate_signature(
|
||||
&self,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
) -> ir::Signature {
|
||||
// Get signature
|
||||
let mut signature = self.env.signatures[Converter(sig_index).into()].clone();
|
||||
let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone();
|
||||
|
||||
// Add the vmctx parameter type to it
|
||||
signature.params.push(ir::AbiParam::special(
|
||||
@ -251,7 +254,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
let ptr_type = self.pointer_type();
|
||||
|
||||
match table_index.local_or_import(self.env.module) {
|
||||
let (table_struct_ptr_ptr, description) = match table_index.local_or_import(self.env.module)
|
||||
{
|
||||
LocalOrImport::Local(local_table_index) => {
|
||||
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
@ -260,88 +264,74 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
let table_struct_offset =
|
||||
let table_struct_ptr_offset =
|
||||
local_table_index.index() * vm::LocalTable::size() as usize;
|
||||
|
||||
let table_struct_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
let table_struct_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: tables_base,
|
||||
offset: (table_struct_offset as i64).into(),
|
||||
offset: (table_struct_ptr_offset as i64).into(),
|
||||
global_type: ptr_type,
|
||||
});
|
||||
|
||||
let table_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: table_struct_addr,
|
||||
offset: (vm::LocalTable::offset_base() as i32).into(),
|
||||
global_type: ptr_type,
|
||||
// we will support growing tables, so this cannot be readonly.
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
let table_bound = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: table_struct_addr,
|
||||
offset: (vm::LocalTable::offset_current_elements() as i32).into(),
|
||||
// the number of elements in a table will always fit in an `i32`.
|
||||
global_type: ir::types::I32,
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
func.create_table(ir::TableData {
|
||||
base_gv: table_base,
|
||||
min_size: (self.env.module.tables[local_table_index].min as u64).into(),
|
||||
bound_gv: table_bound,
|
||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
(
|
||||
table_struct_ptr_ptr,
|
||||
self.env.module.tables[local_table_index],
|
||||
)
|
||||
}
|
||||
LocalOrImport::Import(imported_table_index) => {
|
||||
let imported_tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
LocalOrImport::Import(import_table_index) => {
|
||||
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
offset: (vm::Ctx::offset_imported_tables() as i32).into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
let imported_table_struct_offset =
|
||||
imported_table_index.index() * vm::ImportedTable::size() as usize;
|
||||
let table_struct_ptr_offset =
|
||||
import_table_index.index() * vm::LocalTable::size() as usize;
|
||||
|
||||
let imported_table_struct_addr =
|
||||
func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: imported_tables_base,
|
||||
offset: (imported_table_struct_offset as i64).into(),
|
||||
global_type: ptr_type,
|
||||
});
|
||||
|
||||
let local_table_struct_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: imported_table_struct_addr,
|
||||
offset: (vm::ImportedTable::offset_table() as i32).into(),
|
||||
let table_struct_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: tables_base,
|
||||
offset: (table_struct_ptr_offset as i64).into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
let local_table_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: local_table_struct_addr,
|
||||
offset: (vm::LocalTable::offset_base() as i32).into(),
|
||||
global_type: ptr_type,
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
let local_table_bound = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: local_table_struct_addr,
|
||||
offset: (vm::LocalTable::offset_current_elements() as i32).into(),
|
||||
global_type: ir::types::I32,
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
func.create_table(ir::TableData {
|
||||
base_gv: local_table_base,
|
||||
min_size: (self.env.module.imported_tables[imported_table_index].1.min as u64)
|
||||
.into(),
|
||||
bound_gv: local_table_bound,
|
||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
(
|
||||
table_struct_ptr_ptr,
|
||||
self.env.module.imported_tables[import_table_index].1,
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let table_struct_ptr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: table_struct_ptr_ptr,
|
||||
offset: 0.into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
let table_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: table_struct_ptr,
|
||||
offset: (vm::LocalTable::offset_base() as i32).into(),
|
||||
global_type: ptr_type,
|
||||
// The table can reallocate, so the ptr can't be readonly.
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
let table_count = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: table_struct_ptr,
|
||||
offset: (vm::LocalTable::offset_count() as i32).into(),
|
||||
global_type: ptr_type,
|
||||
// The table length can change, so it can't be readonly.
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
func.create_table(ir::TableData {
|
||||
base_gv: table_base,
|
||||
min_size: (description.min as u64).into(),
|
||||
bound_gv: table_count,
|
||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets up a signature definition in `func`'s preamble.
|
||||
@ -351,10 +341,10 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
fn make_indirect_sig(
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
index: cranelift_wasm::SignatureIndex,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
) -> ir::SigRef {
|
||||
// Create a signature reference out of specified signature (with VMContext param added).
|
||||
func.import_signature(self.generate_signature(index))
|
||||
func.import_signature(self.generate_signature(clif_sig_index))
|
||||
}
|
||||
|
||||
/// Sets up an external function definition in the preamble of `func` that can be used to
|
||||
@ -393,7 +383,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
mut pos: FuncCursor,
|
||||
_table_index: cranelift_wasm::TableIndex,
|
||||
table: ir::Table,
|
||||
sig_index: cranelift_wasm::SignatureIndex,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
sig_ref: ir::SigRef,
|
||||
callee: ir::Value,
|
||||
call_args: &[ir::Value],
|
||||
@ -412,12 +402,25 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
entry_addr,
|
||||
vm::Anyfunc::offset_func() as i32,
|
||||
);
|
||||
let vmctx_ptr = pos.ins().load(
|
||||
ptr_type,
|
||||
mflags,
|
||||
entry_addr,
|
||||
vm::Anyfunc::offset_vmctx() as i32,
|
||||
);
|
||||
|
||||
let vmctx_ptr = {
|
||||
let loaded_vmctx_ptr = pos.ins().load(
|
||||
ptr_type,
|
||||
mflags,
|
||||
entry_addr,
|
||||
vm::Anyfunc::offset_vmctx() as i32,
|
||||
);
|
||||
|
||||
let argument_vmctx_ptr = pos
|
||||
.func
|
||||
.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.expect("missing vmctx parameter");
|
||||
|
||||
// If the loaded vmctx ptr is zero, use the caller vmctx, else use the callee (loaded) vmctx.
|
||||
pos.ins()
|
||||
.select(loaded_vmctx_ptr, loaded_vmctx_ptr, argument_vmctx_ptr)
|
||||
};
|
||||
|
||||
let found_sig = pos.ins().load(
|
||||
ir::types::I32,
|
||||
mflags,
|
||||
@ -427,14 +430,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
|
||||
pos.ins().trapz(func_ptr, ir::TrapCode::IndirectCallToNull);
|
||||
|
||||
let deduplicated_sig_index = self
|
||||
.env
|
||||
.module
|
||||
.sig_registry
|
||||
.lookup_deduplicated_sigindex(Converter(sig_index).into());
|
||||
let expected_sig = pos
|
||||
.ins()
|
||||
.iconst(ir::types::I32, deduplicated_sig_index.index() as i64);
|
||||
let sig_index = self.env.deduplicated[clif_sig_index];
|
||||
|
||||
let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64);
|
||||
let not_equal_flags = pos.ins().ifcmp(found_sig, expected_sig);
|
||||
|
||||
pos.ins().trapif(
|
||||
|
@ -76,7 +76,7 @@ impl Module {
|
||||
start_func: None,
|
||||
|
||||
func_assoc: Map::new(),
|
||||
sig_registry: SigRegistry::new(),
|
||||
sig_registry: SigRegistry,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -87,11 +87,11 @@ impl Module {
|
||||
functions: Map<LocalFuncIndex, ir::Function>,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
// we have to deduplicate `module.func_assoc`
|
||||
let func_assoc = &mut self.module.func_assoc;
|
||||
let sig_registry = &self.module.sig_registry;
|
||||
func_assoc.iter_mut().for_each(|(_, sig_index)| {
|
||||
*sig_index = sig_registry.lookup_deduplicated_sigindex(*sig_index);
|
||||
});
|
||||
// let func_assoc = &mut self.module.func_assoc;
|
||||
// let sig_registry = &self.module.sig_registry;
|
||||
// func_assoc.iter_mut().for_each(|(_, sig_index)| {
|
||||
// *sig_index = sig_registry.lookup_deduplicated_sigindex(*sig_index);
|
||||
// });
|
||||
|
||||
let (func_resolver_builder, handler_data) = FuncResolverBuilder::new(isa, functions)?;
|
||||
self.module.func_resolver = Box::new(func_resolver_builder.finalize()?);
|
||||
@ -152,20 +152,20 @@ convert_clif_to_runtime_index![
|
||||
|
||||
impl<'a> From<Converter<&'a ir::Signature>> for FuncSig {
|
||||
fn from(signature: Converter<&'a ir::Signature>) -> Self {
|
||||
FuncSig {
|
||||
params: signature
|
||||
FuncSig::new(
|
||||
signature
|
||||
.0
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| Converter(param.value_type).into())
|
||||
.collect(),
|
||||
returns: signature
|
||||
.collect::<Vec<_>>(),
|
||||
signature
|
||||
.0
|
||||
.returns
|
||||
.iter()
|
||||
.map(|ret| Converter(ret.value_type).into())
|
||||
.collect(),
|
||||
}
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,15 @@ use crate::{
|
||||
module::{Converter, Module},
|
||||
};
|
||||
use cranelift_codegen::{ir, isa};
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
||||
use hashbrown::HashMap;
|
||||
use wasmer_runtime_core::{
|
||||
error::{CompileError, CompileResult},
|
||||
module::{DataInitializer, ExportIndex, ImportName, TableInitializer},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
ElementType, GlobalDesc, GlobalIndex, GlobalInit, Initializer, LocalFuncIndex,
|
||||
ElementType, FuncSig, GlobalDesc, GlobalIndex, GlobalInit, Initializer, LocalFuncIndex,
|
||||
LocalOrImport, MemoryDesc, SigIndex, TableDesc, Value,
|
||||
},
|
||||
};
|
||||
@ -20,6 +22,8 @@ pub struct ModuleEnv<'module, 'isa> {
|
||||
pub signatures: Map<SigIndex, ir::Signature>,
|
||||
globals: Map<GlobalIndex, cranelift_wasm::Global>,
|
||||
func_bodies: Map<LocalFuncIndex, ir::Function>,
|
||||
pub deduplicated: PrimaryMap<cranelift_wasm::SignatureIndex, SigIndex>,
|
||||
duplicated: HashMap<SigIndex, cranelift_wasm::SignatureIndex>,
|
||||
}
|
||||
|
||||
impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
||||
@ -30,6 +34,8 @@ impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
||||
signatures: Map::new(),
|
||||
globals: Map::new(),
|
||||
func_bodies: Map::new(),
|
||||
deduplicated: PrimaryMap::new(),
|
||||
duplicated: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,23 +54,28 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
|
||||
/// Declares a function signature to the environment.
|
||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||
self.signatures.push(sig.clone());
|
||||
self.module.sig_registry.register(Converter(sig).into());
|
||||
let clif_sig_index = self.signatures.push(sig.clone());
|
||||
let func_sig: FuncSig = Converter(sig).into();
|
||||
let sig_index = self.module.sig_registry.lookup_sigindex(func_sig);
|
||||
self.deduplicated.push(sig_index);
|
||||
self.duplicated
|
||||
.insert(sig_index, Converter(clif_sig_index).into());
|
||||
}
|
||||
|
||||
/// Return the signature with the given index.
|
||||
fn get_signature(&self, sig_index: cranelift_wasm::SignatureIndex) -> &ir::Signature {
|
||||
&self.signatures[Converter(sig_index).into()]
|
||||
fn get_signature(&self, clif_sig_index: cranelift_wasm::SignatureIndex) -> &ir::Signature {
|
||||
&self.signatures[Converter(clif_sig_index).into()]
|
||||
}
|
||||
|
||||
/// Declares a function import to the environment.
|
||||
fn declare_func_import(
|
||||
&mut self,
|
||||
sig_index: cranelift_wasm::SignatureIndex,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
namespace: &'data str,
|
||||
name: &'data str,
|
||||
) {
|
||||
self.module.func_assoc.push(Converter(sig_index).into());
|
||||
let sig_index = self.deduplicated[clif_sig_index];
|
||||
self.module.func_assoc.push(sig_index);
|
||||
|
||||
// Add import names to list of imported functions
|
||||
self.module.imported_functions.push(ImportName {
|
||||
@ -79,8 +90,9 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
}
|
||||
|
||||
/// Declares the type (signature) of a local function in the module.
|
||||
fn declare_func_type(&mut self, sig_index: cranelift_wasm::SignatureIndex) {
|
||||
self.module.func_assoc.push(Converter(sig_index).into());
|
||||
fn declare_func_type(&mut self, clif_sig_index: cranelift_wasm::SignatureIndex) {
|
||||
let sig_index = self.deduplicated[clif_sig_index];
|
||||
self.module.func_assoc.push(sig_index);
|
||||
}
|
||||
|
||||
/// Return the signature index for the given function index.
|
||||
@ -88,7 +100,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
&self,
|
||||
func_index: cranelift_wasm::FuncIndex,
|
||||
) -> cranelift_wasm::SignatureIndex {
|
||||
Converter(self.module.func_assoc[Converter(func_index).into()]).into()
|
||||
let sig_index: SigIndex = self.module.func_assoc[Converter(func_index).into()];
|
||||
self.duplicated[&sig_index]
|
||||
}
|
||||
|
||||
/// Declares a global to the environment.
|
||||
|
@ -43,9 +43,9 @@ impl Trampolines {
|
||||
|
||||
for exported_func_index in func_index_iter {
|
||||
let sig_index = module.func_assoc[*exported_func_index];
|
||||
let func_sig = module.sig_registry.lookup_func_sig(sig_index);
|
||||
let func_sig = module.sig_registry.lookup_signature(sig_index);
|
||||
|
||||
let trampoline_func = generate_func(func_sig);
|
||||
let trampoline_func = generate_func(&func_sig);
|
||||
|
||||
ctx.func = trampoline_func;
|
||||
|
||||
@ -128,8 +128,8 @@ fn generate_func(func_sig: &FuncSig) -> ir::Function {
|
||||
|
||||
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(entry_ebb);
|
||||
|
||||
let mut args_vec = Vec::with_capacity(func_sig.params.len() + 1);
|
||||
for (index, wasm_ty) in func_sig.params.iter().enumerate() {
|
||||
let mut args_vec = Vec::with_capacity(func_sig.params().len() + 1);
|
||||
for (index, wasm_ty) in func_sig.params().iter().enumerate() {
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
|
||||
let val = pos.ins().load(
|
||||
@ -190,7 +190,7 @@ fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature {
|
||||
let mut export_clif_sig = ir::Signature::new(isa::CallConv::SystemV);
|
||||
|
||||
export_clif_sig.params = func_sig
|
||||
.params
|
||||
.params()
|
||||
.iter()
|
||||
.map(|wasm_ty| ir::AbiParam {
|
||||
value_type: wasm_ty_to_clif(*wasm_ty),
|
||||
@ -207,7 +207,7 @@ fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature {
|
||||
.collect();
|
||||
|
||||
export_clif_sig.returns = func_sig
|
||||
.returns
|
||||
.returns()
|
||||
.iter()
|
||||
.map(|wasm_ty| ir::AbiParam {
|
||||
value_type: wasm_ty_to_clif(*wasm_ty),
|
||||
|
Reference in New Issue
Block a user