diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 4 | ||||
| -rw-r--r-- | crates/parser/src/visit.rs | 5 | ||||
| -rw-r--r-- | crates/tinywasm/Cargo.toml | 5 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/executor.rs | 36 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/wasm-wide-arithmetic.csv | 1 | ||||
| -rw-r--r-- | crates/tinywasm/tests/test-wasm-wide-arithmetic.rs | 13 | ||||
| -rw-r--r-- | crates/types/src/instructions.rs | 5 | ||||
| -rwxr-xr-x | examples/rust/build.sh | 6 |
9 files changed, 70 insertions, 7 deletions
@@ -55,7 +55,7 @@ Untrusted WebAssembly code should not be able to crash the runtime or access mem | [**Memory64**](https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md) | 🟢 | `next` | | [**Tail Call**](https://github.com/WebAssembly/tail-call/blob/main/proposals/tail-call/Overview.md) | 🟢 | `next` | | [**Relaxed SIMD**](https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md) | 🟢 | `next` | -| [**Wide Arithmetic**](https://github.com/WebAssembly/wide-arithmetic/blob/main/proposals/wide-arithmetic/Overview.md) | 🚧 | - | +| [**Wide Arithmetic**](https://github.com/WebAssembly/wide-arithmetic/blob/main/proposals/wide-arithmetic/Overview.md) | 🟢 | `next` | | [**Custom Descriptors**](https://github.com/WebAssembly/custom-descriptors/blob/main/proposals/custom-descriptors/Overview.md) | 🌑 | - | | [**Exception Handling**](https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md) | 🌑 | - | | [**Function References**](https://github.com/WebAssembly/function-references/blob/main/proposals/function-references/Overview.md) | 🌑 | - | diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index a799f69..f7e713b 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -66,20 +66,20 @@ impl Parser { custom_page_sizes: true, bulk_memory_opt: true, call_indirect_overlong: true, + wide_arithmetic: true, + relaxed_simd: true, compact_imports: false, cm_map: false, custom_descriptors: false, cm_threading: false, extended_const: false, - wide_arithmetic: false, gc_types: true, stack_switching: false, component_model: false, exceptions: false, gc: false, memory_control: false, - relaxed_simd: true, threads: false, shared_everything_threads: false, legacy_exceptions: false, diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs index e3de009..d6bccdb 100644 --- a/crates/parser/src/visit.rs +++ b/crates/parser/src/visit.rs @@ -363,6 +363,7 @@ macro_rules! impl_visit_operator { (@@saturating_float_to_int $($rest:tt)* ) => {}; (@@bulk_memory $($rest:tt)* ) => {}; (@@simd $($rest:tt)* ) => {}; + (@@wide_arithmetic $($rest:tt)* ) => {}; (@@relaxed_simd $($rest:tt)* ) => {}; (@@tail_call $($rest:tt)* ) => {}; @@ -402,6 +403,10 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild visit_memory_init(MemoryInit, u32, u32), visit_memory_copy(MemoryCopy, u32, u32), visit_table_init(TableInit, u32, u32), visit_memory_fill(MemoryFill, u32), visit_data_drop(DataDrop, u32), visit_elem_drop(ElemDrop, u32) } + define_operands! { + visit_i64_add128(I64Add128), visit_i64_sub128(I64Sub128), visit_i64_mul_wide_s(I64MulWideS), visit_i64_mul_wide_u(I64MulWideU) + } + fn visit_global_set(&mut self, global_index: u32) -> Self::Output { match self.validator.get_operand_type(0) { Some(Some(t)) => self.instructions.push(match t { diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index b89c907..274946a 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -104,6 +104,11 @@ harness=false test=false [[test]] +name="test-wasm-wide-arithmetic" +harness=false +test=false + +[[test]] name="test-wast" harness=false test=false diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs index 17343ee..2292a70 100644 --- a/crates/tinywasm/src/interpreter/executor.rs +++ b/crates/tinywasm/src/interpreter/executor.rs @@ -57,9 +57,25 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> { (binary try $ty:ty, |$a:ident, $b:ident| $expr:expr) => { self.store.stack.values.binary::<$ty>(|$a, $b| $expr)? }; (unary $from:ty => $to:ty, |$v:ident| $expr:expr) => { self.store.stack.values.unary_into::<$from, $to>(|$v| Ok($expr))? }; (binary $from:ty => $to:ty, |$a:ident, $b:ident| $expr:expr) => { self.store.stack.values.binary_into::<$from, $to>(|$a, $b| Ok($expr))? }; + (binary_into2 $from:ty => $to:ty, |$a:ident, $b:ident| $expr:expr) => {{ + let $b = self.store.stack.values.pop::<$from>(); + let $a = self.store.stack.values.pop::<$from>(); + let out = $expr; + self.store.stack.values.push::<$to>(out.0)?; + self.store.stack.values.push::<$to>(out.1)?; + }}; (binary $a:ty, $b:ty, |$lhs:ident, $rhs:ident| $expr:expr) => { stack_op!(binary $a, $b => $b, |$lhs, $rhs| $expr) }; (binary $a:ty, $b:ty => $res:ty, |$lhs:ident, $rhs:ident| $expr:expr) => { self.store.stack.values.binary_mixed::<$a, $b, $res>(|$lhs, $rhs| Ok($expr))? }; (ternary $ty:ty, |$a:ident, $b:ident, $c:ident| $expr:expr) => { self.store.stack.values.ternary::<$ty>(|$a, $b, $c| Ok($expr))? }; + (quaternary_into2 $from:ty => $to:ty, |$a:ident, $b:ident, $c:ident, $d:ident| $expr:expr) => {{ + let $d = self.store.stack.values.pop::<$from>(); + let $c = self.store.stack.values.pop::<$from>(); + let $b = self.store.stack.values.pop::<$from>(); + let $a = self.store.stack.values.pop::<$from>(); + let out = $expr; + self.store.stack.values.push::<$to>(out.0)?; + self.store.stack.values.push::<$to>(out.1)?; + }}; (local_set_pop $ty:ty, $local_index:expr) => {{ let val = self.store.stack.values.pop::<$ty>(); self.store.stack.values.local_set(&self.cf, *$local_index, val); @@ -266,6 +282,26 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> { I64Rotl => stack_op!(binary i64, |a, b| a.wasm_rotl(b)), I32Rotr => stack_op!(binary i32, |a, b| a.wasm_rotr(b)), I64Rotr => stack_op!(binary i64, |a, b| a.wasm_rotr(b)), + I64Add128 => stack_op!(quaternary_into2 i64 => i64, |a_lo, a_hi, b_lo, b_hi| { + let lo = a_lo.wrapping_add(b_lo); + let carry = u64::from((lo as u64) < (a_lo as u64)); + let hi = a_hi.wrapping_add(b_hi).wrapping_add(carry as i64); + (lo, hi) + }), + I64Sub128 => stack_op!(quaternary_into2 i64 => i64, |a_lo, a_hi, b_lo, b_hi| { + let lo = a_lo.wrapping_sub(b_lo); + let borrow = u64::from((a_lo as u64) < (b_lo as u64)); + let hi = a_hi.wrapping_sub(b_hi).wrapping_sub(borrow as i64); + (lo, hi) + }), + I64MulWideS => stack_op!(binary_into2 i64 => i64, |a, b| { + let product = (a as i128).wrapping_mul(b as i128); + (product as i64, (product >> 64) as i64) + }), + I64MulWideU => stack_op!(binary_into2 i64 => i64, |a, b| { + let product = (a as u64 as u128).wrapping_mul(b as u64 as u128); + (product as u64 as i64, (product >> 64) as u64 as i64) + }), I32Clz => stack_op!(unary i32, |v| v.leading_zeros() as i32), I64Clz => stack_op!(unary i64, |v| i64::from(v.leading_zeros())), I32Ctz => stack_op!(unary i32, |v| v.trailing_zeros() as i32), diff --git a/crates/tinywasm/tests/generated/wasm-wide-arithmetic.csv b/crates/tinywasm/tests/generated/wasm-wide-arithmetic.csv new file mode 100644 index 0000000..10d7685 --- /dev/null +++ b/crates/tinywasm/tests/generated/wasm-wide-arithmetic.csv @@ -0,0 +1 @@ +0.9.0-alpha.0,109,0,[{"name":"wide-arithmetic.wast","passed":109,"failed":0}] diff --git a/crates/tinywasm/tests/test-wasm-wide-arithmetic.rs b/crates/tinywasm/tests/test-wasm-wide-arithmetic.rs new file mode 100644 index 0000000..2aa6b43 --- /dev/null +++ b/crates/tinywasm/tests/test-wasm-wide-arithmetic.rs @@ -0,0 +1,13 @@ +mod testsuite; +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.run_files(proposal(&Proposal::WideArithmetic))?; + test_suite.save_csv("./tests/generated/wasm-wide-arithmetic.csv", env!("CARGO_PKG_VERSION"))?; + test_suite.report_status() +} diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index 59dc49f..efb7172 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -176,7 +176,10 @@ pub enum Instruction { DataDrop(DataAddr), ElemDrop(ElemAddr), - // > SIMD Instructions + // > Wide Arithmetic + I64Add128, I64Sub128, I64MulWideS, I64MulWideU, + + // > SIMD V128Load(MemoryArg), V128Load8x8S(MemoryArg), V128Load8x8U(MemoryArg), V128Load16x4S(MemoryArg), V128Load16x4U(MemoryArg), diff --git a/examples/rust/build.sh b/examples/rust/build.sh index d51840b..36f9568 100755 --- a/examples/rust/build.sh +++ b/examples/rust/build.sh @@ -6,8 +6,8 @@ exclude_wat=("tinywasm") out_dir="./target/wasm32-unknown-unknown/wasm" dest_dir="out" -rust_features="+simd128,+reference-types,+bulk-memory,+mutable-globals,+multivalue,+sign-ext,+nontrapping-fptoint" -wasmopt_features="--enable-simd --enable-tail-call --enable-extended-const --enable-reference-types --enable-bulk-memory --enable-mutable-globals --enable-multivalue --enable-sign-ext --enable-nontrapping-float-to-int --duplicate-function-elimination" +rust_features="+simd128,+relaxed-simd,+reference-types,+bulk-memory,+mutable-globals,+multivalue,+sign-ext,+nontrapping-fptoint" +wasmopt_features="--enable-simd --enable-relaxed-simd --enable-tail-call --enable-extended-const --enable-reference-types --enable-bulk-memory --enable-mutable-globals --enable-multivalue --enable-sign-ext --enable-nontrapping-float-to-int --duplicate-function-elimination" # ensure out dir exists mkdir -p "$dest_dir" @@ -25,4 +25,4 @@ for bin in "${bins[@]}"; do if [[ ! " ${exclude_wat[@]} " =~ " $bin " ]]; then wasm2wat "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wat" fi -done
\ No newline at end of file +done |
