diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2024-01-25 13:49:52 +0100 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2024-01-25 13:49:52 +0100 |
| commit | 79463500a7ade3df7dc99454f5797beaf1d7eef9 (patch) | |
| tree | fe6ef0899c070a82fd723a7b78eb0b50878f4fd1 /crates | |
| parent | 00ac90357bbd256436846beceba67b38d4743bf6 (diff) | |
chore: refactor executor and improve documentation
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/parser/src/error.rs | 1 | ||||
| -rw-r--r-- | crates/tinywasm/src/error.rs | 26 | ||||
| -rw-r--r-- | crates/tinywasm/src/func.rs | 4 | ||||
| -rw-r--r-- | crates/tinywasm/src/imports.rs | 109 | ||||
| -rw-r--r-- | crates/tinywasm/src/instance.rs | 8 | ||||
| -rw-r--r-- | crates/tinywasm/src/lib.rs | 40 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/macros.rs (renamed from crates/tinywasm/src/runtime/executor/macros.rs) | 0 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/mod.rs (renamed from crates/tinywasm/src/runtime/executor/mod.rs) | 17 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/traits.rs (renamed from crates/tinywasm/src/runtime/executor/traits.rs) | 0 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/mod.rs | 20 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/call_stack.rs | 7 | ||||
| -rw-r--r-- | crates/tinywasm/src/store.rs | 10 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/mvp.csv | 1 |
13 files changed, 139 insertions, 104 deletions
diff --git a/crates/parser/src/error.rs b/crates/parser/src/error.rs index 714535a..35bad28 100644 --- a/crates/parser/src/error.rs +++ b/crates/parser/src/error.rs @@ -4,6 +4,7 @@ use alloc::string::{String, ToString}; use wasmparser::Encoding; #[derive(Debug)] +/// Errors that can occur when parsing a WebAssembly module pub enum ParseError { InvalidType, UnsupportedSection(String), diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index f9b41be..0344e82 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -3,24 +3,18 @@ use core::fmt::Display; use tinywasm_types::FuncType; #[cfg(feature = "parser")] -use tinywasm_parser::ParseError; +pub use tinywasm_parser::ParseError; -/// A tinywasm error +/// Errors that can occur for TinyWasm operations #[derive(Debug)] pub enum Error { - #[cfg(feature = "parser")] - /// A parsing error occurred - ParseError(ParseError), - #[cfg(feature = "std")] /// An I/O error occurred Io(crate::std::io::Error), - /// A WebAssembly feature is not supported - UnsupportedFeature(String), - - /// An unknown error occurred - Other(String), + #[cfg(feature = "parser")] + /// A parsing error occurred + ParseError(ParseError), /// A WebAssembly trap occurred Trap(Trap), @@ -28,6 +22,12 @@ pub enum Error { /// A linking error occurred Linker(LinkingError), + /// A WebAssembly feature is not supported + UnsupportedFeature(String), + + /// An unknown error occurred + Other(String), + /// A function did not return a value FuncDidNotReturn, @@ -48,7 +48,7 @@ pub enum Error { } #[derive(Debug)] -/// A linking error +/// Errors that can occur when linking a WebAssembly module pub enum LinkingError { /// An unknown import was encountered UnknownImport { @@ -210,5 +210,5 @@ impl From<tinywasm_parser::ParseError> for Error { } } -/// A specialized [`Result`] type for tinywasm operations +/// A wrapper around [`core::result::Result`] for tinywasm operations pub type Result<T, E = Error> = crate::std::result::Result<T, E>; diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 19d1325..7a29e18 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -89,7 +89,7 @@ impl FuncHandle { #[derive(Debug)] /// A typed function handle -pub struct TypedFuncHandle<P, R> { +pub struct FuncHandleTyped<P, R> { /// The underlying function handle pub func: FuncHandle, pub(crate) marker: core::marker::PhantomData<(P, R)>, @@ -105,7 +105,7 @@ pub trait FromWasmValueTuple { Self: Sized; } -impl<P: IntoWasmValueTuple, R: FromWasmValueTuple> TypedFuncHandle<P, R> { +impl<P: IntoWasmValueTuple, R: FromWasmValueTuple> FuncHandleTyped<P, R> { /// Call a typed function pub fn call(&self, store: &mut Store, params: P) -> Result<R> { // Convert params into Vec<WasmValue> diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 804aa12..0720d02 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -90,56 +90,45 @@ impl Debug for HostFunction { /// An external value pub enum Extern { /// A global value - Global(ExternGlobal), + Global { + /// The type of the global value. + ty: GlobalType, + /// The actual value of the global, encapsulated in `WasmValue`. + val: WasmValue, + }, /// A table - Table(ExternTable), + Table { + /// Defines the type of the table, including its element type and limits. + ty: TableType, + /// The initial value of the table. + init: WasmValue, + }, /// A memory - Memory(ExternMemory), + Memory { + /// Defines the type of the memory, including its limits and the type of its pages. + ty: MemoryType, + }, /// A function Function(Function), } -/// A function -#[derive(Debug, Clone)] -pub struct ExternFunc(pub(crate) HostFunction); - -/// A global value -#[derive(Debug, Clone)] -pub struct ExternGlobal { - pub(crate) ty: GlobalType, - pub(crate) val: WasmValue, -} - -/// A table -#[derive(Debug, Clone)] -pub struct ExternTable { - pub(crate) ty: TableType, - pub(crate) val: WasmValue, -} - -/// A memory -#[derive(Debug, Clone)] -pub struct ExternMemory { - pub(crate) ty: MemoryType, -} - impl Extern { /// Create a new global import pub fn global(val: WasmValue, mutable: bool) -> Self { - Self::Global(ExternGlobal { ty: GlobalType { ty: val.val_type(), mutable }, val }) + Self::Global { ty: GlobalType { ty: val.val_type(), mutable }, val } } /// Create a new table import - pub fn table(ty: TableType, val: WasmValue) -> Self { - Self::Table(ExternTable { ty, val }) + pub fn table(ty: TableType, init: WasmValue) -> Self { + Self::Table { ty, init } } /// Create a new memory import pub fn memory(ty: MemoryType) -> Self { - Self::Memory(ExternMemory { ty }) + Self::Memory { ty } } /// Create a new function import @@ -174,10 +163,10 @@ impl Extern { pub(crate) fn kind(&self) -> ExternalKind { match self { - Self::Global(_) => ExternalKind::Global, - Self::Table(_) => ExternalKind::Table, - Self::Memory(_) => ExternalKind::Memory, - Self::Function(_) => ExternalKind::Func, + Self::Global { .. } => ExternalKind::Global, + Self::Table { .. } => ExternalKind::Table, + Self::Memory { .. } => ExternalKind::Memory, + Self::Function { .. } => ExternalKind::Func, } } } @@ -197,6 +186,38 @@ impl From<&Import> for ExternName { #[derive(Debug, Default)] /// Imports for a module instance +/// +/// This is used to link a module instance to its imports +/// +/// ## Example +/// ```rust +/// # fn main() -> tinywasm::Result<()> { +/// use tinywasm::{Imports, Extern}; +/// use tinywasm::types::{ValType, TableType, MemoryType, WasmValue}; +/// let mut imports = Imports::new(); +/// +/// // function args can be either a single +/// // value that implements `TryFrom<WasmValue>` or a tuple of them +/// let print_i32 = Extern::typed_func(|_ctx: tinywasm::FuncContext<'_>, arg: i32| { +/// log::debug!("print_i32: {}", arg); +/// Ok(()) +/// }); +/// +/// let table_type = TableType::new(ValType::RefFunc, 10, Some(20)); +/// let table_init = WasmValue::default_for(ValType::RefFunc); +/// +/// imports +/// .define("my_module", "print_i32", print_i32)? +/// .define("my_module", "table", Extern::table(table_type, table_init))? +/// .define("my_module", "memory", Extern::memory(MemoryType::new_32(1, Some(2))))? +/// .define("my_module", "global_i32", Extern::global(WasmValue::I32(666), false))? +/// .link_module("my_other_module", 0)?; +/// # Ok(()) +/// # } +/// ``` +/// +/// Note that module instance addresses for [`Imports::link_module`] can be obtained from [`crate::ModuleInstance::id`]. +/// Now, the imports object can be passed to [`crate::ModuleInstance::instantiate`]. pub struct Imports { values: BTreeMap<ExternName, Extern>, modules: BTreeMap<String, ModuleInstanceAddr>, @@ -334,17 +355,17 @@ impl Imports { match val { // A link to something that needs to be added to the store ResolvedExtern::Extern(ex) => match (ex, &import.kind) { - (Extern::Global(extern_global), ImportKind::Global(ty)) => { - Self::compare_types(import, &extern_global.ty, ty)?; - imports.globals.push(store.add_global(extern_global.ty, extern_global.val.into(), idx)?); + (Extern::Global { ty, val }, ImportKind::Global(import_ty)) => { + Self::compare_types(import, &ty, import_ty)?; + imports.globals.push(store.add_global(ty, val.into(), idx)?); } - (Extern::Table(extern_table), ImportKind::Table(ty)) => { - Self::compare_table_types(import, &extern_table.ty, ty)?; - imports.tables.push(store.add_table(extern_table.ty, idx)?); + (Extern::Table { ty, .. }, ImportKind::Table(import_ty)) => { + Self::compare_table_types(import, &ty, import_ty)?; + imports.tables.push(store.add_table(ty, idx)?); } - (Extern::Memory(extern_memory), ImportKind::Memory(ty)) => { - Self::compare_memory_types(import, &extern_memory.ty, ty, None)?; - imports.memories.push(store.add_mem(extern_memory.ty, idx)?); + (Extern::Memory { ty }, ImportKind::Memory(import_ty)) => { + Self::compare_memory_types(import, &ty, import_ty, None)?; + imports.memories.push(store.add_mem(ty, idx)?); } (Extern::Function(extern_func), ImportKind::Function(ty)) => { let import_func_type = module diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index d1fbd6f..75d1f87 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -6,10 +6,10 @@ use tinywasm_types::{ use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple}, - Error, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle, + Error, FuncHandle, FuncHandleTyped, Imports, Module, Result, Store, }; -/// A WebAssembly Module Instance +/// An instanciated WebAssembly module /// /// Backed by an Arc, so cloning is cheap /// @@ -178,13 +178,13 @@ impl ModuleInstance { } /// Get a typed exported function by name - pub fn typed_func<P, R>(&self, store: &Store, name: &str) -> Result<TypedFuncHandle<P, R>> + pub fn typed_func<P, R>(&self, store: &Store, name: &str) -> Result<FuncHandleTyped<P, R>> where P: IntoWasmValueTuple, R: FromWasmValueTuple, { let func = self.exported_func_by_name(store, name)?; - Ok(TypedFuncHandle { func, marker: core::marker::PhantomData }) + Ok(FuncHandleTyped { func, marker: core::marker::PhantomData }) } /// Get the start function of the module diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 64d34df..1b63b99 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -14,12 +14,23 @@ //! to be useful for embedded systems and other environments where a full-featured //! runtime is not required. //! -//! ## Getting Started +//! ## Features +//! - `std` (default): Enables the use of `std` and `std::io` for parsing from files and streams. +//! - `logging` (default): Enables logging via the `log` crate. +//! - `parser` (default): Enables the `tinywasm_parser` crate for parsing WebAssembly modules. +//! +//! ## No-std support +//! TinyWasm supports `no_std` environments by disabling the `std` feature and registering +//! a custom allocator. This removes support for parsing from files and streams, +//! but otherwise the API is the same. +//! Additionally, to have proper error types, you currently need a `nightly` compiler to have the error trait in core. //! +//! ## Getting Started //! The easiest way to get started is to use the [`Module::parse_bytes`] function to load a //! WebAssembly module from bytes. This will parse the module and validate it, returning //! a [`Module`] that can be used to instantiate the module. //! +//! //! ```rust //! use tinywasm::{Store, Module}; //! @@ -39,25 +50,21 @@ //! //! // Get a typed handle to the exported "add" function //! // Alternatively, you can use `instance.get_func` to get an untyped handle -//! // that takes and returns WasmValue types -//! let func = instance.typed_func::<(i32, i32), (i32,)>(&mut store, "add")?; +//! // that takes and returns [`WasmValue`]s +//! let func = instance.typed_func::<(i32, i32), i32>(&mut store, "add")?; //! let res = func.call(&mut store, (1, 2))?; //! -//! assert_eq!(res, (3,)); +//! assert_eq!(res, 3); //! # Ok::<(), tinywasm::Error>(()) //! ``` //! -//! ## Features -//! - `std` (default): Enables the use of `std` and `std::io` for parsing from files and streams. -//! - `logging` (default): Enables logging via the `log` crate. -//! - `parser` (default): Enables the `tinywasm_parser` crate for parsing WebAssembly modules. +//! ## Custom Imports //! -//! ## No-std support -//! TinyWasm supports `no_std` environments by disabling the `std` feature and registering -//! a custom allocator. This removes support for parsing from files and streams, -//! but otherwise the API is the same. +//! To provide custom imports to a module, you can use the [`Imports`] struct. +//! This struct allows you to register custom functions, globals, memories, tables, +//! and other modules to be linked into the module when it is instantiated. //! -//! Additionally, if you want proper error types, you must use a `nightly` compiler to have the error trait in core. +//! See the [`Imports`] documentation for more information. mod std; extern crate alloc; @@ -87,13 +94,14 @@ mod instance; pub use instance::ModuleInstance; mod func; -pub use func::{FuncHandle, TypedFuncHandle}; +pub use func::{FuncHandle, FuncHandleTyped}; mod imports; pub use imports::*; -mod runtime; -pub use runtime::*; +/// Runtime for executing WebAssembly modules. +pub mod runtime; +pub use runtime::InterpreterRuntime; #[cfg(feature = "parser")] /// Re-export of [`tinywasm_parser`]. Requires `parser` feature. diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/interpreter/macros.rs index 909acb3..909acb3 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/interpreter/macros.rs diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs index d0f011f..48ce21d 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/interpreter/mod.rs @@ -1,10 +1,10 @@ use core::ops::{BitAnd, BitOr, BitXor, Neg}; -use super::{DefaultRuntime, Stack}; +use super::{InterpreterRuntime, Stack}; use crate::{ log::debug, - runtime::{BlockType, LabelFrame}, - CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, + runtime::{BlockType, CallFrame, LabelArgs, LabelFrame}, + Error, FuncContext, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; use tinywasm_types::{ElementKind, Instruction, ValType}; @@ -14,7 +14,7 @@ mod traits; use macros::*; use traits::*; -impl DefaultRuntime { +impl InterpreterRuntime { pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack) -> Result<()> { // The current call frame, gets updated inside of exec_one let mut cf = stack.call_stack.pop()?; @@ -246,7 +246,7 @@ fn exec_one( instr_ptr: cf.instr_ptr + *else_offset, end_instr_ptr: cf.instr_ptr + *end_offset, stack_ptr: stack.values.len(), // - params, - args: crate::LabelArgs::new(*args, module)?, + args: LabelArgs::new(*args, module)?, ty: BlockType::Else, }, &mut stack.values, @@ -302,11 +302,8 @@ fn exec_one( } let idx = stack.values.pop_t::<i32>()? as usize; - if let Some(label) = instr.get(idx) { - break_to!(cf, stack, label); - } else { - break_to!(cf, stack, default); - } + let to = instr.get(idx).unwrap_or(default); + break_to!(cf, stack, to); } Br(v) => break_to!(cf, stack, v), diff --git a/crates/tinywasm/src/runtime/executor/traits.rs b/crates/tinywasm/src/runtime/interpreter/traits.rs index 06aab2a..06aab2a 100644 --- a/crates/tinywasm/src/runtime/executor/traits.rs +++ b/crates/tinywasm/src/runtime/interpreter/traits.rs diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs index 610810f..3b9a57c 100644 --- a/crates/tinywasm/src/runtime/mod.rs +++ b/crates/tinywasm/src/runtime/mod.rs @@ -1,19 +1,23 @@ -mod executor; +mod interpreter; mod stack; mod value; pub use stack::*; pub(crate) use value::RawWasmValue; +use crate::Result; + #[allow(rustdoc::private_intra_doc_links)] -/// A WebAssembly Runtime. -/// -/// Generic over `CheckTypes` to enable type checking at runtime. -/// This is useful for debugging, but should be disabled if you know -/// that the module is valid. +/// A WebAssembly runtime. /// /// See <https://webassembly.github.io/spec/core/exec/runtime.html> +pub trait Runtime { + /// Execute all call-frames on the stack until the stack is empty. + fn exec(&self, store: &mut crate::Store, stack: &mut crate::runtime::Stack) -> Result<()>; +} + +/// The main TinyWasm runtime. /// -/// Execution is implemented in the [`crate::runtime::executor`] module +/// This is the default runtime used by TinyWasm. #[derive(Debug, Default)] -pub struct DefaultRuntime {} +pub struct InterpreterRuntime {} diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 1bcd474..098b918 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,8 +1,11 @@ -use crate::{runtime::RawWasmValue, BlockType, Error, FunctionInstance, LabelFrame, Result, Trap}; +use crate::{ + runtime::{BlockType, RawWasmValue}, + Error, FunctionInstance, Result, Trap, +}; use alloc::{boxed::Box, rc::Rc, vec::Vec}; use tinywasm_types::{ValType, WasmValue}; -use super::blocks::Labels; +use super::{blocks::Labels, LabelFrame}; // minimum call stack size const CALL_STACK_SIZE: usize = 128; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index aabbf71..4d3e326 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -7,8 +7,8 @@ use alloc::{boxed::Box, format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::*; use crate::{ - runtime::{self, DefaultRuntime}, - Error, Function, ModuleInstance, RawWasmValue, Result, Trap, + runtime::{self, InterpreterRuntime, RawWasmValue}, + Error, Function, ModuleInstance, Result, Trap, }; // global store id counter @@ -51,9 +51,9 @@ impl Store { } /// Create a new store with the given runtime - pub(crate) fn runtime(&self) -> runtime::DefaultRuntime { + pub(crate) fn runtime(&self) -> runtime::InterpreterRuntime { match self.runtime { - Runtime::Default => DefaultRuntime::default(), + Runtime::Default => InterpreterRuntime::default(), } } } @@ -441,7 +441,7 @@ impl Store { /// A WebAssembly Function Instance /// /// See <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances> -pub struct FunctionInstance { +pub(crate) struct FunctionInstance { pub(crate) func: Function, pub(crate) _type_idx: TypeAddr, pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 23c080d..03241b3 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,3 +3,4 @@ 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.3.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] |
