Files
wasmtime/crates/wast/src/spectest.rs
Alex Crichton 0bee67a852 Document and update the API of the externals.rs module (#812)
* Document and update the API of the `externals.rs` module

This commit ensures that all public methods and items are documented in
the `externals.rs` module, notably all external values that can be
imported and exported in WebAssembly. Along the way this also tidies up
the API and fixes a few bugs:

* `Global::new` now returns a `Result` and fails if the provided value
  does not match the type of the global.
* `Global::set` now returns a `Result` and fails if the global is either
  immutable or the provided value doesn't match the type of the global.
* `Table::new` now fails if the provided initializer does not match the
  element type.
* `Table::get` now returns `Option<Val>` instead of implicitly returning
  null.
* `Table::set` now returns `Result<()>`, returning an error on out of
  bounds or if the input type is of the wrong type.
* `Table::grow` now returns `Result<u32>`, returning the previous number
  of table elements if succesful or an error if the maximum is reached
  or the initializer value is of the wrong type. Additionally a bug was
  fixed here where if the wrong initializer was provided the table would
  be grown still, but initialization would fail.
* `Memory::data` was renamed to `Memory::data_unchecked_mut`.
  Additionally `Memory::data_unchecked` was added. Lots of caveats were
  written down about how using the method can go wrong.
* `Memory::grow` now returns `Result<u32>`, returning an error if growth
  fails or the number of pages previous the growth if successful.

* Run rustfmt

* Fix another test

* Update crates/api/src/externals.rs

Co-Authored-By: Sergei Pepyakin <s.pepyakin@gmail.com>

Co-authored-by: Sergei Pepyakin <s.pepyakin@gmail.com>
2020-01-17 09:43:35 -06:00

104 lines
3.5 KiB
Rust

use anyhow::Result;
use std::collections::HashMap;
use std::rc::Rc;
use wasmtime::*;
struct MyCall<F>(F);
impl<F> Callable for MyCall<F>
where
F: Fn(&[Val], &mut [Val]) -> Result<(), Trap>,
{
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
(self.0)(params, results)
}
}
fn wrap(
store: &Store,
ty: FuncType,
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), Trap> + 'static,
) -> Func {
Func::new(store, ty, Rc::new(MyCall(callable)))
}
/// Return an instance implementing the "spectest" interface used in the
/// spec testsuite.
pub fn instantiate_spectest(store: &Store) -> HashMap<&'static str, Extern> {
let mut ret = HashMap::new();
let ty = FuncType::new(Box::new([]), Box::new([]));
let func = wrap(store, ty, |_params, _results| Ok(()));
ret.insert("print", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::I32]), Box::new([]));
let func = wrap(store, ty, |params, _results| {
println!("{}: i32", params[0].unwrap_i32());
Ok(())
});
ret.insert("print_i32", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::I64]), Box::new([]));
let func = wrap(store, ty, |params, _results| {
println!("{}: i64", params[0].unwrap_i64());
Ok(())
});
ret.insert("print_i64", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::F32]), Box::new([]));
let func = wrap(store, ty, |params, _results| {
println!("{}: f32", params[0].unwrap_f32());
Ok(())
});
ret.insert("print_f32", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::F64]), Box::new([]));
let func = wrap(store, ty, |params, _results| {
println!("{}: f64", params[0].unwrap_f64());
Ok(())
});
ret.insert("print_f64", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::I32, ValType::F32]), Box::new([]));
let func = wrap(store, ty, |params, _results| {
println!("{}: i32", params[0].unwrap_i32());
println!("{}: f32", params[1].unwrap_f32());
Ok(())
});
ret.insert("print_i32_f32", Extern::Func(func));
let ty = FuncType::new(Box::new([ValType::F64, ValType::F64]), Box::new([]));
let func = wrap(store, ty, |params, _results| {
println!("{}: f64", params[0].unwrap_f64());
println!("{}: f64", params[1].unwrap_f64());
Ok(())
});
ret.insert("print_f64_f64", Extern::Func(func));
let ty = GlobalType::new(ValType::I32, Mutability::Const);
let g = Global::new(store, ty, Val::I32(666)).unwrap();
ret.insert("global_i32", Extern::Global(g));
let ty = GlobalType::new(ValType::I64, Mutability::Const);
let g = Global::new(store, ty, Val::I64(666)).unwrap();
ret.insert("global_i64", Extern::Global(g));
let ty = GlobalType::new(ValType::F32, Mutability::Const);
let g = Global::new(store, ty, Val::F32(0x4426_8000)).unwrap();
ret.insert("global_f32", Extern::Global(g));
let ty = GlobalType::new(ValType::F64, Mutability::Const);
let g = Global::new(store, ty, Val::F64(0x4084_d000_0000_0000)).unwrap();
ret.insert("global_f64", Extern::Global(g));
let ty = TableType::new(ValType::FuncRef, Limits::new(10, Some(20)));
let table = Table::new(store, ty, Val::AnyRef(AnyRef::Null)).unwrap();
ret.insert("table", Extern::Table(table));
let ty = MemoryType::new(Limits::new(1, Some(2)));
let memory = Memory::new(store, ty);
ret.insert("memory", Extern::Memory(memory));
return ret;
}