Skip to content

Commit ddc997a

Browse files
feat: Wide Arithmetic
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 1f741ba commit ddc997a

File tree

9 files changed

+70
-7
lines changed

9 files changed

+70
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Untrusted WebAssembly code should not be able to crash the runtime or access mem
5555
| [**Memory64**](https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md) | 🟢 | `next` |
5656
| [**Tail Call**](https://github.com/WebAssembly/tail-call/blob/main/proposals/tail-call/Overview.md) | 🟢 | `next` |
5757
| [**Relaxed SIMD**](https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md) | 🟢 | `next` |
58-
| [**Wide Arithmetic**](https://github.com/WebAssembly/wide-arithmetic/blob/main/proposals/wide-arithmetic/Overview.md) | 🚧 | - |
58+
| [**Wide Arithmetic**](https://github.com/WebAssembly/wide-arithmetic/blob/main/proposals/wide-arithmetic/Overview.md) | 🟢 | `next` |
5959
| [**Custom Descriptors**](https://github.com/WebAssembly/custom-descriptors/blob/main/proposals/custom-descriptors/Overview.md) | 🌑 | - |
6060
| [**Exception Handling**](https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md) | 🌑 | - |
6161
| [**Function References**](https://github.com/WebAssembly/function-references/blob/main/proposals/function-references/Overview.md) | 🌑 | - |

crates/parser/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,20 @@ impl Parser {
6666
custom_page_sizes: true,
6767
bulk_memory_opt: true,
6868
call_indirect_overlong: true,
69+
wide_arithmetic: true,
70+
relaxed_simd: true,
6971

7072
compact_imports: false,
7173
cm_map: false,
7274
custom_descriptors: false,
7375
cm_threading: false,
7476
extended_const: false,
75-
wide_arithmetic: false,
7677
gc_types: true,
7778
stack_switching: false,
7879
component_model: false,
7980
exceptions: false,
8081
gc: false,
8182
memory_control: false,
82-
relaxed_simd: true,
8383
threads: false,
8484
shared_everything_threads: false,
8585
legacy_exceptions: false,

crates/parser/src/visit.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ macro_rules! impl_visit_operator {
363363
(@@saturating_float_to_int $($rest:tt)* ) => {};
364364
(@@bulk_memory $($rest:tt)* ) => {};
365365
(@@simd $($rest:tt)* ) => {};
366+
(@@wide_arithmetic $($rest:tt)* ) => {};
366367
(@@relaxed_simd $($rest:tt)* ) => {};
367368
(@@tail_call $($rest:tt)* ) => {};
368369

@@ -402,6 +403,10 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
402403
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)
403404
}
404405

406+
define_operands! {
407+
visit_i64_add128(I64Add128), visit_i64_sub128(I64Sub128), visit_i64_mul_wide_s(I64MulWideS), visit_i64_mul_wide_u(I64MulWideU)
408+
}
409+
405410
fn visit_global_set(&mut self, global_index: u32) -> Self::Output {
406411
match self.validator.get_operand_type(0) {
407412
Some(Some(t)) => self.instructions.push(match t {

crates/tinywasm/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ name="test-wasm-simd"
103103
harness=false
104104
test=false
105105

106+
[[test]]
107+
name="test-wasm-wide-arithmetic"
108+
harness=false
109+
test=false
110+
106111
[[test]]
107112
name="test-wast"
108113
harness=false

crates/tinywasm/src/interpreter/executor.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,25 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
5757
(binary try $ty:ty, |$a:ident, $b:ident| $expr:expr) => { self.store.stack.values.binary::<$ty>(|$a, $b| $expr)? };
5858
(unary $from:ty => $to:ty, |$v:ident| $expr:expr) => { self.store.stack.values.unary_into::<$from, $to>(|$v| Ok($expr))? };
5959
(binary $from:ty => $to:ty, |$a:ident, $b:ident| $expr:expr) => { self.store.stack.values.binary_into::<$from, $to>(|$a, $b| Ok($expr))? };
60+
(binary_into2 $from:ty => $to:ty, |$a:ident, $b:ident| $expr:expr) => {{
61+
let $b = self.store.stack.values.pop::<$from>();
62+
let $a = self.store.stack.values.pop::<$from>();
63+
let out = $expr;
64+
self.store.stack.values.push::<$to>(out.0)?;
65+
self.store.stack.values.push::<$to>(out.1)?;
66+
}};
6067
(binary $a:ty, $b:ty, |$lhs:ident, $rhs:ident| $expr:expr) => { stack_op!(binary $a, $b => $b, |$lhs, $rhs| $expr) };
6168
(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))? };
6269
(ternary $ty:ty, |$a:ident, $b:ident, $c:ident| $expr:expr) => { self.store.stack.values.ternary::<$ty>(|$a, $b, $c| Ok($expr))? };
70+
(quaternary_into2 $from:ty => $to:ty, |$a:ident, $b:ident, $c:ident, $d:ident| $expr:expr) => {{
71+
let $d = self.store.stack.values.pop::<$from>();
72+
let $c = self.store.stack.values.pop::<$from>();
73+
let $b = self.store.stack.values.pop::<$from>();
74+
let $a = self.store.stack.values.pop::<$from>();
75+
let out = $expr;
76+
self.store.stack.values.push::<$to>(out.0)?;
77+
self.store.stack.values.push::<$to>(out.1)?;
78+
}};
6379
(local_set_pop $ty:ty, $local_index:expr) => {{
6480
let val = self.store.stack.values.pop::<$ty>();
6581
self.store.stack.values.local_set(&self.cf, *$local_index, val);
@@ -266,6 +282,26 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
266282
I64Rotl => stack_op!(binary i64, |a, b| a.wasm_rotl(b)),
267283
I32Rotr => stack_op!(binary i32, |a, b| a.wasm_rotr(b)),
268284
I64Rotr => stack_op!(binary i64, |a, b| a.wasm_rotr(b)),
285+
I64Add128 => stack_op!(quaternary_into2 i64 => i64, |a_lo, a_hi, b_lo, b_hi| {
286+
let lo = a_lo.wrapping_add(b_lo);
287+
let carry = u64::from((lo as u64) < (a_lo as u64));
288+
let hi = a_hi.wrapping_add(b_hi).wrapping_add(carry as i64);
289+
(lo, hi)
290+
}),
291+
I64Sub128 => stack_op!(quaternary_into2 i64 => i64, |a_lo, a_hi, b_lo, b_hi| {
292+
let lo = a_lo.wrapping_sub(b_lo);
293+
let borrow = u64::from((a_lo as u64) < (b_lo as u64));
294+
let hi = a_hi.wrapping_sub(b_hi).wrapping_sub(borrow as i64);
295+
(lo, hi)
296+
}),
297+
I64MulWideS => stack_op!(binary_into2 i64 => i64, |a, b| {
298+
let product = (a as i128).wrapping_mul(b as i128);
299+
(product as i64, (product >> 64) as i64)
300+
}),
301+
I64MulWideU => stack_op!(binary_into2 i64 => i64, |a, b| {
302+
let product = (a as u64 as u128).wrapping_mul(b as u64 as u128);
303+
(product as u64 as i64, (product >> 64) as u64 as i64)
304+
}),
269305
I32Clz => stack_op!(unary i32, |v| v.leading_zeros() as i32),
270306
I64Clz => stack_op!(unary i64, |v| i64::from(v.leading_zeros())),
271307
I32Ctz => stack_op!(unary i32, |v| v.trailing_zeros() as i32),
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.9.0-alpha.0,109,0,[{"name":"wide-arithmetic.wast","passed":109,"failed":0}]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mod testsuite;
2+
use eyre::Result;
3+
use testsuite::TestSuite;
4+
use wasm_testsuite::data::{Proposal, proposal};
5+
6+
fn main() -> Result<()> {
7+
TestSuite::set_log_level(log::LevelFilter::Off);
8+
9+
let mut test_suite = TestSuite::new();
10+
test_suite.run_files(proposal(&Proposal::WideArithmetic))?;
11+
test_suite.save_csv("./tests/generated/wasm-wide-arithmetic.csv", env!("CARGO_PKG_VERSION"))?;
12+
test_suite.report_status()
13+
}

crates/types/src/instructions.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ pub enum Instruction {
176176
DataDrop(DataAddr),
177177
ElemDrop(ElemAddr),
178178

179-
// > SIMD Instructions
179+
// > Wide Arithmetic
180+
I64Add128, I64Sub128, I64MulWideS, I64MulWideU,
181+
182+
// > SIMD
180183
V128Load(MemoryArg),
181184
V128Load8x8S(MemoryArg), V128Load8x8U(MemoryArg),
182185
V128Load16x4S(MemoryArg), V128Load16x4U(MemoryArg),

examples/rust/build.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ exclude_wat=("tinywasm")
66
out_dir="./target/wasm32-unknown-unknown/wasm"
77
dest_dir="out"
88

9-
rust_features="+simd128,+reference-types,+bulk-memory,+mutable-globals,+multivalue,+sign-ext,+nontrapping-fptoint"
10-
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"
9+
rust_features="+simd128,+relaxed-simd,+reference-types,+bulk-memory,+mutable-globals,+multivalue,+sign-ext,+nontrapping-fptoint"
10+
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"
1111

1212
# ensure out dir exists
1313
mkdir -p "$dest_dir"
@@ -25,4 +25,4 @@ for bin in "${bins[@]}"; do
2525
if [[ ! " ${exclude_wat[@]} " =~ " $bin " ]]; then
2626
wasm2wat "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wat"
2727
fi
28-
done
28+
done

0 commit comments

Comments
 (0)