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

@@ -1,16 +1,14 @@
use cranelift_codegen::ir::types;
use cranelift_codegen::{ir, isa};
use cranelift_entity::PrimaryMap;
use cranelift_wasm::{Global, GlobalInit, Memory, Table, TableElementType};
use std::ptr;
use cranelift_wasm::{DefinedFuncIndex, Global, GlobalInit, Memory, Table, TableElementType};
use std::rc::Rc;
use target_lexicon::HOST;
use wasmtime_environ::{
translate_signature, MemoryPlan, MemoryStyle, Module, TablePlan, TableStyle,
};
use wasmtime_execute::{Export, Resolver};
use wasmtime_runtime::{
Imports, Instance, VMFunctionBody, VMGlobalDefinition, VMMemoryDefinition, VMTableDefinition,
translate_signature, Export, MemoryPlan, MemoryStyle, Module, TablePlan, TableStyle,
};
use wasmtime_execute::{ActionError, InstancePlus};
use wasmtime_runtime::{Imports, VMFunctionBody};
extern "C" fn spectest_print() {}
@@ -46,195 +44,181 @@ extern "C" fn spectest_print_f64_f64(x: f64, y: f64) {
println!("{}: f64", y);
}
pub struct SpecTest {
instance: Instance,
spectest_global_i32: VMGlobalDefinition,
spectest_global_f32: VMGlobalDefinition,
spectest_global_f64: VMGlobalDefinition,
spectest_table: VMTableDefinition,
spectest_memory: VMMemoryDefinition,
}
/// Return an instance implementing the "spectest" interface used in the
/// spec testsuite.
pub fn instantiate_spectest() -> Result<InstancePlus, ActionError> {
let call_conv = isa::CallConv::triple_default(&HOST);
let pointer_type = types::Type::triple_pointer_type(&HOST);
let mut module = Module::new();
let mut finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody> =
PrimaryMap::new();
impl SpecTest {
pub fn new() -> Result<Self, String> {
let finished_functions = PrimaryMap::new();
let imports = Imports::none();
let data_initializers = Vec::new();
Ok(Self {
instance: Instance::new(
&Module::new(),
&finished_functions.into_boxed_slice(),
imports,
&data_initializers,
)?,
spectest_global_i32: VMGlobalDefinition::new(&Global {
ty: types::I32,
mutability: true,
initializer: GlobalInit::I32Const(0),
}),
spectest_global_f32: VMGlobalDefinition::new(&Global {
ty: types::I32,
mutability: true,
initializer: GlobalInit::F32Const(0),
}),
spectest_global_f64: VMGlobalDefinition::new(&Global {
ty: types::I32,
mutability: true,
initializer: GlobalInit::F64Const(0),
}),
spectest_table: VMTableDefinition {
base: ptr::null_mut(),
current_elements: 0,
},
spectest_memory: VMMemoryDefinition {
base: ptr::null_mut(),
current_length: 0,
},
})
}
}
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print".to_owned(), Export::Function(func));
finished_functions.push(spectest_print as *const VMFunctionBody);
impl Resolver for SpecTest {
fn resolve(&mut self, module: &str, field: &str) -> Option<Export> {
let call_conv = isa::CallConv::triple_default(&HOST);
let pointer_type = types::Type::triple_pointer_type(&HOST);
match module {
"spectest" => match field {
"print" => Some(Export::function(
spectest_print as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"print_i32" => Some(Export::function(
spectest_print_i32 as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::I32)],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"print_i64" => Some(Export::function(
spectest_print_i64 as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::I64)],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"print_f32" => Some(Export::function(
spectest_print_f32 as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::F32)],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"print_f64" => Some(Export::function(
spectest_print_f64 as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::F64)],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"print_i32_f32" => Some(Export::function(
spectest_print_i32_f32 as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![
ir::AbiParam::new(types::I32),
ir::AbiParam::new(types::F32),
],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"print_f64_f64" => Some(Export::function(
spectest_print_f64_f64 as *const VMFunctionBody,
translate_signature(
ir::Signature {
params: vec![
ir::AbiParam::new(types::F64),
ir::AbiParam::new(types::F64),
],
returns: vec![],
call_conv,
},
pointer_type,
),
)),
"global_i32" => Some(Export::global(
&mut self.spectest_global_i32,
Global {
ty: ir::types::I32,
mutability: false,
initializer: GlobalInit::I32Const(0),
},
)),
"global_f32" => Some(Export::global(
&mut self.spectest_global_f32,
Global {
ty: ir::types::F32,
mutability: false,
initializer: GlobalInit::F32Const(0),
},
)),
"global_f64" => Some(Export::global(
&mut self.spectest_global_f64,
Global {
ty: ir::types::F64,
mutability: false,
initializer: GlobalInit::F64Const(0),
},
)),
"table" => Some(Export::table(
&mut self.spectest_table,
self.instance.vmctx_mut(),
TablePlan {
table: Table {
ty: TableElementType::Func,
minimum: 0,
maximum: None,
},
style: TableStyle::CallerChecksSignature,
},
)),
"memory" => Some(Export::memory(
&mut self.spectest_memory,
self.instance.vmctx_mut(),
MemoryPlan {
memory: Memory {
minimum: 0,
maximum: None,
shared: false,
},
style: MemoryStyle::Dynamic,
offset_guard_size: 0,
},
)),
_ => None,
},
_ => None,
}
}
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::I32)],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print_i32".to_owned(), Export::Function(func));
finished_functions.push(spectest_print_i32 as *const VMFunctionBody);
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::I64)],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print_i64".to_owned(), Export::Function(func));
finished_functions.push(spectest_print_i64 as *const VMFunctionBody);
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::F32)],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print_f32".to_owned(), Export::Function(func));
finished_functions.push(spectest_print_f32 as *const VMFunctionBody);
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::F64)],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print_f64".to_owned(), Export::Function(func));
finished_functions.push(spectest_print_f64 as *const VMFunctionBody);
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::I32), ir::AbiParam::new(types::F32)],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print_i32_f32".to_owned(), Export::Function(func));
finished_functions.push(spectest_print_i32_f32 as *const VMFunctionBody);
let sig = module.signatures.push(translate_signature(
ir::Signature {
params: vec![ir::AbiParam::new(types::F64), ir::AbiParam::new(types::F64)],
returns: vec![],
call_conv,
},
pointer_type,
));
let func = module.functions.push(sig);
module
.exports
.insert("print_f64_f64".to_owned(), Export::Function(func));
finished_functions.push(spectest_print_f64_f64 as *const VMFunctionBody);
let global = module.globals.push(Global {
ty: types::I32,
mutability: false,
initializer: GlobalInit::I32Const(666),
});
module
.exports
.insert("global_i32".to_owned(), Export::Global(global));
let global = module.globals.push(Global {
ty: types::I64,
mutability: false,
initializer: GlobalInit::I64Const(666),
});
module
.exports
.insert("global_i64".to_owned(), Export::Global(global));
let global = module.globals.push(Global {
ty: types::F32,
mutability: false,
initializer: GlobalInit::F32Const(0x44268000),
});
module
.exports
.insert("global_f32".to_owned(), Export::Global(global));
let global = module.globals.push(Global {
ty: types::F64,
mutability: false,
initializer: GlobalInit::F64Const(0x4084d00000000000),
});
module
.exports
.insert("global_f64".to_owned(), Export::Global(global));
let table = module.table_plans.push(TablePlan {
table: Table {
ty: TableElementType::Func,
minimum: 10,
maximum: Some(20),
},
style: TableStyle::CallerChecksSignature,
});
module
.exports
.insert("table".to_owned(), Export::Table(table));
let memory = module.memory_plans.push(MemoryPlan {
memory: Memory {
minimum: 1,
maximum: Some(2),
shared: false,
},
style: MemoryStyle::Static { bound: 65536 },
offset_guard_size: 0x80000000,
});
module
.exports
.insert("memory".to_owned(), Export::Memory(memory));
let imports = Imports::none();
let data_initializers = Vec::new();
InstancePlus::with_parts(
Rc::new(module),
finished_functions.into_boxed_slice(),
imports,
data_initializers,
)
}