summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs2
-rw-r--r--crates/tinywasm/src/interpreter/value128.rs26
-rw-r--r--crates/tinywasm/src/store/memory.rs2
-rw-r--r--crates/tinywasm/tests/generated/wasm-simd.csv2
-rw-r--r--crates/types/src/value.rs58
5 files changed, 74 insertions, 16 deletions
diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs
index 2850e91..016b823 100644
--- a/crates/tinywasm/src/interpreter/stack/value_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs
@@ -1,7 +1,7 @@
use alloc::vec::Vec;
use tinywasm_types::{ExternRef, FuncRef, ValType, ValueCounts, ValueCountsSmall, WasmValue};
-use crate::{interpreter::*, Result, StackConfig};
+use crate::{Result, StackConfig, interpreter::*};
use super::Locals;
diff --git a/crates/tinywasm/src/interpreter/value128.rs b/crates/tinywasm/src/interpreter/value128.rs
index 6b807c9..60e709c 100644
--- a/crates/tinywasm/src/interpreter/value128.rs
+++ b/crates/tinywasm/src/interpreter/value128.rs
@@ -6,20 +6,26 @@ pub struct Value128(i128);
impl Value128 {
#[inline]
fn canonicalize_simd_f32_nan(x: f32) -> f32 {
+ #[cfg(feature = "canonicalize_nans")]
if x.is_nan() {
- f32::from_bits(0x7fc0_0000)
+ f32::NAN
} else {
x
}
+ #[cfg(not(feature = "canonicalize_nans"))]
+ x
}
#[inline]
fn canonicalize_simd_f64_nan(x: f64) -> f64 {
+ #[cfg(feature = "canonicalize_nans")]
if x.is_nan() {
- f64::from_bits(0x7ff8_0000_0000_0000)
+ f64::NAN
} else {
x
}
+ #[cfg(not(feature = "canonicalize_nans"))]
+ x
}
const fn saturate_i16_to_i8(x: i16) -> i8 {
@@ -2186,42 +2192,42 @@ impl Value128 {
#[doc(alias = "f32x4.ceil")]
pub fn f32x4_ceil(self) -> Self {
- self.map_f32x4(f32::ceil)
+ self.map_f32x4(|x| Self::canonicalize_simd_f32_nan(x.ceil()))
}
#[doc(alias = "f64x2.ceil")]
pub fn f64x2_ceil(self) -> Self {
- self.map_f64x2(f64::ceil)
+ self.map_f64x2(|x| Self::canonicalize_simd_f64_nan(x.ceil()))
}
#[doc(alias = "f32x4.floor")]
pub fn f32x4_floor(self) -> Self {
- self.map_f32x4(f32::floor)
+ self.map_f32x4(|x| Self::canonicalize_simd_f32_nan(x.floor()))
}
#[doc(alias = "f64x2.floor")]
pub fn f64x2_floor(self) -> Self {
- self.map_f64x2(f64::floor)
+ self.map_f64x2(|x| Self::canonicalize_simd_f64_nan(x.floor()))
}
#[doc(alias = "f32x4.trunc")]
pub fn f32x4_trunc(self) -> Self {
- self.map_f32x4(f32::trunc)
+ self.map_f32x4(|x| Self::canonicalize_simd_f32_nan(x.trunc()))
}
#[doc(alias = "f64x2.trunc")]
pub fn f64x2_trunc(self) -> Self {
- self.map_f64x2(f64::trunc)
+ self.map_f64x2(|x| Self::canonicalize_simd_f64_nan(x.trunc()))
}
#[doc(alias = "f32x4.nearest")]
pub fn f32x4_nearest(self) -> Self {
- self.map_f32x4(TinywasmFloatExt::tw_nearest)
+ self.map_f32x4(|x| Self::canonicalize_simd_f32_nan(TinywasmFloatExt::tw_nearest(x)))
}
#[doc(alias = "f64x2.nearest")]
pub fn f64x2_nearest(self) -> Self {
- self.map_f64x2(TinywasmFloatExt::tw_nearest)
+ self.map_f64x2(|x| Self::canonicalize_simd_f64_nan(TinywasmFloatExt::tw_nearest(x)))
}
#[doc(alias = "f32x4.abs")]
diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs
index 65c4361..8898212 100644
--- a/crates/tinywasm/src/store/memory.rs
+++ b/crates/tinywasm/src/store/memory.rs
@@ -2,7 +2,7 @@ use alloc::vec;
use alloc::vec::Vec;
use tinywasm_types::{MemoryArch, MemoryType, ModuleInstanceAddr};
-use crate::{cold, interpreter::Value128, log, Error, Result};
+use crate::{Error, Result, cold, interpreter::Value128, log};
/// A WebAssembly Memory Instance
///
diff --git a/crates/tinywasm/tests/generated/wasm-simd.csv b/crates/tinywasm/tests/generated/wasm-simd.csv
index 96d9796..b05959c 100644
--- a/crates/tinywasm/tests/generated/wasm-simd.csv
+++ b/crates/tinywasm/tests/generated/wasm-simd.csv
@@ -1,2 +1,2 @@
0.8.0,1300,24679,[{"name":"simd_address.wast","passed":4,"failed":45},{"name":"simd_align.wast","passed":46,"failed":54},{"name":"simd_bit_shift.wast","passed":39,"failed":213},{"name":"simd_bitwise.wast","passed":28,"failed":141},{"name":"simd_boolean.wast","passed":16,"failed":261},{"name":"simd_const.wast","passed":301,"failed":456},{"name":"simd_conversions.wast","passed":48,"failed":234},{"name":"simd_f32x4.wast","passed":16,"failed":774},{"name":"simd_f32x4_arith.wast","passed":16,"failed":1806},{"name":"simd_f32x4_cmp.wast","passed":24,"failed":2583},{"name":"simd_f32x4_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f32x4_rounding.wast","passed":24,"failed":177},{"name":"simd_f64x2.wast","passed":8,"failed":795},{"name":"simd_f64x2_arith.wast","passed":16,"failed":1809},{"name":"simd_f64x2_cmp.wast","passed":24,"failed":2661},{"name":"simd_f64x2_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f64x2_rounding.wast","passed":24,"failed":177},{"name":"simd_i16x8_arith.wast","passed":11,"failed":183},{"name":"simd_i16x8_arith2.wast","passed":19,"failed":153},{"name":"simd_i16x8_cmp.wast","passed":30,"failed":435},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":4,"failed":17},{"name":"simd_i16x8_extmul_i8x16.wast","passed":12,"failed":105},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":3,"failed":27},{"name":"simd_i16x8_sat_arith.wast","passed":16,"failed":206},{"name":"simd_i32x4_arith.wast","passed":11,"failed":183},{"name":"simd_i32x4_arith2.wast","passed":26,"failed":123},{"name":"simd_i32x4_cmp.wast","passed":40,"failed":435},{"name":"simd_i32x4_dot_i16x8.wast","passed":3,"failed":27},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":4,"failed":17},{"name":"simd_i32x4_extmul_i16x8.wast","passed":12,"failed":105},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":4,"failed":103},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":4,"failed":103},{"name":"simd_i64x2_arith.wast","passed":11,"failed":189},{"name":"simd_i64x2_arith2.wast","passed":2,"failed":23},{"name":"simd_i64x2_cmp.wast","passed":10,"failed":103},{"name":"simd_i64x2_extmul_i32x4.wast","passed":12,"failed":105},{"name":"simd_i8x16_arith.wast","passed":8,"failed":123},{"name":"simd_i8x16_arith2.wast","passed":25,"failed":186},{"name":"simd_i8x16_cmp.wast","passed":30,"failed":415},{"name":"simd_i8x16_sat_arith.wast","passed":24,"failed":190},{"name":"simd_int_to_int_extend.wast","passed":24,"failed":229},{"name":"simd_lane.wast","passed":189,"failed":286},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":8,"failed":31},{"name":"simd_load16_lane.wast","passed":3,"failed":33},{"name":"simd_load32_lane.wast","passed":3,"failed":21},{"name":"simd_load64_lane.wast","passed":3,"failed":13},{"name":"simd_load8_lane.wast","passed":3,"failed":49},{"name":"simd_load_extend.wast","passed":18,"failed":86},{"name":"simd_load_splat.wast","passed":12,"failed":114},{"name":"simd_load_zero.wast","passed":10,"failed":29},{"name":"simd_splat.wast","passed":23,"failed":162},{"name":"simd_store.wast","passed":9,"failed":19},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
-0.9.0-alpha.0,25964,25,[{"name":"simd_address.wast","passed":49,"failed":0},{"name":"simd_align.wast","passed":100,"failed":0},{"name":"simd_bit_shift.wast","passed":252,"failed":0},{"name":"simd_bitwise.wast","passed":169,"failed":0},{"name":"simd_boolean.wast","passed":277,"failed":0},{"name":"simd_const.wast","passed":757,"failed":0},{"name":"simd_conversions.wast","passed":276,"failed":6},{"name":"simd_f32x4.wast","passed":790,"failed":0},{"name":"simd_f32x4_arith.wast","passed":1822,"failed":0},{"name":"simd_f32x4_cmp.wast","passed":2607,"failed":0},{"name":"simd_f32x4_pmin_pmax.wast","passed":3887,"failed":0},{"name":"simd_f32x4_rounding.wast","passed":192,"failed":9},{"name":"simd_f64x2.wast","passed":803,"failed":0},{"name":"simd_f64x2_arith.wast","passed":1824,"failed":1},{"name":"simd_f64x2_cmp.wast","passed":2685,"failed":0},{"name":"simd_f64x2_pmin_pmax.wast","passed":3887,"failed":0},{"name":"simd_f64x2_rounding.wast","passed":192,"failed":9},{"name":"simd_i16x8_arith.wast","passed":194,"failed":0},{"name":"simd_i16x8_arith2.wast","passed":172,"failed":0},{"name":"simd_i16x8_cmp.wast","passed":465,"failed":0},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":21,"failed":0},{"name":"simd_i16x8_extmul_i8x16.wast","passed":117,"failed":0},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":30,"failed":0},{"name":"simd_i16x8_sat_arith.wast","passed":222,"failed":0},{"name":"simd_i32x4_arith.wast","passed":194,"failed":0},{"name":"simd_i32x4_arith2.wast","passed":149,"failed":0},{"name":"simd_i32x4_cmp.wast","passed":475,"failed":0},{"name":"simd_i32x4_dot_i16x8.wast","passed":32,"failed":0},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":21,"failed":0},{"name":"simd_i32x4_extmul_i16x8.wast","passed":117,"failed":0},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":107,"failed":0},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":107,"failed":0},{"name":"simd_i64x2_arith.wast","passed":200,"failed":0},{"name":"simd_i64x2_arith2.wast","passed":25,"failed":0},{"name":"simd_i64x2_cmp.wast","passed":113,"failed":0},{"name":"simd_i64x2_extmul_i32x4.wast","passed":117,"failed":0},{"name":"simd_i8x16_arith.wast","passed":131,"failed":0},{"name":"simd_i8x16_arith2.wast","passed":211,"failed":0},{"name":"simd_i8x16_cmp.wast","passed":445,"failed":0},{"name":"simd_i8x16_sat_arith.wast","passed":214,"failed":0},{"name":"simd_int_to_int_extend.wast","passed":253,"failed":0},{"name":"simd_lane.wast","passed":475,"failed":0},{"name":"simd_linking.wast","passed":3,"failed":0},{"name":"simd_load.wast","passed":39,"failed":0},{"name":"simd_load16_lane.wast","passed":36,"failed":0},{"name":"simd_load32_lane.wast","passed":24,"failed":0},{"name":"simd_load64_lane.wast","passed":16,"failed":0},{"name":"simd_load8_lane.wast","passed":52,"failed":0},{"name":"simd_load_extend.wast","passed":104,"failed":0},{"name":"simd_load_splat.wast","passed":126,"failed":0},{"name":"simd_load_zero.wast","passed":39,"failed":0},{"name":"simd_memory-multi.wast","passed":1,"failed":0},{"name":"simd_select.wast","passed":7,"failed":0},{"name":"simd_splat.wast","passed":185,"failed":0},{"name":"simd_store.wast","passed":28,"failed":0},{"name":"simd_store16_lane.wast","passed":36,"failed":0},{"name":"simd_store32_lane.wast","passed":24,"failed":0},{"name":"simd_store64_lane.wast","passed":16,"failed":0},{"name":"simd_store8_lane.wast","passed":52,"failed":0}]
+0.9.0-alpha.0,25989,0,[{"name":"simd_address.wast","passed":49,"failed":0},{"name":"simd_align.wast","passed":100,"failed":0},{"name":"simd_bit_shift.wast","passed":252,"failed":0},{"name":"simd_bitwise.wast","passed":169,"failed":0},{"name":"simd_boolean.wast","passed":277,"failed":0},{"name":"simd_const.wast","passed":757,"failed":0},{"name":"simd_conversions.wast","passed":282,"failed":0},{"name":"simd_f32x4.wast","passed":790,"failed":0},{"name":"simd_f32x4_arith.wast","passed":1822,"failed":0},{"name":"simd_f32x4_cmp.wast","passed":2607,"failed":0},{"name":"simd_f32x4_pmin_pmax.wast","passed":3887,"failed":0},{"name":"simd_f32x4_rounding.wast","passed":201,"failed":0},{"name":"simd_f64x2.wast","passed":803,"failed":0},{"name":"simd_f64x2_arith.wast","passed":1825,"failed":0},{"name":"simd_f64x2_cmp.wast","passed":2685,"failed":0},{"name":"simd_f64x2_pmin_pmax.wast","passed":3887,"failed":0},{"name":"simd_f64x2_rounding.wast","passed":201,"failed":0},{"name":"simd_i16x8_arith.wast","passed":194,"failed":0},{"name":"simd_i16x8_arith2.wast","passed":172,"failed":0},{"name":"simd_i16x8_cmp.wast","passed":465,"failed":0},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":21,"failed":0},{"name":"simd_i16x8_extmul_i8x16.wast","passed":117,"failed":0},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":30,"failed":0},{"name":"simd_i16x8_sat_arith.wast","passed":222,"failed":0},{"name":"simd_i32x4_arith.wast","passed":194,"failed":0},{"name":"simd_i32x4_arith2.wast","passed":149,"failed":0},{"name":"simd_i32x4_cmp.wast","passed":475,"failed":0},{"name":"simd_i32x4_dot_i16x8.wast","passed":32,"failed":0},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":21,"failed":0},{"name":"simd_i32x4_extmul_i16x8.wast","passed":117,"failed":0},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":107,"failed":0},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":107,"failed":0},{"name":"simd_i64x2_arith.wast","passed":200,"failed":0},{"name":"simd_i64x2_arith2.wast","passed":25,"failed":0},{"name":"simd_i64x2_cmp.wast","passed":113,"failed":0},{"name":"simd_i64x2_extmul_i32x4.wast","passed":117,"failed":0},{"name":"simd_i8x16_arith.wast","passed":131,"failed":0},{"name":"simd_i8x16_arith2.wast","passed":211,"failed":0},{"name":"simd_i8x16_cmp.wast","passed":445,"failed":0},{"name":"simd_i8x16_sat_arith.wast","passed":214,"failed":0},{"name":"simd_int_to_int_extend.wast","passed":253,"failed":0},{"name":"simd_lane.wast","passed":475,"failed":0},{"name":"simd_linking.wast","passed":3,"failed":0},{"name":"simd_load.wast","passed":39,"failed":0},{"name":"simd_load16_lane.wast","passed":36,"failed":0},{"name":"simd_load32_lane.wast","passed":24,"failed":0},{"name":"simd_load64_lane.wast","passed":16,"failed":0},{"name":"simd_load8_lane.wast","passed":52,"failed":0},{"name":"simd_load_extend.wast","passed":104,"failed":0},{"name":"simd_load_splat.wast","passed":126,"failed":0},{"name":"simd_load_zero.wast","passed":39,"failed":0},{"name":"simd_memory-multi.wast","passed":1,"failed":0},{"name":"simd_select.wast","passed":7,"failed":0},{"name":"simd_splat.wast","passed":185,"failed":0},{"name":"simd_store.wast","passed":28,"failed":0},{"name":"simd_store16_lane.wast","passed":36,"failed":0},{"name":"simd_store32_lane.wast","passed":24,"failed":0},{"name":"simd_store64_lane.wast","passed":16,"failed":0},{"name":"simd_store8_lane.wast","passed":52,"failed":0}]
diff --git a/crates/types/src/value.rs b/crates/types/src/value.rs
index 22bb4eb..aa9e8c5 100644
--- a/crates/types/src/value.rs
+++ b/crates/types/src/value.rs
@@ -138,19 +138,23 @@ impl WasmValue {
match (self, other) {
(Self::I32(a), Self::I32(b)) => a == b,
(Self::I64(a), Self::I64(b)) => a == b,
- (Self::V128(a), Self::V128(b)) => a == b,
+ (Self::V128(a), Self::V128(b)) => {
+ let a_bytes = a.to_le_bytes();
+ let b_bytes = b.to_le_bytes();
+ a_bytes == b_bytes || Self::v128_nan_eq(a_bytes, b_bytes)
+ }
(Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2,
(Self::RefFunc(addr), Self::RefFunc(addr2)) => addr == addr2,
(Self::F32(a), Self::F32(b)) => {
if a.is_nan() && b.is_nan() {
- true // Both are NaN, treat them as equal
+ true
} else {
a.to_bits() == b.to_bits()
}
}
(Self::F64(a), Self::F64(b)) => {
if a.is_nan() && b.is_nan() {
- true // Both are NaN, treat them as equal
+ true
} else {
a.to_bits() == b.to_bits()
}
@@ -159,6 +163,54 @@ impl WasmValue {
}
}
+ fn v128_nan_eq(a: [u8; 16], b: [u8; 16]) -> bool {
+ let a_f32x4: [f32; 4] = [
+ f32::from_le_bytes([a[0], a[1], a[2], a[3]]),
+ f32::from_le_bytes([a[4], a[5], a[6], a[7]]),
+ f32::from_le_bytes([a[8], a[9], a[10], a[11]]),
+ f32::from_le_bytes([a[12], a[13], a[14], a[15]]),
+ ];
+ let b_f32x4: [f32; 4] = [
+ f32::from_le_bytes([b[0], b[1], b[2], b[3]]),
+ f32::from_le_bytes([b[4], b[5], b[6], b[7]]),
+ f32::from_le_bytes([b[8], b[9], b[10], b[11]]),
+ f32::from_le_bytes([b[12], b[13], b[14], b[15]]),
+ ];
+
+ let all_nan_match = a_f32x4.iter().zip(b_f32x4.iter()).all(|(x, y)| {
+ if x.is_nan() && y.is_nan() {
+ true
+ } else if x.is_nan() || y.is_nan() {
+ false
+ } else {
+ x.to_bits() == y.to_bits()
+ }
+ });
+
+ if all_nan_match && a_f32x4.iter().any(|x| x.is_nan()) {
+ return true;
+ }
+
+ let a_f64x2: [f64; 2] = [
+ f64::from_le_bytes([a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]]),
+ f64::from_le_bytes([a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]]),
+ ];
+ let b_f64x2: [f64; 2] = [
+ f64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]),
+ f64::from_le_bytes([b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]]),
+ ];
+
+ a_f64x2.iter().zip(b_f64x2.iter()).all(|(x, y)| {
+ if x.is_nan() && y.is_nan() {
+ true
+ } else if x.is_nan() || y.is_nan() {
+ false
+ } else {
+ x.to_bits() == y.to_bits()
+ }
+ }) && a_f64x2.iter().any(|x| x.is_nan())
+ }
+
#[doc(hidden)]
pub fn as_i32(&self) -> Option<i32> {
match self {