diff --git a/Cargo.lock b/Cargo.lock index 1178a8a..8bdb809 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -674,9 +674,9 @@ dependencies = [ [[package]] name = "wasm-testsuite" -version = "0.4.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea6edc2d1ffad1d673091e3e3e98961e7c1a8c0f24cbf2431fa02d861e071bd" +checksum = "e01c897a970135c086793fa320de6632534ad7b4a519a3ca51c7ef40e6a567d7" dependencies = [ "include_dir", "wast", diff --git a/README.md b/README.md index 6b72448..27eb8f5 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,15 @@ - **Tiny**: TinyWasm is designed to be as small as possible without significantly compromising performance or functionality (< 4000 LLOC). - **Portable**: TinyWasm runs on any platform that Rust can target, including `no_std`, with minimal external dependencies. -- **Safe**: No unsafe code is used in the runtime (`rkyv`, which uses unsafe code, can be used for serialization but is optional). +- **Safe**: No unsafe code is used in the runtime -## Status +## Current Status -TinyWasm passes all WebAssembly MVP tests from the [WebAssembly core testsuite](https://github.com/WebAssembly/testsuite) and is able to run most WebAssembly programs. Additionally, the current 2.0 Draft is mostly supported, with the exception of Fixed-Width SIMD and Memory64/Multiple Memories. See the [Supported Proposals](#supported-proposals) section for more information. +TinyWasm passes all WebAssembly MVP tests from the [WebAssembly core testsuite](https://github.com/WebAssembly/testsuite) and is able to run most WebAssembly programs. Additionally, the current 2.0 WebAssembly is mostly supported, with the exception of the SIMD and Memory64 proposals. See the [Supported Proposals](#supported-proposals) section for more information. + +## Safety + +Safety wise, TinyWasm doesn't use any unsafe code and is designed to be completly memory-safe. Untrusted WebAssembly code should not be able to crash the runtime or access memory outside of its sandbox, however currently there is no protection against infinite loops or excessive memory usage. Unvalidated Wasm and untrusted, precompilled twasm bytecode is safe to run too but can crash the runtime. ## Supported Proposals @@ -38,7 +42,7 @@ TinyWasm passes all WebAssembly MVP tests from the [WebAssembly core testsuite]( | [**Multiple Memories**](https://github.com/WebAssembly/multi-memory/blob/master/proposals/multi-memory/Overview.md) | 🟢 | 0.8.0 | | [**Custom Page Sizes**](https://github.com/WebAssembly/custom-page-sizes/blob/main/proposals/custom-page-sizes/Overview.md) | 🟢 | `next` | | [**Tail Call**](https://github.com/WebAssembly/tail-call/blob/main/proposals/tail-call/Overview.md) | 🟢 | `next` | -| [**Memory64**](https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md) | 🚧 | N/A | +| [**Memory64**](https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md) | 🟢 | `next` | | [**Fixed-Width SIMD**](https://github.com/webassembly/simd) | 🚧 | N/A | ## Usage diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index d004760..9be8233 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -20,7 +20,7 @@ tinywasm-types={version="0.9.0-alpha.0", path="../types", default-features=false libm={version="0.2", default-features=false} [dev-dependencies] -wasm-testsuite={version="0.4.4"} +wasm-testsuite={version="0.5.0"} indexmap="2.7" wast={workspace=true} wat={workspace=true} diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs index c776710..4ba4556 100644 --- a/crates/tinywasm/src/interpreter/executor.rs +++ b/crates/tinywasm/src/interpreter/executor.rs @@ -518,16 +518,31 @@ impl<'store, 'stack> Executor<'store, 'stack> { fn exec_memory_size(&mut self, addr: u32) { let mem = self.store.get_mem(self.module.resolve_mem_addr(addr)); - self.stack.values.push::(mem.page_count as i32); + + match mem.is_64bit() { + true => self.stack.values.push::(mem.page_count as i64), + false => self.stack.values.push::(mem.page_count as i32), + } } fn exec_memory_grow(&mut self, addr: u32) { let mem = self.store.get_mem_mut(self.module.resolve_mem_addr(addr)); - let prev_size = mem.page_count as i32; - let pages_delta = self.stack.values.pop::(); - self.stack.values.push::(match mem.grow(pages_delta) { - Some(_) => prev_size, - None => -1, - }); + let prev_size = mem.page_count; + + let pages_delta = match mem.is_64bit() { + true => self.stack.values.pop::(), + false => self.stack.values.pop::() as i64, + }; + + match ( + mem.is_64bit(), + match mem.grow(pages_delta) { + Some(_) => prev_size as i64, + None => -1_i64, + }, + ) { + (true, size) => self.stack.values.push::(size), + (false, size) => self.stack.values.push::(size as i32), + }; } fn exec_memory_copy(&mut self, from: u32, to: u32) -> Result<()> { @@ -605,14 +620,13 @@ impl<'store, 'stack> Executor<'store, 'stack> { dst as usize, src as usize, size as usize, - )?; + ) } else { // copy between two memories let (table_from, table_to) = self.store.get_tables_mut(self.module.resolve_table_addr(from), self.module.resolve_table_addr(to))?; - table_to.copy_from_slice(dst as usize, table_from.load(src as usize, size as usize)?)?; + table_to.copy_from_slice(dst as usize, table_from.load(src as usize, size as usize)?) } - Ok(()) } fn exec_mem_load, const LOAD_SIZE: usize, TARGET: InternalValue>( @@ -622,11 +636,16 @@ impl<'store, 'stack> Executor<'store, 'stack> { cast: fn(LOAD) -> TARGET, ) -> ControlFlow> { let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr)); - let val = self.stack.values.pop::() as u64; - let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else { + + let addr = match mem.is_64bit() { + true => self.stack.values.pop::() as u64, + false => self.stack.values.pop::() as u32 as u64, + }; + + let Some(Ok(addr)) = offset.checked_add(addr).map(TryInto::try_into) else { cold(); return ControlFlow::Break(Some(Error::Trap(Trap::MemoryOutOfBounds { - offset: val as usize, + offset: addr as usize, len: LOAD_SIZE, max: 0, }))); @@ -644,10 +663,16 @@ impl<'store, 'stack> Executor<'store, 'stack> { let mem = self.store.get_mem_mut(self.module.resolve_mem_addr(mem_addr)); let val = self.stack.values.pop::(); let val = (cast(val)).to_mem_bytes(); - let addr = self.stack.values.pop::() as u64; + + let addr = match mem.is_64bit() { + true => self.stack.values.pop::() as u64, + false => self.stack.values.pop::() as u32 as u64, + }; + if let Err(e) = mem.store((offset + addr) as usize, val.len(), &val) { return ControlFlow::Break(Some(e)); } + ControlFlow::Continue(()) } @@ -707,7 +732,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { return Err(Trap::TableOutOfBounds { offset: 0, len: 0, max: 0 }.into()); }; - table.init(dst, &items[offset as usize..(offset + size) as usize]) + table.init(dst as i64, &items[offset as usize..(offset + size) as usize]) } fn exec_table_grow(&mut self, table_index: u32) -> Result<()> { let table = self.store.get_table_mut(self.module.resolve_table_addr(table_index)); diff --git a/crates/tinywasm/src/reference.rs b/crates/tinywasm/src/reference.rs index e151c87..e32a2f3 100644 --- a/crates/tinywasm/src/reference.rs +++ b/crates/tinywasm/src/reference.rs @@ -54,7 +54,7 @@ impl MemoryRefMut<'_> { } /// Grow the memory by the given number of pages - pub fn grow(&mut self, delta_pages: i32) -> Option { + pub fn grow(&mut self, delta_pages: i64) -> Option { self.0.grow(delta_pages) } diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs index d204c67..53c1133 100644 --- a/crates/tinywasm/src/store/memory.rs +++ b/crates/tinywasm/src/store/memory.rs @@ -1,6 +1,6 @@ use alloc::vec; use alloc::vec::Vec; -use tinywasm_types::{MemoryType, ModuleInstanceAddr}; +use tinywasm_types::{MemoryArch, MemoryType, ModuleInstanceAddr}; use crate::{Error, Result, cold, log}; @@ -28,6 +28,11 @@ impl MemoryInstance { } } + #[inline] + pub(crate) fn is_64bit(&self) -> bool { + matches!(self.kind.arch(), MemoryArch::I64) + } + #[inline(always)] pub(crate) fn len(&self) -> usize { self.data.len() @@ -124,15 +129,13 @@ impl MemoryInstance { } #[inline] - pub(crate) fn grow(&mut self, pages_delta: i32) -> Option { + pub(crate) fn grow(&mut self, pages_delta: i64) -> Option { let current_pages = self.page_count; - let new_pages = current_pages as i64 + pages_delta as i64; - debug_assert!(new_pages <= i32::MAX as i64, "page count should never be greater than i32::MAX"); + let new_pages = current_pages as i64 + pages_delta; if new_pages < 0 || new_pages as usize > self.max_pages() { log::debug!("memory.grow failed: new_pages={}, max_pages={}", new_pages, self.max_pages()); log::debug!("{} {}", self.kind.page_count_max(), self.kind.page_size()); - return None; } @@ -145,7 +148,7 @@ impl MemoryInstance { self.data.reserve_exact(new_size); self.data.resize_with(new_size, Default::default); self.page_count = new_pages as usize; - Some(current_pages as i32) + Some(current_pages as i64) } } @@ -241,14 +244,14 @@ mod memory_instance_tests { fn test_memory_grow() { let mut memory = create_test_memory(); let original_pages = memory.page_count; - assert_eq!(memory.grow(1), Some(original_pages as i32)); + assert_eq!(memory.grow(1), Some(original_pages as i64)); assert_eq!(memory.page_count, original_pages + 1); } #[test] fn test_memory_grow_out_of_bounds() { let mut memory = create_test_memory(); - assert!(memory.grow(memory.kind.max_size() as i32 + 1).is_none()); + assert!(memory.grow(memory.kind.max_size() as i64 + 1).is_none()); } #[test] diff --git a/crates/tinywasm/src/store/mod.rs b/crates/tinywasm/src/store/mod.rs index 5730631..358cbef 100644 --- a/crates/tinywasm/src/store/mod.rs +++ b/crates/tinywasm/src/store/mod.rs @@ -243,9 +243,6 @@ impl Store { let mem_count = self.data.memories.len(); let mut mem_addrs = Vec::with_capacity(mem_count); for (i, mem) in memories.into_iter().enumerate() { - if let MemoryArch::I64 = mem.arch() { - return Err(Error::UnsupportedFeature("64-bit memories".to_string())); - } self.data.memories.push(MemoryInstance::new(mem, idx)); mem_addrs.push((i + mem_count) as MemAddr); } @@ -325,7 +322,7 @@ impl Store { // this one is active, so we need to initialize it (essentially a `table.init` instruction) ElementKind::Active { offset, table } => { - let offset = self.eval_i32_const(offset)?; + let offset = self.eval_size_const(offset)?; let table_addr = table_addrs .get(table as usize) .copied() @@ -373,7 +370,7 @@ impl Store { return Err(Error::Other(format!("memory {mem_addr} not found for data segment {i}"))); }; - let offset = self.eval_i32_const(offset)?; + let offset = self.eval_size_const(offset)?; let Some(mem) = self.data.memories.get_mut(*mem_addr as usize) else { return Err(Error::Other(format!("memory {mem_addr} not found for data segment {i}"))); }; @@ -418,15 +415,18 @@ impl Store { Ok(self.data.funcs.len() as FuncAddr - 1) } - /// Evaluate a constant expression, only supporting i32 globals and i32.const - pub(crate) fn eval_i32_const(&self, const_instr: tinywasm_types::ConstInstruction) -> Result { - use tinywasm_types::ConstInstruction::*; - let val = match const_instr { - I32Const(i) => i, - GlobalGet(addr) => self.data.globals[addr as usize].value.get().unwrap_32() as i32, - _ => return Err(Error::Other("expected i32".to_string())), - }; - Ok(val) + /// Evaluate a constant expression that's either a i32 or a i64 as a global or a const instruction + pub(crate) fn eval_size_const(&self, const_instr: tinywasm_types::ConstInstruction) -> Result { + Ok(match const_instr { + ConstInstruction::I32Const(i) => i as i64, + ConstInstruction::I64Const(i) => i, + ConstInstruction::GlobalGet(addr) => match self.data.globals[addr as usize].value.get() { + TinyWasmValue::Value32(i) => i as i64, + TinyWasmValue::Value64(i) => i as i64, + o => return Err(Error::Other(format!("expected i32 or i64, got {o:?}"))), + }, + o => return Err(Error::Other(format!("expected i32, got {o:?}"))), + }) } /// Evaluate a constant expression diff --git a/crates/tinywasm/src/store/table.rs b/crates/tinywasm/src/store/table.rs index 0cbd054..f83de9b 100644 --- a/crates/tinywasm/src/store/table.rs +++ b/crates/tinywasm/src/store/table.rs @@ -134,7 +134,7 @@ impl TableInstance { .expect("error initializing table: function not found. This should have been caught by the validator") } - pub(crate) fn init(&mut self, offset: i32, init: &[TableElement]) -> Result<()> { + pub(crate) fn init(&mut self, offset: i64, init: &[TableElement]) -> Result<()> { let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or({ Error::Trap(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }) diff --git a/crates/tinywasm/tests/generated/wasm-3.csv b/crates/tinywasm/tests/generated/wasm-3.csv index a1df609..5d4d068 100644 --- a/crates/tinywasm/tests/generated/wasm-3.csv +++ b/crates/tinywasm/tests/generated/wasm-3.csv @@ -1 +1 @@ -0.9.0-alpha.0,32377,2526,[{"name":"address.wast","passed":260,"failed":0},{"name":"address64.wast","passed":0,"failed":242},{"name":"align.wast","passed":161,"failed":0},{"name":"align64.wast","passed":83,"failed":73},{"name":"annotations.wast","passed":74,"failed":0},{"name":"binary-leb128.wast","passed":92,"failed":1},{"name":"binary.wast","passed":126,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":119,"failed":0},{"name":"br_on_non_null.wast","passed":1,"failed":9},{"name":"br_on_null.wast","passed":1,"failed":9},{"name":"br_table.wast","passed":24,"failed":162},{"name":"bulk.wast","passed":117,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":49,"failed":124},{"name":"call_ref.wast","passed":4,"failed":31},{"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":59,"failed":6},{"name":"elem.wast","passed":137,"failed":14},{"name":"endianness.wast","passed":69,"failed":0},{"name":"endianness64.wast","passed":0,"failed":69},{"name":"exports.wast","passed":97,"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":927,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_memory64.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":471,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":175,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":53,"failed":71},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"id.wast","passed":7,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":169,"failed":90},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"instance.wast","passed":0,"failed":23},{"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":142,"failed":21},{"name":"load.wast","passed":118,"failed":0},{"name":"load64.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_init.wast","passed":10,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":98,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":89,"failed":1},{"name":"memory64.wast","passed":14,"failed":55},{"name":"memory_copy.wast","passed":8385,"failed":515},{"name":"memory_fill.wast","passed":164,"failed":36},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_grow64.wast","passed":0,"failed":49},{"name":"memory_init.wast","passed":307,"failed":173},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_redundancy64.wast","passed":0,"failed":8},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"memory_trap64.wast","passed":0,"failed":172},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"obsolete-keywords.wast","passed":11,"failed":0},{"name":"ref.wast","passed":12,"failed":1},{"name":"ref_as_non_null.wast","passed":1,"failed":6},{"name":"ref_func.wast","passed":17,"failed":0},{"name":"ref_is_null.wast","passed":2,"failed":20},{"name":"ref_null.wast","passed":0,"failed":34},{"name":"return.wast","passed":84,"failed":0},{"name":"return_call.wast","passed":40,"failed":5},{"name":"return_call_indirect.wast","passed":69,"failed":7},{"name":"return_call_ref.wast","passed":11,"failed":40},{"name":"select.wast","passed":155,"failed":2},{"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":111,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":1},{"name":"table.wast","passed":47,"failed":13},{"name":"table_copy.wast","passed":1742,"failed":30},{"name":"table_copy_mixed.wast","passed":4,"failed":0},{"name":"table_fill.wast","passed":45,"failed":35},{"name":"table_get.wast","passed":16,"failed":1},{"name":"table_grow.wast","passed":58,"failed":21},{"name":"table_init.wast","passed":780,"failed":96},{"name":"table_set.wast","passed":26,"failed":2},{"name":"table_size.wast","passed":39,"failed":1},{"name":"tag.wast","passed":1,"failed":8},{"name":"throw.wast","passed":3,"failed":10},{"name":"throw_ref.wast","passed":2,"failed":13},{"name":"token.wast","passed":61,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"try_table.wast","passed":11,"failed":51},{"name":"type-canon.wast","passed":0,"failed":2},{"name":"type-equivalence.wast","passed":12,"failed":20},{"name":"type-rec.wast","passed":6,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":121,"failed":0},{"name":"unreached-valid.wast","passed":2,"failed":11},{"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.9.0-alpha.0,33714,1189,[{"name":"address.wast","passed":260,"failed":0},{"name":"address64.wast","passed":242,"failed":0},{"name":"align.wast","passed":161,"failed":0},{"name":"align64.wast","passed":156,"failed":0},{"name":"annotations.wast","passed":74,"failed":0},{"name":"binary-leb128.wast","passed":93,"failed":0},{"name":"binary.wast","passed":126,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":119,"failed":0},{"name":"br_on_non_null.wast","passed":1,"failed":9},{"name":"br_on_null.wast","passed":1,"failed":9},{"name":"br_table.wast","passed":24,"failed":162},{"name":"bulk.wast","passed":117,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":172,"failed":1},{"name":"call_ref.wast","passed":4,"failed":31},{"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":59,"failed":6},{"name":"elem.wast","passed":137,"failed":14},{"name":"endianness.wast","passed":69,"failed":0},{"name":"endianness64.wast","passed":69,"failed":0},{"name":"exports.wast","passed":97,"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":927,"failed":0},{"name":"float_literals.wast","passed":179,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_memory64.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":471,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":175,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":53,"failed":71},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"id.wast","passed":7,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":169,"failed":90},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"instance.wast","passed":0,"failed":23},{"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":142,"failed":21},{"name":"load.wast","passed":118,"failed":0},{"name":"load64.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_init.wast","passed":10,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":98,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":89,"failed":1},{"name":"memory64.wast","passed":68,"failed":1},{"name":"memory_copy.wast","passed":8628,"failed":272},{"name":"memory_fill.wast","passed":184,"failed":16},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_grow64.wast","passed":49,"failed":0},{"name":"memory_init.wast","passed":439,"failed":41},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_redundancy64.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"memory_trap64.wast","passed":172,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"obsolete-keywords.wast","passed":11,"failed":0},{"name":"ref.wast","passed":12,"failed":1},{"name":"ref_as_non_null.wast","passed":1,"failed":6},{"name":"ref_func.wast","passed":17,"failed":0},{"name":"ref_is_null.wast","passed":2,"failed":20},{"name":"ref_null.wast","passed":0,"failed":34},{"name":"return.wast","passed":84,"failed":0},{"name":"return_call.wast","passed":45,"failed":0},{"name":"return_call_indirect.wast","passed":76,"failed":0},{"name":"return_call_ref.wast","passed":11,"failed":40},{"name":"select.wast","passed":155,"failed":2},{"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":111,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":1},{"name":"table.wast","passed":47,"failed":13},{"name":"table_copy.wast","passed":1750,"failed":22},{"name":"table_copy_mixed.wast","passed":4,"failed":0},{"name":"table_fill.wast","passed":45,"failed":35},{"name":"table_get.wast","passed":16,"failed":1},{"name":"table_grow.wast","passed":58,"failed":21},{"name":"table_init.wast","passed":783,"failed":93},{"name":"table_set.wast","passed":26,"failed":2},{"name":"table_size.wast","passed":39,"failed":1},{"name":"tag.wast","passed":1,"failed":8},{"name":"throw.wast","passed":3,"failed":10},{"name":"throw_ref.wast","passed":2,"failed":13},{"name":"token.wast","passed":61,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"try_table.wast","passed":11,"failed":51},{"name":"type-canon.wast","passed":0,"failed":2},{"name":"type-equivalence.wast","passed":12,"failed":20},{"name":"type-rec.wast","passed":6,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":121,"failed":0},{"name":"unreached-valid.wast","passed":2,"failed":11},{"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}] diff --git a/crates/tinywasm/tests/generated/wasm-memory64.csv b/crates/tinywasm/tests/generated/wasm-memory64.csv index 6638c85..039fe8c 100644 --- a/crates/tinywasm/tests/generated/wasm-memory64.csv +++ b/crates/tinywasm/tests/generated/wasm-memory64.csv @@ -1,2 +1,2 @@ 0.8.0,15081,3214,[{"name":"address.wast","passed":260,"failed":0},{"name":"address0.wast","passed":92,"failed":0},{"name":"address1.wast","passed":127,"failed":0},{"name":"address64.wast","passed":0,"failed":242},{"name":"align.wast","passed":161,"failed":0},{"name":"align0.wast","passed":5,"failed":0},{"name":"align64.wast","passed":83,"failed":73},{"name":"annotations.wast","passed":74,"failed":0},{"name":"array_copy.wast","passed":4,"failed":31},{"name":"array_fill.wast","passed":3,"failed":14},{"name":"array_init_data.wast","passed":2,"failed":31},{"name":"array_init_elem.wast","passed":3,"failed":20},{"name":"binary-gc.wast","passed":1,"failed":0},{"name":"binary-leb128.wast","passed":92,"failed":1},{"name":"binary.wast","passed":124,"failed":0},{"name":"binary0.wast","passed":7,"failed":0},{"name":"br_if.wast","passed":119,"failed":0},{"name":"br_on_cast.wast","passed":6,"failed":31},{"name":"br_on_cast_fail.wast","passed":6,"failed":31},{"name":"br_on_non_null.wast","passed":1,"failed":9},{"name":"br_on_null.wast","passed":1,"failed":9},{"name":"br_table.wast","passed":24,"failed":162},{"name":"call_indirect.wast","passed":47,"failed":124},{"name":"call_ref.wast","passed":4,"failed":31},{"name":"data.wast","passed":59,"failed":6},{"name":"data0.wast","passed":7,"failed":0},{"name":"data1.wast","passed":14,"failed":0},{"name":"data_drop0.wast","passed":11,"failed":0},{"name":"elem.wast","passed":137,"failed":14},{"name":"endianness64.wast","passed":0,"failed":69},{"name":"exports.wast","passed":97,"failed":0},{"name":"exports0.wast","passed":8,"failed":0},{"name":"float_exprs0.wast","passed":14,"failed":0},{"name":"float_exprs1.wast","passed":3,"failed":0},{"name":"float_memory0.wast","passed":30,"failed":0},{"name":"float_memory64.wast","passed":0,"failed":90},{"name":"func.wast","passed":175,"failed":0},{"name":"id.wast","passed":7,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":99,"failed":82},{"name":"imports0.wast","passed":8,"failed":0},{"name":"imports1.wast","passed":5,"failed":0},{"name":"imports2.wast","passed":20,"failed":0},{"name":"imports3.wast","passed":10,"failed":0},{"name":"imports4.wast","passed":16,"failed":0},{"name":"linking.wast","passed":122,"failed":41},{"name":"linking0.wast","passed":6,"failed":0},{"name":"linking1.wast","passed":14,"failed":0},{"name":"linking2.wast","passed":11,"failed":0},{"name":"linking3.wast","passed":14,"failed":0},{"name":"load.wast","passed":118,"failed":0},{"name":"load0.wast","passed":3,"failed":0},{"name":"load1.wast","passed":18,"failed":0},{"name":"load2.wast","passed":38,"failed":0},{"name":"load64.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_init.wast","passed":10,"failed":0},{"name":"local_tee.wast","passed":98,"failed":0},{"name":"memory-multi.wast","passed":6,"failed":0},{"name":"memory.wast","passed":86,"failed":0},{"name":"memory64.wast","passed":10,"failed":53},{"name":"memory64/array.wast (skipped)","passed":0,"failed":0},{"name":"memory64/extern.wast (skipped)","passed":0,"failed":0},{"name":"memory64/global.wast (skipped)","passed":0,"failed":0},{"name":"memory64/i31.wast (skipped)","passed":0,"failed":0},{"name":"memory64/ref_null.wast (skipped)","passed":0,"failed":0},{"name":"memory64/select.wast (skipped)","passed":0,"failed":0},{"name":"memory64/simd_address.wast (skipped)","passed":0,"failed":0},{"name":"memory64/simd_lane.wast (skipped)","passed":0,"failed":0},{"name":"memory64/struct.wast (skipped)","passed":0,"failed":0},{"name":"memory64/table.wast (skipped)","passed":0,"failed":0},{"name":"memory_copy.wast","passed":8385,"failed":515},{"name":"memory_copy0.wast","passed":29,"failed":0},{"name":"memory_copy1.wast","passed":14,"failed":0},{"name":"memory_fill.wast","passed":164,"failed":36},{"name":"memory_fill0.wast","passed":16,"failed":0},{"name":"memory_grow.wast","passed":157,"failed":0},{"name":"memory_grow64.wast","passed":0,"failed":49},{"name":"memory_init.wast","passed":307,"failed":173},{"name":"memory_init0.wast","passed":13,"failed":0},{"name":"memory_redundancy64.wast","passed":0,"failed":8},{"name":"memory_size.wast","passed":49,"failed":0},{"name":"memory_size0.wast","passed":8,"failed":0},{"name":"memory_size1.wast","passed":15,"failed":0},{"name":"memory_size2.wast","passed":21,"failed":0},{"name":"memory_size3.wast","passed":2,"failed":0},{"name":"memory_trap0.wast","passed":14,"failed":0},{"name":"memory_trap1.wast","passed":168,"failed":0},{"name":"memory_trap64.wast","passed":0,"failed":172},{"name":"ref.wast","passed":12,"failed":1},{"name":"ref_as_non_null.wast","passed":1,"failed":6},{"name":"ref_cast.wast","passed":0,"failed":45},{"name":"ref_eq.wast","passed":6,"failed":83},{"name":"ref_is_null.wast","passed":2,"failed":20},{"name":"ref_test.wast","passed":0,"failed":71},{"name":"return_call.wast","passed":18,"failed":27},{"name":"return_call_indirect.wast","passed":31,"failed":45},{"name":"return_call_ref.wast","passed":11,"failed":40},{"name":"simd_memory-multi.wast","passed":0,"failed":1},{"name":"start0.wast","passed":9,"failed":0},{"name":"store.wast","passed":111,"failed":0},{"name":"store0.wast","passed":5,"failed":0},{"name":"store1.wast","passed":13,"failed":0},{"name":"table-sub.wast","passed":2,"failed":1},{"name":"table_copy.wast","passed":1742,"failed":30},{"name":"table_copy_mixed.wast","passed":3,"failed":1},{"name":"table_fill.wast","passed":9,"failed":71},{"name":"table_get.wast","passed":5,"failed":12},{"name":"table_grow.wast","passed":36,"failed":43},{"name":"table_init.wast","passed":588,"failed":288},{"name":"table_set.wast","passed":7,"failed":21},{"name":"table_size.wast","passed":2,"failed":38},{"name":"tag.wast","passed":1,"failed":8},{"name":"throw.wast","passed":3,"failed":10},{"name":"throw_ref.wast","passed":2,"failed":13},{"name":"token.wast","passed":61,"failed":0},{"name":"traps0.wast","passed":15,"failed":0},{"name":"try_table.wast","passed":11,"failed":51},{"name":"type-canon.wast","passed":0,"failed":2},{"name":"type-equivalence.wast","passed":12,"failed":20},{"name":"type-rec.wast","passed":6,"failed":14},{"name":"type-subtyping.wast","passed":16,"failed":86},{"name":"unreached-invalid.wast","passed":121,"failed":0},{"name":"unreached-valid.wast","passed":2,"failed":11}] -0.9.0-alpha.0,12505,1919,[{"name":"address.wast","passed":260,"failed":0},{"name":"address64.wast","passed":0,"failed":242},{"name":"align64.wast","passed":83,"failed":73},{"name":"binary-leb128.wast","passed":92,"failed":1},{"name":"binary.wast","passed":126,"failed":0},{"name":"binary0.wast","passed":7,"failed":0},{"name":"call_indirect.wast","passed":47,"failed":124},{"name":"endianness64.wast","passed":0,"failed":69},{"name":"float_memory64.wast","passed":0,"failed":90},{"name":"imports.wast","passed":169,"failed":90},{"name":"load64.wast","passed":59,"failed":38},{"name":"memory.wast","passed":86,"failed":0},{"name":"memory64.wast","passed":10,"failed":53},{"name":"memory64/simd_address.wast (skipped)","passed":0,"failed":0},{"name":"memory64/table.wast (skipped)","passed":0,"failed":0},{"name":"memory_copy.wast","passed":8385,"failed":515},{"name":"memory_fill.wast","passed":164,"failed":36},{"name":"memory_grow64.wast","passed":0,"failed":49},{"name":"memory_init.wast","passed":307,"failed":173},{"name":"memory_redundancy64.wast","passed":0,"failed":8},{"name":"memory_trap64.wast","passed":0,"failed":172},{"name":"table_copy.wast","passed":1742,"failed":30},{"name":"table_copy_mixed.wast","passed":4,"failed":0},{"name":"table_fill.wast","passed":45,"failed":35},{"name":"table_get.wast","passed":16,"failed":1},{"name":"table_grow.wast","passed":58,"failed":21},{"name":"table_init.wast","passed":780,"failed":96},{"name":"table_set.wast","passed":26,"failed":2},{"name":"table_size.wast","passed":39,"failed":1}] +0.9.0-alpha.0,1556,42,[{"name":"address.wast","passed":260,"failed":0},{"name":"address64.wast","passed":242,"failed":0},{"name":"align64.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":93,"failed":0},{"name":"binary.wast","passed":169,"failed":0},{"name":"endianness64.wast","passed":69,"failed":0},{"name":"float_memory64.wast","passed":90,"failed":0},{"name":"load64.wast","passed":97,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory64.wast","passed":65,"failed":0},{"name":"memory_grow64.wast","passed":49,"failed":0},{"name":"memory_redundancy64.wast","passed":8,"failed":0},{"name":"memory_trap64.wast","passed":172,"failed":0},{"name":"simd_address.wast","passed":7,"failed":42}] diff --git a/crates/tinywasm/tests/test-wasm-memory64.rs b/crates/tinywasm/tests/test-wasm-memory64.rs index 391a1ef..447bbfc 100644 --- a/crates/tinywasm/tests/test-wasm-memory64.rs +++ b/crates/tinywasm/tests/test-wasm-memory64.rs @@ -1,22 +1,11 @@ mod testsuite; -use eyre::{eyre, Result}; -use owo_colors::OwoColorize; +use eyre::Result; use testsuite::TestSuite; +use wasm_testsuite::data::{Proposal, proposal}; fn main() -> Result<()> { TestSuite::set_log_level(log::LevelFilter::Off); - let mut test_suite = TestSuite::new(); - test_suite.skip("memory64/array.wast"); - test_suite.skip("memory64/extern.wast"); - test_suite.skip("memory64/global.wast"); - test_suite.skip("memory64/i31.wast"); - test_suite.skip("memory64/ref_null.wast"); - test_suite.skip("memory64/select.wast"); - test_suite.skip("memory64/simd_address.wast"); - test_suite.skip("memory64/simd_lane.wast"); - test_suite.skip("memory64/struct.wast"); - test_suite.skip("memory64/table.wast"); test_suite.run_files(proposal(&Proposal::Memory64))?; test_suite.save_csv("./tests/generated/wasm-memory64.csv", env!("CARGO_PKG_VERSION"))?;