From 0029ff95acf4a2582c82ed082d07af8b9f457b8d Mon Sep 17 00:00:00 2001 From: Lann Date: Tue, 3 Jan 2023 15:23:38 -0500 Subject: [PATCH] Use floats for `wasmtime::component::Val::Float*` (#5510) The definitions of `wasmtime::component::Val::Float{32,64}` mirrored `wasmtime::Val::F{32,64}` by using integers as their wrapped types, storing the bit representation of their floating point values. This was necessary for the core Wasm `f32`/`f64` types because Rust floats don't have guaranteed NaN bit representations. The component model `float32`/`float64` types require NaN canonicalization, so we can use normal Rust `f{32,64}` instead. Closes #5480 --- .../fuzzing/src/generators/component_types.rs | 4 +-- crates/wasmtime/src/component/values.rs | 28 +++++++-------- crates/wast/src/component.rs | 8 ++--- tests/all/component_model/dynamic.rs | 34 +++++++------------ 4 files changed, 33 insertions(+), 41 deletions(-) diff --git a/crates/fuzzing/src/generators/component_types.rs b/crates/fuzzing/src/generators/component_types.rs index 0c83bf10cf..05a008ab30 100644 --- a/crates/fuzzing/src/generators/component_types.rs +++ b/crates/fuzzing/src/generators/component_types.rs @@ -34,8 +34,8 @@ pub fn arbitrary_val(ty: &component::Type, input: &mut Unstructured) -> arbitrar Type::U32 => Val::U32(input.arbitrary()?), Type::S64 => Val::S64(input.arbitrary()?), Type::U64 => Val::U64(input.arbitrary()?), - Type::Float32 => Val::Float32(input.arbitrary::()?.to_bits()), - Type::Float64 => Val::Float64(input.arbitrary::()?.to_bits()), + Type::Float32 => Val::Float32(input.arbitrary()?), + Type::Float64 => Val::Float64(input.arbitrary()?), Type::Char => Val::Char(input.arbitrary()?), Type::String => Val::String(input.arbitrary()?), Type::List(list) => { diff --git a/crates/wasmtime/src/component/values.rs b/crates/wasmtime/src/component/values.rs index 9f87ba1a5c..41c41c1242 100644 --- a/crates/wasmtime/src/component/values.rs +++ b/crates/wasmtime/src/component/values.rs @@ -11,7 +11,7 @@ use std::ops::Deref; use wasmtime_component_util::{DiscriminantSize, FlagsSize}; use wasmtime_environ::component::VariantInfo; -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct List { ty: types::List, values: Box<[Val]>, @@ -57,7 +57,7 @@ impl fmt::Debug for List { } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct Record { ty: types::Record, values: Box<[Val]>, @@ -127,7 +127,7 @@ impl fmt::Debug for Record { } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct Tuple { ty: types::Tuple, values: Box<[Val]>, @@ -176,7 +176,7 @@ impl fmt::Debug for Tuple { } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct Variant { ty: types::Variant, discriminant: u32, @@ -284,7 +284,7 @@ impl fmt::Debug for Enum { } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct Union { ty: types::Union, discriminant: u32, @@ -336,7 +336,7 @@ impl fmt::Debug for Union { } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct OptionVal { ty: types::OptionType, discriminant: u32, @@ -378,7 +378,7 @@ impl fmt::Debug for OptionVal { } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Clone)] pub struct ResultVal { ty: types::ResultType, discriminant: u32, @@ -487,7 +487,7 @@ impl fmt::Debug for Flags { } /// Represents possible runtime values which a component function can either consume or produce -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone, PartialEq)] #[allow(missing_docs)] pub enum Val { Bool(bool), @@ -499,8 +499,8 @@ pub enum Val { U32(u32), S64(i64), U64(u64), - Float32(u32), - Float64(u64), + Float32(f32), + Float64(f64), Char(char), String(Box), List(List), @@ -560,8 +560,8 @@ impl Val { Type::U32 => Val::U32(u32::lift(store, options, next(src))?), Type::S64 => Val::S64(i64::lift(store, options, next(src))?), Type::U64 => Val::U64(u64::lift(store, options, next(src))?), - Type::Float32 => Val::Float32(u32::lift(store, options, next(src))?), - Type::Float64 => Val::Float64(u64::lift(store, options, next(src))?), + Type::Float32 => Val::Float32(f32::lift(store, options, next(src))?), + Type::Float64 => Val::Float64(f64::lift(store, options, next(src))?), Type::Char => Val::Char(char::lift(store, options, next(src))?), Type::String => { Val::String(Box::::lift(store, options, &[*next(src), *next(src)])?) @@ -688,8 +688,8 @@ impl Val { Type::U32 => Val::U32(u32::load(mem, bytes)?), Type::S64 => Val::S64(i64::load(mem, bytes)?), Type::U64 => Val::U64(u64::load(mem, bytes)?), - Type::Float32 => Val::Float32(u32::load(mem, bytes)?), - Type::Float64 => Val::Float64(u64::load(mem, bytes)?), + Type::Float32 => Val::Float32(f32::load(mem, bytes)?), + Type::Float64 => Val::Float64(f64::load(mem, bytes)?), Type::Char => Val::Char(char::load(mem, bytes)?), Type::String => Val::String(Box::::load(mem, bytes)?), Type::List(handle) => { diff --git a/crates/wast/src/component.rs b/crates/wast/src/component.rs index 8a88538bb0..425689de49 100644 --- a/crates/wast/src/component.rs +++ b/crates/wast/src/component.rs @@ -18,8 +18,8 @@ pub fn val(v: &WastVal<'_>, ty: &Type) -> Result { WastVal::S32(b) => Val::S32(*b), WastVal::U64(b) => Val::U64(*b), WastVal::S64(b) => Val::S64(*b), - WastVal::Float32(b) => Val::Float32(b.bits), - WastVal::Float64(b) => Val::Float64(b.bits), + WastVal::Float32(b) => Val::Float32(f32::from_bits(b.bits)), + WastVal::Float64(b) => Val::Float64(f64::from_bits(b.bits)), WastVal::Char(b) => Val::Char(*b), WastVal::String(s) => Val::String(s.to_string().into()), WastVal::List(vals) => match ty { @@ -173,11 +173,11 @@ pub fn match_val(expected: &WastVal<'_>, actual: &Val) -> Result<()> { _ => mismatch(expected, actual), }, WastVal::Float32(e) => match actual { - Val::Float32(a) => core::match_f32(*a, &NanPattern::Value(*e)), + Val::Float32(a) => core::match_f32(a.to_bits(), &NanPattern::Value(*e)), _ => mismatch(expected, actual), }, WastVal::Float64(e) => match actual { - Val::Float64(a) => core::match_f64(*a, &NanPattern::Value(*e)), + Val::Float64(a) => core::match_f64(a.to_bits(), &NanPattern::Value(*e)), _ => mismatch(expected, actual), }, WastVal::Char(e) => match actual { diff --git a/tests/all/component_model/dynamic.rs b/tests/all/component_model/dynamic.rs index e24ac80ff8..b71553493c 100644 --- a/tests/all/component_model/dynamic.rs +++ b/tests/all/component_model/dynamic.rs @@ -21,12 +21,12 @@ fn primitives() -> Result<()> { (Val::S64(-31415926535897), "s64", Param(Type::I64, Some(0))), (Val::U64(31415926535897), "u64", Param(Type::I64, Some(0))), ( - Val::Float32(3.14159265_f32.to_bits()), + Val::Float32(3.14159265), "float32", Param(Type::F32, Some(0)), ), ( - Val::Float64(3.14159265_f64.to_bits()), + Val::Float64(3.14159265), "float64", Param(Type::F64, Some(0)), ), @@ -59,10 +59,7 @@ fn primitives() -> Result<()> { let err = func .call_and_post_return( &mut store, - &[ - Val::Float64(3.14159265_f64.to_bits()), - Val::Float64(3.14159265_f64.to_bits()), - ], + &[Val::Float64(3.14159265), Val::Float64(3.14159265)], &mut output, ) .unwrap_err(); @@ -135,7 +132,7 @@ fn lists() -> Result<()> { .new_val(Box::new([ Val::U32(32343), Val::U32(79023439), - Val::Float32(3.14159265_f32.to_bits()), + Val::Float32(3.14159265), ])) .unwrap_err(); @@ -167,7 +164,7 @@ fn records() -> Result<()> { let inner_type = &ty.unwrap_record().fields().nth(2).unwrap().ty; let input = ty.unwrap_record().new_val([ ("A", Val::U32(32343)), - ("B", Val::Float64(3.14159265_f64.to_bits())), + ("B", Val::Float64(3.14159265)), ( "C", inner_type @@ -186,7 +183,7 @@ fn records() -> Result<()> { .unwrap_record() .new_val([ ("A", Val::S32(32343)), - ("B", Val::Float64(3.14159265_f64.to_bits())), + ("B", Val::Float64(3.14159265)), ( "C", inner_type @@ -204,7 +201,7 @@ fn records() -> Result<()> { .unwrap_record() .new_val([ ("A", Val::U32(32343)), - ("B", Val::Float64(3.14159265_f64.to_bits())), + ("B", Val::Float64(3.14159265)), ( "C", inner_type @@ -224,10 +221,7 @@ fn records() -> Result<()> { let err = ty .unwrap_record() - .new_val([ - ("A", Val::U32(32343)), - ("B", Val::Float64(3.14159265_f64.to_bits())), - ]) + .new_val([("A", Val::U32(32343)), ("B", Val::Float64(3.14159265))]) .unwrap_err(); assert!( @@ -259,7 +253,7 @@ fn variants() -> Result<()> { let ty = &func.params(&store)[0]; let input = ty .unwrap_variant() - .new_val("B", Some(Val::Float64(3.14159265_f64.to_bits())))?; + .new_val("B", Some(Val::Float64(3.14159265)))?; let mut output = [Val::Bool(false)]; func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; @@ -481,14 +475,14 @@ fn everything() -> Result<()> { "J", j_type .unwrap_variant() - .new_val("L", Some(Val::Float64(3.14159265_f64.to_bits())))?, + .new_val("L", Some(Val::Float64(3.14159265)))?, ), ("P", Val::S8(42)), ("Q", Val::S16(4242)), ("R", Val::S32(42424242)), ("S", Val::S64(424242424242424242)), - ("T", Val::Float32(3.14159265_f32.to_bits())), - ("U", Val::Float64(3.14159265_f64.to_bits())), + ("T", Val::Float32(3.14159265)), + ("U", Val::Float64(3.14159265)), ("V", Val::String(Box::from("wow, nice types"))), ("W", Val::Char('🦀')), ( @@ -499,9 +493,7 @@ fn everything() -> Result<()> { ), ( "Z", - z_type - .unwrap_union() - .new_val(1, Val::Float64(3.14159265_f64.to_bits()))?, + z_type.unwrap_union().new_val(1, Val::Float64(3.14159265))?, ), ( "AA",