diff options
| author | Henry <mail@henrygressmann.de> | 2026-04-03 23:56:03 +0200 |
|---|---|---|
| committer | Henry <mail@henrygressmann.de> | 2026-04-03 23:56:03 +0200 |
| commit | ddc997ab59762958da139a333a2fa5f0ce37eace (patch) | |
| tree | 04785a45c53fa6edfb75a6cae4ad1cc2565e56f5 /crates | |
| parent | 1f741ba37d8217de333488d0a66fa6cc7f8537a7 (diff) | |
feat: Wide Arithmetic
Signed-off-by: Henry <mail@henrygressmann.de>
Diffstat (limited to 'crates')
| -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 |
7 files changed, 66 insertions, 3 deletions
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), |
