Implement the remaining valid spec tests.
And lots of other miscellaneous changes. Rename InstanceWorld to InstancePlus and reorganize its contents. This still isn't a great name, but at least now it has a clear purpose.
This commit is contained in:
@@ -132,14 +132,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
||||
self.isa.frontend_config().pointer_type()
|
||||
}
|
||||
|
||||
/// Transform the call argument list in preparation for making a call.
|
||||
fn get_real_call_args(func: &Function, call_args: &[ir::Value]) -> Vec<ir::Value> {
|
||||
let mut real_call_args = Vec::with_capacity(call_args.len() + 1);
|
||||
real_call_args.extend_from_slice(call_args);
|
||||
real_call_args.push(func.special_param(ArgumentPurpose::VMContext).unwrap());
|
||||
real_call_args
|
||||
}
|
||||
|
||||
fn vmctx(&mut self, func: &mut Function) -> ir::GlobalValue {
|
||||
self.vmctx.unwrap_or_else(|| {
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
@@ -539,15 +531,6 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
|
||||
let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0);
|
||||
|
||||
// Dereference table_entry_addr to get the function address.
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
let func_addr = pos.ins().load(
|
||||
pointer_type,
|
||||
mem_flags,
|
||||
table_entry_addr,
|
||||
i32::from(self.offsets.vmcaller_checked_anyfunc_func_ptr()),
|
||||
);
|
||||
|
||||
// If necessary, check the signature.
|
||||
match self.module.table_plans[table_index].style {
|
||||
TableStyle::CallerChecksSignature => {
|
||||
@@ -597,7 +580,27 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
}
|
||||
}
|
||||
|
||||
let real_call_args = FuncEnvironment::get_real_call_args(pos.func, call_args);
|
||||
// Dereference table_entry_addr to get the function address.
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
let func_addr = pos.ins().load(
|
||||
pointer_type,
|
||||
mem_flags,
|
||||
table_entry_addr,
|
||||
i32::from(self.offsets.vmcaller_checked_anyfunc_func_ptr()),
|
||||
);
|
||||
|
||||
let mut real_call_args = Vec::with_capacity(call_args.len() + 1);
|
||||
real_call_args.extend_from_slice(call_args);
|
||||
|
||||
// Append the callee vmctx address.
|
||||
let vmctx = pos.ins().load(
|
||||
pointer_type,
|
||||
mem_flags,
|
||||
table_entry_addr,
|
||||
i32::from(self.offsets.vmcaller_checked_anyfunc_vmctx()),
|
||||
);
|
||||
real_call_args.push(vmctx);
|
||||
|
||||
Ok(pos.ins().call_indirect(sig_ref, func_addr, &real_call_args))
|
||||
}
|
||||
|
||||
@@ -608,10 +611,12 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
callee: ir::FuncRef,
|
||||
call_args: &[ir::Value],
|
||||
) -> WasmResult<ir::Inst> {
|
||||
let real_call_args = FuncEnvironment::get_real_call_args(pos.func, call_args);
|
||||
let mut real_call_args = Vec::with_capacity(call_args.len() + 1);
|
||||
real_call_args.extend_from_slice(call_args);
|
||||
|
||||
// Handle direct calls to locally-defined functions.
|
||||
if !self.module.is_imported_function(callee_index) {
|
||||
real_call_args.push(pos.func.special_param(ArgumentPurpose::VMContext).unwrap());
|
||||
return Ok(pos.ins().call(callee, &real_call_args));
|
||||
}
|
||||
|
||||
@@ -623,9 +628,18 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
let base = pos
|
||||
.ins()
|
||||
.global_value(pointer_type, imported_functions_base);
|
||||
let offset = self.offsets.index_vmfunction_body_import(callee_index);
|
||||
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
let func_addr = pos.ins().load(pointer_type, mem_flags, base, offset);
|
||||
|
||||
// Load the callee address.
|
||||
let body_offset = self.offsets.index_vmfunction_import_body(callee_index);
|
||||
let func_addr = pos.ins().load(pointer_type, mem_flags, base, body_offset);
|
||||
|
||||
// Append the callee vmctx address.
|
||||
let vmctx_offset = self.offsets.index_vmfunction_import_vmctx(callee_index);
|
||||
let vmctx = pos.ins().load(pointer_type, mem_flags, base, vmctx_offset);
|
||||
real_call_args.push(vmctx);
|
||||
|
||||
Ok(pos.ins().call_indirect(sig_ref, func_addr, &real_call_args))
|
||||
}
|
||||
|
||||
|
||||
@@ -48,10 +48,10 @@ mod vmoffsets;
|
||||
pub use compilation::{
|
||||
compile_module, Compilation, CompileError, RelocSink, Relocation, RelocationTarget, Relocations,
|
||||
};
|
||||
pub use module::{
|
||||
DataInitializer, Export, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle,
|
||||
pub use module::{Export, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle};
|
||||
pub use module_environ::{
|
||||
translate_signature, DataInitializer, ModuleEnvironment, ModuleTranslation,
|
||||
};
|
||||
pub use module_environ::{translate_signature, ModuleEnvironment, ModuleTranslation};
|
||||
pub use tunables::Tunables;
|
||||
pub use vmoffsets::VMOffsets;
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ impl MemoryStyle {
|
||||
|
||||
/// A WebAssembly linear memory description along with our chosen style for
|
||||
/// implementing it.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MemoryPlan {
|
||||
/// The WebAssembly linear memory description.
|
||||
pub memory: Memory,
|
||||
@@ -113,7 +113,7 @@ impl TableStyle {
|
||||
|
||||
/// A WebAssembly table description along with our chosen style for
|
||||
/// implementing it.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TablePlan {
|
||||
/// The WebAssembly table description.
|
||||
pub table: cranelift_wasm::Table,
|
||||
@@ -277,34 +277,3 @@ impl Module {
|
||||
index.index() < self.imported_globals.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// A data initializer for linear memory.
|
||||
pub struct DataInitializer<'data> {
|
||||
/// The index of the memory to initialize.
|
||||
pub memory_index: MemoryIndex,
|
||||
/// Optionally a globalvar base to initialize at.
|
||||
pub base: Option<GlobalIndex>,
|
||||
/// A constant offset to initialize at.
|
||||
pub offset: usize,
|
||||
/// The initialization data.
|
||||
pub data: &'data [u8],
|
||||
}
|
||||
|
||||
/// References to the input wasm data buffer to be decoded and processed later,
|
||||
/// separately from the main module translation.
|
||||
pub struct LazyContents<'data> {
|
||||
/// References to the function bodies.
|
||||
pub function_body_inputs: PrimaryMap<DefinedFuncIndex, &'data [u8]>,
|
||||
|
||||
/// References to the data initializers.
|
||||
pub data_initializers: Vec<DataInitializer<'data>>,
|
||||
}
|
||||
|
||||
impl<'data> LazyContents<'data> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
function_body_inputs: PrimaryMap::new(),
|
||||
data_initializers: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{
|
||||
self, translate_module, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex,
|
||||
Table, TableIndex, WasmResult,
|
||||
self, translate_module, DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
|
||||
SignatureIndex, Table, TableIndex, WasmResult,
|
||||
};
|
||||
use func_environ::FuncEnvironment;
|
||||
use module::{DataInitializer, Export, LazyContents, MemoryPlan, Module, TableElements, TablePlan};
|
||||
use module::{Export, MemoryPlan, Module, TableElements, TablePlan};
|
||||
use std::clone::Clone;
|
||||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
@@ -259,3 +260,34 @@ pub fn translate_signature(mut sig: ir::Signature, pointer_type: ir::Type) -> ir
|
||||
.push(AbiParam::special(pointer_type, ArgumentPurpose::VMContext));
|
||||
sig
|
||||
}
|
||||
|
||||
/// A data initializer for linear memory.
|
||||
pub struct DataInitializer<'data> {
|
||||
/// The index of the memory to initialize.
|
||||
pub memory_index: MemoryIndex,
|
||||
/// Optionally a globalvar base to initialize at.
|
||||
pub base: Option<GlobalIndex>,
|
||||
/// A constant offset to initialize at.
|
||||
pub offset: usize,
|
||||
/// The initialization data.
|
||||
pub data: &'data [u8],
|
||||
}
|
||||
|
||||
/// References to the input wasm data buffer to be decoded and processed later,
|
||||
/// separately from the main module translation.
|
||||
pub struct LazyContents<'data> {
|
||||
/// References to the function bodies.
|
||||
pub function_body_inputs: PrimaryMap<DefinedFuncIndex, &'data [u8]>,
|
||||
|
||||
/// References to the data initializers.
|
||||
pub data_initializers: Vec<DataInitializer<'data>>,
|
||||
}
|
||||
|
||||
impl<'data> LazyContents<'data> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
function_body_inputs: PrimaryMap::new(),
|
||||
data_initializers: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,26 @@ impl VMOffsets {
|
||||
}
|
||||
}
|
||||
|
||||
/// Offsets for `VMFunctionImport`.
|
||||
impl VMOffsets {
|
||||
/// The offset of the `body` field.
|
||||
#[allow(clippy::erasing_op)]
|
||||
pub fn vmfunction_import_body(&self) -> u8 {
|
||||
0 * self.pointer_size
|
||||
}
|
||||
|
||||
/// The offset of the `vmctx` field.
|
||||
#[allow(clippy::identity_op)]
|
||||
pub fn vmfunction_import_vmctx(&self) -> u8 {
|
||||
1 * self.pointer_size
|
||||
}
|
||||
|
||||
/// Return the size of `VMFunctionImport`.
|
||||
pub fn size_of_vmfunction_import(&self) -> u8 {
|
||||
2 * self.pointer_size
|
||||
}
|
||||
}
|
||||
|
||||
/// Offsets for `*const VMFunctionBody`.
|
||||
impl VMOffsets {
|
||||
/// The size of the `current_elements` field.
|
||||
@@ -174,9 +194,14 @@ impl VMOffsets {
|
||||
1 * self.pointer_size
|
||||
}
|
||||
|
||||
/// The offset of the `vmctx` field.
|
||||
pub fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 {
|
||||
2 * self.pointer_size
|
||||
}
|
||||
|
||||
/// Return the size of `VMCallerCheckedAnyfunc`.
|
||||
pub fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
|
||||
2 * self.pointer_size
|
||||
3 * self.pointer_size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +255,17 @@ impl VMOffsets {
|
||||
8 * self.pointer_size
|
||||
}
|
||||
|
||||
/// Return the offset from the `imported_functions` pointer to `VMFunctionImport` index `index`.
|
||||
fn index_vmfunction_import(&self, index: FuncIndex) -> i32 {
|
||||
cast::i32(
|
||||
index
|
||||
.as_u32()
|
||||
.checked_mul(u32::from(self.size_of_vmfunction_import()))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Return the offset from the `imported_tables` pointer to `VMTableImport` index `index`.
|
||||
fn index_vmtable_import(&self, index: TableIndex) -> i32 {
|
||||
cast::i32(
|
||||
@@ -286,15 +322,19 @@ impl VMOffsets {
|
||||
}
|
||||
|
||||
/// Return the offset from the `imported_functions` pointer to the
|
||||
/// `*const VMFunctionBody` index `index`.
|
||||
pub fn index_vmfunction_body_import(&self, index: FuncIndex) -> i32 {
|
||||
cast::i32(
|
||||
index
|
||||
.as_u32()
|
||||
.checked_mul(u32::from(self.size_of_vmfunction_body_ptr()))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
/// `body` field in `*const VMFunctionBody` index `index`.
|
||||
pub fn index_vmfunction_import_body(&self, index: FuncIndex) -> i32 {
|
||||
self.index_vmfunction_import(index)
|
||||
.checked_add(i32::from(self.vmfunction_import_body()))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Return the offset from the `imported_functions` pointer to the
|
||||
/// `vmctx` field in `*const VMFunctionBody` index `index`.
|
||||
pub fn index_vmfunction_import_vmctx(&self, index: FuncIndex) -> i32 {
|
||||
self.index_vmfunction_import(index)
|
||||
.checked_add(i32::from(self.vmfunction_import_vmctx()))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Return the offset from the `tables` pointer to the `from` field in
|
||||
|
||||
Reference in New Issue
Block a user