Update the *.wast runner to use the wasmtime API (#690)

* Update the `*.wast` runner to use the `wasmtime` API

This commit migrates the `wasmtime-wast` crate, which executes `*.wast`
test suites, to use the `wasmtime` crate exclusively instead of the raw
support provided by the `wasmtime-*` family of crates.

The primary motivation for this change is to use `*.wast` test to test
the support for interface types, but interface types is only being added
in the `wasmtime` crate for now rather than all throughout the core
crates. This means that without this transition it's much more difficult
to write tests for wasm interface types!

A secondary motivation for this is that it's testing the support we
provide to users through the `wasmtime` crate, since that's the
expectation of what most users would use rather than the raw
`wasmtime-*` crates.

* Run rustfmt

* Fix the multi example

* Handle v128 values in the `wasmtime` crate

Ensure that we allocate 128-bit stack slots instead of 64-bit stack
slots.

* Update to master

* Add comment
This commit is contained in:
Alex Crichton
2019-12-17 13:30:50 -06:00
committed by GitHub
parent 4141daae68
commit d5a2eb397c
13 changed files with 368 additions and 478 deletions

View File

@@ -121,7 +121,7 @@ impl WasmtimeFn {
impl WrappedCallable for WasmtimeFn {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
use std::cmp::max;
use std::{mem, ptr};
use std::mem;
let (vmctx, body, signature) = match self.wasmtime_export() {
Export::Function {
@@ -132,21 +132,14 @@ impl WrappedCallable for WasmtimeFn {
_ => panic!("unexpected export type in Callable"),
};
let value_size = mem::size_of::<u64>();
let mut values_vec: Vec<u64> = vec![0; max(params.len(), results.len())];
let value_size = mem::size_of::<u128>();
let mut values_vec = vec![0; max(params.len(), results.len())];
// Store the argument values into `values_vec`.
for (index, arg) in params.iter().enumerate() {
unsafe {
let ptr = values_vec.as_mut_ptr().add(index);
match arg {
Val::I32(x) => ptr::write(ptr as *mut i32, *x),
Val::I64(x) => ptr::write(ptr as *mut i64, *x),
Val::F32(x) => ptr::write(ptr as *mut u32, *x),
Val::F64(x) => ptr::write(ptr as *mut u64, *x),
_ => unimplemented!("WasmtimeFn arg"),
}
arg.write_value_to(ptr);
}
}
@@ -176,13 +169,7 @@ impl WrappedCallable for WasmtimeFn {
unsafe {
let ptr = values_vec.as_ptr().add(index);
results[index] = match abi_param.value_type {
ir::types::I32 => Val::I32(ptr::read(ptr as *const i32)),
ir::types::I64 => Val::I64(ptr::read(ptr as *const i64)),
ir::types::F32 => Val::F32(ptr::read(ptr as *const u32)),
ir::types::F64 => Val::F64(ptr::read(ptr as *const u64)),
other => panic!("unsupported value type {:?}", other),
}
results[index] = Val::read_value_from(ptr, abi_param.value_type);
}
}

View File

@@ -201,14 +201,15 @@ impl Module {
_ => None,
}
}
pub fn validate(_store: &HostRef<Store>, binary: &[u8]) -> Result<()> {
pub fn validate(store: &HostRef<Store>, binary: &[u8]) -> Result<()> {
let features = store.borrow().engine().borrow().config.features.clone();
let config = ValidatingParserConfig {
operator_config: OperatorValidatorConfig {
enable_threads: false,
enable_reference_types: false,
enable_bulk_memory: false,
enable_simd: false,
enable_multi_value: true,
enable_threads: features.threads,
enable_reference_types: features.reference_types,
enable_bulk_memory: features.bulk_memory,
enable_simd: features.simd,
enable_multi_value: features.multi_value,
},
};
validate(binary, Some(config)).map_err(Error::new)

View File

@@ -94,7 +94,7 @@ impl Default for Config {
#[derive(Default)]
pub struct Engine {
config: Config,
pub(crate) config: Config,
}
impl Engine {

View File

@@ -63,7 +63,7 @@ impl Drop for TrampolineState {
}
}
unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, call_id: u32, values_vec: *mut i64) -> u32 {
unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, call_id: u32, values_vec: *mut i128) -> u32 {
let mut instance = InstanceHandle::from_vmctx(vmctx);
let (args, returns_len) = {
@@ -130,7 +130,10 @@ fn make_trampoline(
// Add error/trap return.
stub_sig.returns.push(ir::AbiParam::new(types::I32));
let values_vec_len = 8 * cmp::max(signature.params.len() - 1, signature.returns.len()) as u32;
let value_size = 16;
let values_vec_len = ((value_size as usize)
* cmp::max(signature.params.len() - 1, signature.returns.len()))
as u32;
let mut context = Context::new();
context.func = Function::with_name_signature(ExternalName::user(0, 0), signature.clone());
@@ -139,7 +142,6 @@ fn make_trampoline(
StackSlotKind::ExplicitSlot,
values_vec_len,
));
let value_size = 8;
{
let mut builder = FunctionBuilder::new(&mut context.func, fn_builder_ctx);

View File

@@ -83,22 +83,24 @@ impl Val {
}
}
pub(crate) unsafe fn write_value_to(&self, p: *mut i64) {
pub(crate) unsafe fn write_value_to(&self, p: *mut i128) {
match self {
Val::I32(i) => ptr::write(p as *mut i32, *i),
Val::I64(i) => ptr::write(p as *mut i64, *i),
Val::F32(u) => ptr::write(p as *mut u32, *u),
Val::F64(u) => ptr::write(p as *mut u64, *u),
Val::V128(b) => ptr::write(p as *mut u128, *b),
_ => unimplemented!("Val::write_value_to"),
}
}
pub(crate) unsafe fn read_value_from(p: *const i64, ty: ir::Type) -> Val {
pub(crate) unsafe fn read_value_from(p: *const i128, ty: ir::Type) -> Val {
match ty {
ir::types::I32 => Val::I32(ptr::read(p as *const i32)),
ir::types::I64 => Val::I64(ptr::read(p as *const i64)),
ir::types::F32 => Val::F32(ptr::read(p as *const u32)),
ir::types::F64 => Val::F64(ptr::read(p as *const u64)),
ir::types::I8X16 => Val::V128(ptr::read(p as *const u128)),
_ => unimplemented!("Val::read_value_from"),
}
}