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:
Dan Gohman
2018-12-11 17:12:33 -08:00
parent 6dd39dee6a
commit 3f24098edc
34 changed files with 1572 additions and 1262 deletions

View File

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

View File

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

View File

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

View File

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

View File

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