summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2025-04-26 17:43:23 +0200
committerHenry Gressmann <mail@henrygressmann.de>2025-04-26 17:43:23 +0200
commite1b76386b7e323054d5e8844366ebad86bba693e (patch)
treeed5ab4829ce1c20dc3bfe7bd4e1f65f0febbc07c
parentc1a8cfad737cc79772b44a99088bcccd0ab6ee02 (diff)
feat: add canonicalize_nans feature
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
-rw-r--r--CHANGELOG.md3
-rw-r--r--Cargo.lock20
-rw-r--r--crates/tinywasm/Cargo.toml10
-rw-r--r--crates/tinywasm/src/interpreter/num_helpers.rs29
4 files changed, 47 insertions, 15 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e63ff2b..8c47dea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for the custom memory page sizes proposal ([#22](https://github.com/explodingcamera/tinywasm/pull/22) by [@danielstuart14](https://github.com/danielstuart14))
- Support for the `tail_call` proposal
+- Support for the `memory64` proposal
+- Groundwork for the `simd` proposal
+- New `canonicalize_nans` feature flag to enable canonicalizing NaN values in the `f32`, `f64`, and `v128` types
### Breaking Changes
diff --git a/Cargo.lock b/Cargo.lock
index acdc41b..f194530 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -114,18 +114,18 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.36"
+version = "4.5.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
+checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
-version = "4.5.36"
+version = "4.5.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
+checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
dependencies = [
"anstyle",
"clap_lex",
@@ -353,15 +353,15 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
-version = "0.2.171"
+version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libm"
-version = "0.2.11"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
+checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72"
[[package]]
name = "log"
@@ -426,9 +426,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.94"
+version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml
index 3281476..10a3099 100644
--- a/crates/tinywasm/Cargo.toml
+++ b/crates/tinywasm/Cargo.toml
@@ -32,12 +32,20 @@ serde_json={version="1.0"}
serde={version="1.0", features=["derive"]}
[features]
-default=["std", "parser", "logging", "archive"]
+default=["std", "parser", "logging", "archive", "canonicalize_nans"]
+
logging=["log", "tinywasm-parser?/logging", "tinywasm-types/logging"]
std=["tinywasm-parser?/std", "tinywasm-types/std"]
+
+# support for parsing WebAssembly
parser=["dep:tinywasm-parser"]
+
+# support for "archiving" tinywasm bytecode
archive=["tinywasm-types/archive"]
+# canonicalize all NaN values to a single representation
+canonicalize_nans=[]
+
# enable simd support (unstable / unfinished)
__simd=[]
diff --git a/crates/tinywasm/src/interpreter/num_helpers.rs b/crates/tinywasm/src/interpreter/num_helpers.rs
index 678c32e..7e8a461 100644
--- a/crates/tinywasm/src/interpreter/num_helpers.rs
+++ b/crates/tinywasm/src/interpreter/num_helpers.rs
@@ -72,9 +72,12 @@ macro_rules! impl_wasm_float_ops {
($($t:ty)*) => ($(
impl TinywasmFloatExt for $t {
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest
+ #[inline]
fn tw_nearest(self) -> Self {
match self {
- // x if x.is_nan() => x, // preserve NaN
+ #[cfg(not(feature = "canonicalize_nans"))]
+ x if x.is_nan() => x, // preserve NaN
+ #[cfg(feature = "canonicalize_nans")]
x if x.is_nan() => Self::NAN, // Do not preserve NaN
x if x.is_infinite() || x == 0.0 => x, // preserve infinities and zeros
x if (0.0..=0.5).contains(&x) => 0.0,
@@ -100,7 +103,9 @@ macro_rules! impl_wasm_float_ops {
Some(core::cmp::Ordering::Less) => self,
Some(core::cmp::Ordering::Greater) => other,
Some(core::cmp::Ordering::Equal) => if self.is_sign_negative() && other.is_sign_positive() { self } else { other },
- // None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ #[cfg(not(feature = "canonicalize_nans"))]
+ None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ #[cfg(feature = "canonicalize_nans")]
None => Self::NAN, // Do not preserve NaN
}
}
@@ -113,7 +118,9 @@ macro_rules! impl_wasm_float_ops {
Some(core::cmp::Ordering::Greater) => self,
Some(core::cmp::Ordering::Less) => other,
Some(core::cmp::Ordering::Equal) => if self.is_sign_negative() && other.is_sign_positive() { other } else { self },
- // None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ #[cfg(not(feature = "canonicalize_nans"))]
+ None => self + other, // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ #[cfg(feature = "canonicalize_nans")]
None => Self::NAN, // Do not preserve NaN
}
}
@@ -184,8 +191,15 @@ macro_rules! impl_checked_wrapping_rem {
impl_checked_wrapping_rem! { i32 i64 u32 u64 }
-#[cfg(feature = "__simd")]
+#[cfg(all(feature = "__simd", not(feature = "canonicalize_nans")))]
+#[inline]
+pub(crate) fn canonicalize_f32x4(x: core::simd::f32x4) -> core::simd::f32x4 {
+ x // No need to do anything, as we are not replacing NaNs
+}
+
+#[cfg(all(feature = "__simd", feature = "canonicalize_nans"))]
/// replace all NaNs in a f32x4 with f32::NAN
+#[inline]
pub(crate) fn canonicalize_f32x4(x: core::simd::f32x4) -> core::simd::f32x4 {
use core::simd::{Simd, num::SimdFloat};
let nan = Simd::splat(f32::NAN);
@@ -193,8 +207,15 @@ pub(crate) fn canonicalize_f32x4(x: core::simd::f32x4) -> core::simd::f32x4 {
mask.select(nan, x)
}
+#[cfg(all(feature = "__simd", not(feature = "canonicalize_nans")))]
+#[inline]
+pub(crate) fn canonicalize_f64x2(x: core::simd::f64x2) -> core::simd::f64x2 {
+ x // No need to do anything, as we are not replacing NaNs
+}
+
#[cfg(feature = "__simd")]
/// replace all NaNs in a f64x2 with f64::NAN
+#[inline]
pub(crate) fn canonicalize_f64x2(x: core::simd::f64x2) -> core::simd::f64x2 {
use core::simd::{Simd, num::SimdFloat};
let nan = Simd::splat(f64::NAN);