From 29018ba694ef866cc06e0156acbe320226c5d10a Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sun, 7 Jan 2024 22:08:20 +0100 Subject: chore: progress towards linking modules Signed-off-by: Henry Gressmann --- crates/tinywasm/src/imports.rs | 35 +++++++++--- crates/tinywasm/src/instance.rs | 11 ++-- crates/tinywasm/src/runtime/executor/macros.rs | 3 ++ crates/tinywasm/src/runtime/executor/mod.rs | 5 +- crates/tinywasm/src/runtime/stack.rs | 4 -- crates/tinywasm/src/store.rs | 69 +++++++++++++++--------- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/generated/progress-mvp.svg | 8 +-- crates/tinywasm/tests/testsuite/run.rs | 39 ++++++++++---- 9 files changed, 119 insertions(+), 57 deletions(-) (limited to 'crates') diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 99ebc4b..37fb60e 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -3,7 +3,7 @@ use alloc::{ collections::BTreeMap, string::{String, ToString}, }; -use tinywasm_types::{Global, GlobalType, WasmValue}; +use tinywasm_types::{Global, GlobalType, ModuleInstanceAddr, WasmValue}; #[derive(Debug)] #[non_exhaustive] @@ -11,6 +11,8 @@ use tinywasm_types::{Global, GlobalType, WasmValue}; pub enum Extern { /// A global value Global(Global), + /// A registered module + Module(String), // Func(HostFunc), // Table(Table), } @@ -39,6 +41,20 @@ pub struct ExternName { /// Imports for a module instance pub struct Imports { values: BTreeMap, + modules: BTreeMap, +} + +pub(crate) struct LinkedImports { + pub(crate) values: BTreeMap, +} + +impl LinkedImports { + pub(crate) fn get(&self, module: &str, name: &str) -> Option<&Extern> { + self.values.get(&ExternName { + module: module.to_string(), + name: name.to_string(), + }) + } } impl Imports { @@ -46,9 +62,18 @@ impl Imports { pub fn new() -> Self { Imports { values: BTreeMap::new(), + modules: BTreeMap::new(), } } + /// Link a module + /// + /// This will automatically link all imported values + pub fn link_module(&mut self, name: &str, addr: ModuleInstanceAddr) -> Result<&mut Self> { + self.modules.insert(name.to_string(), addr); + Ok(self) + } + /// Define an import pub fn define(&mut self, module: &str, name: &str, value: Extern) -> Result<&mut Self> { self.values.insert( @@ -61,10 +86,8 @@ impl Imports { Ok(self) } - pub(crate) fn get(&self, module: &str, name: &str) -> Option<&Extern> { - self.values.get(&ExternName { - module: module.to_string(), - name: name.to_string(), - }) + pub(crate) fn link(self, store: &mut crate::Store, module: &crate::Module) -> Result { + let values = self.values; + Ok(LinkedImports { values }) } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 7415d85..0ef63a9 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -36,17 +36,22 @@ pub(crate) struct ModuleInstanceInner { } impl ModuleInstance { + /// Get the module instance's address + pub fn id(&self) -> ModuleInstanceAddr { + self.0.idx + } + /// Instantiate the module in the given store pub fn instantiate(store: &mut Store, module: Module, imports: Option) -> Result { let idx = store.next_module_instance_idx(); let imports = imports.unwrap_or_default(); + let linked_imports = imports.link(store, &module)?; let func_addrs = store.add_funcs(module.data.funcs.into(), idx); let table_addrs = store.add_tables(module.data.table_types.into(), idx); let mem_addrs = store.add_mems(module.data.memory_types.into(), idx)?; - - let global_addrs = store.add_globals(module.data.globals.into(), &module.data.imports, &imports, idx)?; - let elem_addrs = store.add_elems(module.data.elements.into(), idx); + let global_addrs = store.add_globals(module.data.globals.into(), &module.data.imports, &linked_imports, idx)?; + let elem_addrs = store.add_elems(module.data.elements.into(), idx)?; let data_addrs = store.add_datas(module.data.data.into(), idx); let instance = ModuleInstanceInner { diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index 5942f60..08e2149 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -1,6 +1,8 @@ //! More generic macros for various instructions //! //! These macros are used to generate the actual instruction implementations. +//! In some basic tests this generated better assembly than using generic functions, even when inlined. +//! (Something to revisit in the future) /// Load a value from memory macro_rules! mem_load { @@ -37,6 +39,7 @@ macro_rules! mem_store { }}; ($store_type:ty, $target_type:ty, $arg:ident, $stack:ident, $store:ident, $module:ident) => {{ + // likewise, there could be a lot of performance improvements here let mem_idx = $module.resolve_mem_addr($arg.mem_addr); let mem = $store.get_mem(mem_idx as usize)?; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 22cb204..d7d8fc7 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -164,10 +164,6 @@ fn exec_one( } } - // Else(_end_offset) => { - // // end the if block - // cf.break_to(0, &mut stack.values)?; - // } Loop(args, end_offset) => { // let params = stack.values.pop_block_params(*args, &module)?; cf.enter_label( @@ -240,6 +236,7 @@ fn exec_one( } } + // We're essentially using else as a EndBlockFrame instruction Else(end_offset) => { let Some(block) = cf.labels.pop() else { panic!("else: no label to end, this should have been validated by the parser"); diff --git a/crates/tinywasm/src/runtime/stack.rs b/crates/tinywasm/src/runtime/stack.rs index a7074ad..07d9316 100644 --- a/crates/tinywasm/src/runtime/stack.rs +++ b/crates/tinywasm/src/runtime/stack.rs @@ -9,10 +9,6 @@ pub(crate) use call_stack::CallFrame; /// A WebAssembly Stack #[derive(Debug, Default)] pub struct Stack { - // keeping this typed for now to make it easier to debug - // TODO: Maybe split into Vec and Vec for better memory usage? pub(crate) values: ValueStack, - - /// The call stack pub(crate) call_stack: CallStack, } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 289b5b6..a50e8b2 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -13,7 +13,7 @@ use tinywasm_types::{ use crate::{ runtime::{self, DefaultRuntime}, - Error, Extern, Imports, ModuleInstance, RawWasmValue, Result, + Error, Extern, LinkedImports, ModuleInstance, RawWasmValue, Result, }; // global store id counter @@ -153,7 +153,7 @@ impl Store { &mut self, globals: Vec, wasm_imports: &[Import], - user_imports: &Imports, + user_imports: &LinkedImports, idx: ModuleInstanceAddr, ) -> Result> { // TODO: initialize imported globals @@ -191,41 +191,58 @@ impl Store { let iterator = imported_globals.into_iter().chain(globals.as_ref()); for (i, global) in iterator.enumerate() { - use tinywasm_types::ConstInstruction::*; - let val = match global.init { - F32Const(f) => RawWasmValue::from(f), - F64Const(f) => RawWasmValue::from(f), - I32Const(i) => RawWasmValue::from(i), - I64Const(i) => RawWasmValue::from(i), - GlobalGet(addr) => { - let addr = global_addrs[addr as usize]; - let global = self.data.globals[addr as usize].clone(); - let val = global.borrow().value; - val - } - RefNull(_) => RawWasmValue::default(), - RefFunc(idx) => RawWasmValue::from(idx as i64), - }; - - self.data - .globals - .push(Rc::new(RefCell::new(GlobalInstance::new(global.ty, val, idx)))); - + self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( + global.ty, + self.eval_const(&global.init)?, + idx, + )))); global_addrs.push((i + global_count) as Addr); } - log::debug!("global_addrs: {:?}", global_addrs); + Ok(global_addrs) } + pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { + use tinywasm_types::ConstInstruction::*; + let val = match const_instr { + F32Const(f) => RawWasmValue::from(*f), + F64Const(f) => RawWasmValue::from(*f), + I32Const(i) => RawWasmValue::from(*i), + I64Const(i) => RawWasmValue::from(*i), + GlobalGet(addr) => { + let addr = *addr as usize; + let global = self.data.globals[addr].clone(); + let val = global.borrow().value; + val + } + RefNull(_) => RawWasmValue::default(), + RefFunc(idx) => RawWasmValue::from(*idx as i64), + }; + Ok(val) + } + /// Add elements to the store, returning their addresses in the store - pub(crate) fn add_elems(&mut self, elems: Vec, idx: ModuleInstanceAddr) -> Vec { + /// Should be called after the tables have been added + pub(crate) fn add_elems(&mut self, elems: Vec, idx: ModuleInstanceAddr) -> Result> { let elem_count = self.data.elems.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, elem) in elems.into_iter().enumerate() { self.data.elems.push(ElemInstance::new(elem.kind, idx)); elem_addrs.push((i + elem_count) as Addr); + + // match elem.kind { + // ElementKind::Active { table, offset } => { + // // let table = self.data.tables[table as usize]; + + // // let offset = self.eval_const(&offset)?; + // // let offset = offset.raw_value() as usize; + // // let offset = offset + elem_addrs[i] as usize; + // // let offset = offset as Addr; + // } + // } } - elem_addrs + + Ok(elem_addrs) } /// Add data to the store, returning their addresses in the store @@ -313,8 +330,8 @@ pub(crate) struct TableInstance { impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { Self { + elements: vec![0; kind.size_initial as usize], kind, - elements: Vec::new(), owner, } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 92002dd..ff3e9cf 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.4,9258,10909,[{"name":"address.wast","passed":0,"failed":54},{"name":"align.wast","passed":0,"failed":109},{"name":"binary-leb128.wast","passed":66,"failed":25},{"name":"binary.wast","passed":104,"failed":8},{"name":"block.wast","passed":0,"failed":171},{"name":"br.wast","passed":0,"failed":21},{"name":"br_if.wast","passed":0,"failed":30},{"name":"br_table.wast","passed":0,"failed":25},{"name":"call.wast","passed":0,"failed":22},{"name":"call_indirect.wast","passed":0,"failed":56},{"name":"comments.wast","passed":4,"failed":4},{"name":"const.wast","passed":702,"failed":76},{"name":"conversions.wast","passed":0,"failed":93},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":0,"failed":61},{"name":"elem.wast","passed":0,"failed":76},{"name":"endianness.wast","passed":0,"failed":1},{"name":"exports.wast","passed":21,"failed":73},{"name":"f32.wast","passed":1005,"failed":1509},{"name":"f32_bitwise.wast","passed":1,"failed":363},{"name":"f32_cmp.wast","passed":2401,"failed":6},{"name":"f64.wast","passed":1005,"failed":1509},{"name":"f64_bitwise.wast","passed":1,"failed":363},{"name":"f64_cmp.wast","passed":2401,"failed":6},{"name":"fac.wast","passed":0,"failed":2},{"name":"float_exprs.wast","passed":269,"failed":591},{"name":"float_literals.wast","passed":34,"failed":129},{"name":"float_memory.wast","passed":0,"failed":6},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":4,"failed":75},{"name":"func_ptrs.wast","passed":0,"failed":16},{"name":"global.wast","passed":4,"failed":49},{"name":"i32.wast","passed":0,"failed":96},{"name":"i64.wast","passed":0,"failed":42},{"name":"if.wast","passed":0,"failed":118},{"name":"imports.wast","passed":1,"failed":156},{"name":"inline-module.wast","passed":0,"failed":1},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":5,"failed":46},{"name":"labels.wast","passed":1,"failed":28},{"name":"left-to-right.wast","passed":0,"failed":1},{"name":"linking.wast","passed":1,"failed":66},{"name":"load.wast","passed":0,"failed":60},{"name":"local_get.wast","passed":2,"failed":34},{"name":"local_set.wast","passed":5,"failed":48},{"name":"local_tee.wast","passed":0,"failed":42},{"name":"loop.wast","passed":0,"failed":43},{"name":"memory.wast","passed":0,"failed":34},{"name":"memory_grow.wast","passed":0,"failed":19},{"name":"memory_redundancy.wast","passed":0,"failed":1},{"name":"memory_size.wast","passed":0,"failed":6},{"name":"memory_trap.wast","passed":0,"failed":172},{"name":"names.wast","passed":484,"failed":1},{"name":"nop.wast","passed":0,"failed":5},{"name":"return.wast","passed":0,"failed":21},{"name":"select.wast","passed":0,"failed":32},{"name":"skip-stack-guard-page.wast","passed":0,"failed":11},{"name":"stack.wast","passed":0,"failed":2},{"name":"start.wast","passed":0,"failed":10},{"name":"store.wast","passed":0,"failed":59},{"name":"switch.wast","passed":1,"failed":27},{"name":"token.wast","passed":16,"failed":42},{"name":"traps.wast","passed":3,"failed":33},{"name":"type.wast","passed":1,"failed":2},{"name":"unreachable.wast","passed":0,"failed":59},{"name":"unreached-invalid.wast","passed":0,"failed":118},{"name":"unwind.wast","passed":1,"failed":49},{"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":0,"failed":176}] 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"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.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-alpha.0,18642,1586,[{"name":"address.wast","passed":13,"failed":247},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":217,"failed":6},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":115,"failed":3},{"name":"br_table.wast","passed":27,"failed":147},{"name":"call.wast","passed":71,"failed":20},{"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":54,"failed":45},{"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":132,"failed":40},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":101,"failed":9},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":226,"failed":15},{"name":"imports.wast","passed":76,"failed":107},{"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":17,"failed":12},{"name":"left-to-right.wast","passed":91,"failed":5},{"name":"linking.wast","passed":19,"failed":113},{"name":"load.wast","passed":90,"failed":7},{"name":"local_get.wast","passed":35,"failed":1},{"name":"local_set.wast","passed":52,"failed":1},{"name":"local_tee.wast","passed":90,"failed":7},{"name":"loop.wast","passed":113,"failed":7},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":76,"failed":20},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":3,"failed":179},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":74,"failed":14},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":110,"failed":38},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":13,"failed":7},{"name":"store.wast","passed":67,"failed":1},{"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":64,"failed":0},{"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-alpha.0,18657,1571,[{"name":"address.wast","passed":13,"failed":247},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":217,"failed":6},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":115,"failed":3},{"name":"br_table.wast","passed":27,"failed":147},{"name":"call.wast","passed":71,"failed":20},{"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":132,"failed":40},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":101,"failed":9},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":226,"failed":15},{"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":17,"failed":12},{"name":"left-to-right.wast","passed":91,"failed":5},{"name":"linking.wast","passed":28,"failed":104},{"name":"load.wast","passed":90,"failed":7},{"name":"local_get.wast","passed":35,"failed":1},{"name":"local_set.wast","passed":52,"failed":1},{"name":"local_tee.wast","passed":90,"failed":7},{"name":"loop.wast","passed":113,"failed":7},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":76,"failed":20},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":3,"failed":179},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":74,"failed":14},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":110,"failed":38},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":13,"failed":7},{"name":"store.wast","passed":67,"failed":1},{"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":64,"failed":0},{"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}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 8c00424..caad2bb 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.1.0 (17630) -v0.2.0-alpha.0 (18642) +v0.2.0-alpha.0 (18657) - - - + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index f0f78cd..d34df6c 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -8,7 +8,7 @@ use super::TestSuite; use eyre::{eyre, Result}; use log::{debug, error, info}; use tinywasm::{Extern, Imports, ModuleInstance}; -use tinywasm_types::WasmValue; +use tinywasm_types::{ModuleInstanceAddr, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, Wast}; impl TestSuite { @@ -22,12 +22,18 @@ impl TestSuite { Ok(()) } - fn imports() -> Result { + fn imports(registered_modules: Vec<(String, ModuleInstanceAddr)>) -> Result { let mut imports = Imports::new(); - imports.define("spectest", "global_i32", Extern::global(WasmValue::I32(666), false))?; - imports.define("spectest", "global_i64", Extern::global(WasmValue::I64(666), false))?; - imports.define("spectest", "global_f32", Extern::global(WasmValue::F32(666.0), false))?; - imports.define("spectest", "global_f64", Extern::global(WasmValue::F64(666.0), false))?; + + imports + .define("spectest", "global_i32", Extern::global(WasmValue::I32(666), false))? + .define("spectest", "global_i64", Extern::global(WasmValue::I64(666), false))? + .define("spectest", "global_f32", Extern::global(WasmValue::F32(666.0), false))? + .define("spectest", "global_f64", Extern::global(WasmValue::F64(666.0), false))?; + + for (name, addr) in registered_modules { + imports.link_module(&name, addr)?; + } Ok(imports) } @@ -60,6 +66,7 @@ impl TestSuite { let wast_data = wast::parser::parse::(&buf).expect("failed to parse wat"); let mut store = tinywasm::Store::default(); + let mut registered_modules = Vec::new(); let mut last_module: Option = None; println!("running {} tests for group: {}", wast_data.directives.len(), group_name); @@ -68,14 +75,29 @@ impl TestSuite { use wast::WastDirective::*; match directive { + Register { span, name, .. } => { + let Some(last) = &last_module else { + test_group.add_result( + &format!("Register({})", i), + span.linecol_in(wast), + Err(eyre!("no module to register")), + ); + continue; + }; + + registered_modules.push((name.to_string(), last.id())); + test_group.add_result(&format!("Register({})", i), span.linecol_in(wast), Ok(())); + } + Wat(mut module) => { - debug!("got wat module"); + // TODO: modules are not properly isolated from each other - tests fail because of this otherwise store = tinywasm::Store::default(); + debug!("got wat module"); let result = catch_unwind(AssertUnwindSafe(|| { let m = parse_module_bytes(&module.encode().expect("failed to encode module")) .expect("failed to parse module"); tinywasm::Module::from(m) - .instantiate(&mut store, Some(Self::imports().unwrap())) + .instantiate(&mut store, Some(Self::imports(registered_modules.clone()).unwrap())) .map_err(|e| { println!("failed to instantiate module: {:?}", e); e @@ -210,7 +232,6 @@ impl TestSuite { AssertReturn { span, exec, results } => { info!("AssertReturn: {:?}", exec); - let invoke = match match exec { wast::WastExecute::Wat(_) => Err(eyre!("wat not supported")), wast::WastExecute::Get { module: _, global: _ } => Err(eyre!("get not supported")), -- cgit v1.3.1