Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 03ff413

Browse files
feat: pass all float tests
Signed-off-by: Henry <[email protected]>
1 parent 9ea2796 commit 03ff413

File tree

7 files changed

+164
-41
lines changed

7 files changed

+164
-41
lines changed

crates/tinywasm/src/runtime/executor/mod.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::ops::{BitAnd, BitOr, BitXor};
1+
use core::ops::{BitAnd, BitOr, BitXor, Neg};
22

33
use super::{DefaultRuntime, Stack};
44
use crate::{
@@ -332,16 +332,16 @@ fn exec_one(
332332
I64Or => arithmetic_method!(bitor, i64, stack),
333333
I32Xor => arithmetic_method!(bitxor, i32, stack),
334334
I64Xor => arithmetic_method!(bitxor, i64, stack),
335-
I32Shl => arithmetic_method!(wrapping_shl_self, i32, stack),
336-
I64Shl => arithmetic_method!(wrapping_shl_self, i64, stack),
337-
I32ShrS => arithmetic_method!(wrapping_shr_self, i32, stack),
338-
I64ShrS => arithmetic_method!(wrapping_shr_self, i64, stack),
339-
I32ShrU => arithmetic_method_cast!(wrapping_shr_self, i32, u32, stack),
340-
I64ShrU => arithmetic_method_cast!(wrapping_shr_self, i64, u64, stack),
341-
I32Rotl => arithmetic_method!(wrapping_rotl_self, i32, stack),
342-
I64Rotl => arithmetic_method!(wrapping_rotl_self, i64, stack),
343-
I32Rotr => arithmetic_method!(wrapping_rotr_self, i32, stack),
344-
I64Rotr => arithmetic_method!(wrapping_rotr_self, i64, stack),
335+
I32Shl => arithmetic_method!(wasm_shl, i32, stack),
336+
I64Shl => arithmetic_method!(wasm_shl, i64, stack),
337+
I32ShrS => arithmetic_method!(wasm_shr, i32, stack),
338+
I64ShrS => arithmetic_method!(wasm_shr, i64, stack),
339+
I32ShrU => arithmetic_method_cast!(wasm_shr, i32, u32, stack),
340+
I64ShrU => arithmetic_method_cast!(wasm_shr, i64, u64, stack),
341+
I32Rotl => arithmetic_method!(wasm_rotl, i32, stack),
342+
I64Rotl => arithmetic_method!(wasm_rotl, i64, stack),
343+
I32Rotr => arithmetic_method!(wasm_rotr, i32, stack),
344+
I64Rotr => arithmetic_method!(wasm_rotr, i64, stack),
345345

346346
I32Clz => arithmetic_method_self!(leading_zeros, i32, stack),
347347
I64Clz => arithmetic_method_self!(leading_zeros, i64, stack),
@@ -367,6 +367,27 @@ fn exec_one(
367367
I64ExtendI32S => conv_1!(i32, i64, stack),
368368
I32WrapI64 => conv_1!(i64, i32, stack),
369369

370+
F32Abs => arithmetic_method_self!(abs, f32, stack),
371+
F64Abs => arithmetic_method_self!(abs, f64, stack),
372+
F32Neg => arithmetic_method_self!(neg, f32, stack),
373+
F64Neg => arithmetic_method_self!(neg, f64, stack),
374+
F32Ceil => arithmetic_method_self!(ceil, f32, stack),
375+
F64Ceil => arithmetic_method_self!(ceil, f64, stack),
376+
F32Floor => arithmetic_method_self!(floor, f32, stack),
377+
F64Floor => arithmetic_method_self!(floor, f64, stack),
378+
F32Trunc => arithmetic_method_self!(trunc, f32, stack),
379+
F64Trunc => arithmetic_method_self!(trunc, f64, stack),
380+
F32Nearest => arithmetic_method_self!(wasm_nearest, f32, stack),
381+
F64Nearest => arithmetic_method_self!(wasm_nearest, f64, stack),
382+
F32Sqrt => arithmetic_method_self!(sqrt, f32, stack),
383+
F64Sqrt => arithmetic_method_self!(sqrt, f64, stack),
384+
F32Min => arithmetic_method!(wasm_min, f32, stack),
385+
F64Min => arithmetic_method!(wasm_min, f64, stack),
386+
F32Max => arithmetic_method!(wasm_max, f32, stack),
387+
F64Max => arithmetic_method!(wasm_max, f64, stack),
388+
F32Copysign => arithmetic_method!(copysign, f32, stack),
389+
F64Copysign => arithmetic_method!(copysign, f64, stack),
390+
370391
// no-op instructions since types are erased at runtime
371392
I32ReinterpretF32 => {}
372393
I64ReinterpretF64 => {}

crates/tinywasm/src/runtime/executor/traits.rs

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,91 @@ where
55
fn checked_wrapping_rem(self, rhs: Self) -> Option<Self>;
66
}
77

8-
pub(crate) trait WrappingSelfOps {
9-
fn wrapping_shl_self(self, rhs: Self) -> Self;
10-
fn wrapping_shr_self(self, rhs: Self) -> Self;
11-
fn wrapping_rotl_self(self, rhs: Self) -> Self;
12-
fn wrapping_rotr_self(self, rhs: Self) -> Self;
8+
pub(crate) trait WasmFloatOps {
9+
fn wasm_min(self, other: Self) -> Self;
10+
fn wasm_max(self, other: Self) -> Self;
11+
fn wasm_nearest(self) -> Self;
12+
}
13+
14+
macro_rules! impl_wasm_float_ops {
15+
($($t:ty)*) => ($(
16+
impl WasmFloatOps for $t {
17+
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest
18+
fn wasm_nearest(self) -> Self {
19+
log::info!("wasm_nearest: {}", self);
20+
match self {
21+
x if x.is_nan() => x,
22+
x if x.is_infinite() || x == 0.0 => x,
23+
x if x > 0.0 && x <= 0.5 => 0.0,
24+
x if x < 0.0 && x >= -0.5 => -0.0,
25+
x => x.round(),
26+
}
27+
}
28+
29+
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fmin
30+
// Based on f32::minimum (which is not yet stable)
31+
#[inline]
32+
fn wasm_min(self, other: Self) -> Self {
33+
if self < other {
34+
self
35+
} else if other < self {
36+
other
37+
} else if self == other {
38+
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
39+
} else {
40+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
41+
self + other
42+
}
43+
}
44+
45+
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fmax
46+
// Based on f32::maximum (which is not yet stable)
47+
#[inline]
48+
fn wasm_max(self, other: Self) -> Self {
49+
if self > other {
50+
self
51+
} else if other > self {
52+
other
53+
} else if self == other {
54+
if self.is_sign_negative() && other.is_sign_positive() { other } else { self }
55+
} else {
56+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
57+
self + other
58+
}
59+
}
60+
}
61+
)*)
62+
}
63+
64+
impl_wasm_float_ops! { f32 f64 }
65+
66+
pub(crate) trait WasmIntOps {
67+
fn wasm_shl(self, rhs: Self) -> Self;
68+
fn wasm_shr(self, rhs: Self) -> Self;
69+
fn wasm_rotl(self, rhs: Self) -> Self;
70+
fn wasm_rotr(self, rhs: Self) -> Self;
1371
}
1472

1573
macro_rules! impl_wrapping_self_sh {
1674
($($t:ty)*) => ($(
17-
impl WrappingSelfOps for $t {
75+
impl WasmIntOps for $t {
1876
#[inline]
19-
fn wrapping_shl_self(self, rhs: Self) -> Self {
77+
fn wasm_shl(self, rhs: Self) -> Self {
2078
self.wrapping_shl(rhs as u32)
2179
}
2280

2381
#[inline]
24-
fn wrapping_shr_self(self, rhs: Self) -> Self {
82+
fn wasm_shr(self, rhs: Self) -> Self {
2583
self.wrapping_shr(rhs as u32)
2684
}
2785

2886
#[inline]
29-
fn wrapping_rotl_self(self, rhs: Self) -> Self {
87+
fn wasm_rotl(self, rhs: Self) -> Self {
3088
self.rotate_left(rhs as u32)
3189
}
3290

3391
#[inline]
34-
fn wrapping_rotr_self(self, rhs: Self) -> Self {
92+
fn wasm_rotr(self, rhs: Self) -> Self {
3593
self.rotate_right(rhs as u32)
3694
}
3795
}

0 commit comments

Comments
 (0)