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
This commit is contained in:
@@ -34,8 +34,8 @@ pub fn arbitrary_val(ty: &component::Type, input: &mut Unstructured) -> arbitrar
|
|||||||
Type::U32 => Val::U32(input.arbitrary()?),
|
Type::U32 => Val::U32(input.arbitrary()?),
|
||||||
Type::S64 => Val::S64(input.arbitrary()?),
|
Type::S64 => Val::S64(input.arbitrary()?),
|
||||||
Type::U64 => Val::U64(input.arbitrary()?),
|
Type::U64 => Val::U64(input.arbitrary()?),
|
||||||
Type::Float32 => Val::Float32(input.arbitrary::<f32>()?.to_bits()),
|
Type::Float32 => Val::Float32(input.arbitrary()?),
|
||||||
Type::Float64 => Val::Float64(input.arbitrary::<f64>()?.to_bits()),
|
Type::Float64 => Val::Float64(input.arbitrary()?),
|
||||||
Type::Char => Val::Char(input.arbitrary()?),
|
Type::Char => Val::Char(input.arbitrary()?),
|
||||||
Type::String => Val::String(input.arbitrary()?),
|
Type::String => Val::String(input.arbitrary()?),
|
||||||
Type::List(list) => {
|
Type::List(list) => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use std::ops::Deref;
|
|||||||
use wasmtime_component_util::{DiscriminantSize, FlagsSize};
|
use wasmtime_component_util::{DiscriminantSize, FlagsSize};
|
||||||
use wasmtime_environ::component::VariantInfo;
|
use wasmtime_environ::component::VariantInfo;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct List {
|
pub struct List {
|
||||||
ty: types::List,
|
ty: types::List,
|
||||||
values: Box<[Val]>,
|
values: Box<[Val]>,
|
||||||
@@ -57,7 +57,7 @@ impl fmt::Debug for List {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
ty: types::Record,
|
ty: types::Record,
|
||||||
values: Box<[Val]>,
|
values: Box<[Val]>,
|
||||||
@@ -127,7 +127,7 @@ impl fmt::Debug for Record {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct Tuple {
|
pub struct Tuple {
|
||||||
ty: types::Tuple,
|
ty: types::Tuple,
|
||||||
values: Box<[Val]>,
|
values: Box<[Val]>,
|
||||||
@@ -176,7 +176,7 @@ impl fmt::Debug for Tuple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct Variant {
|
pub struct Variant {
|
||||||
ty: types::Variant,
|
ty: types::Variant,
|
||||||
discriminant: u32,
|
discriminant: u32,
|
||||||
@@ -284,7 +284,7 @@ impl fmt::Debug for Enum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct Union {
|
pub struct Union {
|
||||||
ty: types::Union,
|
ty: types::Union,
|
||||||
discriminant: u32,
|
discriminant: u32,
|
||||||
@@ -336,7 +336,7 @@ impl fmt::Debug for Union {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct OptionVal {
|
pub struct OptionVal {
|
||||||
ty: types::OptionType,
|
ty: types::OptionType,
|
||||||
discriminant: u32,
|
discriminant: u32,
|
||||||
@@ -378,7 +378,7 @@ impl fmt::Debug for OptionVal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct ResultVal {
|
pub struct ResultVal {
|
||||||
ty: types::ResultType,
|
ty: types::ResultType,
|
||||||
discriminant: u32,
|
discriminant: u32,
|
||||||
@@ -487,7 +487,7 @@ impl fmt::Debug for Flags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Represents possible runtime values which a component function can either consume or produce
|
/// 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)]
|
#[allow(missing_docs)]
|
||||||
pub enum Val {
|
pub enum Val {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
@@ -499,8 +499,8 @@ pub enum Val {
|
|||||||
U32(u32),
|
U32(u32),
|
||||||
S64(i64),
|
S64(i64),
|
||||||
U64(u64),
|
U64(u64),
|
||||||
Float32(u32),
|
Float32(f32),
|
||||||
Float64(u64),
|
Float64(f64),
|
||||||
Char(char),
|
Char(char),
|
||||||
String(Box<str>),
|
String(Box<str>),
|
||||||
List(List),
|
List(List),
|
||||||
@@ -560,8 +560,8 @@ impl Val {
|
|||||||
Type::U32 => Val::U32(u32::lift(store, options, next(src))?),
|
Type::U32 => Val::U32(u32::lift(store, options, next(src))?),
|
||||||
Type::S64 => Val::S64(i64::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::U64 => Val::U64(u64::lift(store, options, next(src))?),
|
||||||
Type::Float32 => Val::Float32(u32::lift(store, options, next(src))?),
|
Type::Float32 => Val::Float32(f32::lift(store, options, next(src))?),
|
||||||
Type::Float64 => Val::Float64(u64::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::Char => Val::Char(char::lift(store, options, next(src))?),
|
||||||
Type::String => {
|
Type::String => {
|
||||||
Val::String(Box::<str>::lift(store, options, &[*next(src), *next(src)])?)
|
Val::String(Box::<str>::lift(store, options, &[*next(src), *next(src)])?)
|
||||||
@@ -688,8 +688,8 @@ impl Val {
|
|||||||
Type::U32 => Val::U32(u32::load(mem, bytes)?),
|
Type::U32 => Val::U32(u32::load(mem, bytes)?),
|
||||||
Type::S64 => Val::S64(i64::load(mem, bytes)?),
|
Type::S64 => Val::S64(i64::load(mem, bytes)?),
|
||||||
Type::U64 => Val::U64(u64::load(mem, bytes)?),
|
Type::U64 => Val::U64(u64::load(mem, bytes)?),
|
||||||
Type::Float32 => Val::Float32(u32::load(mem, bytes)?),
|
Type::Float32 => Val::Float32(f32::load(mem, bytes)?),
|
||||||
Type::Float64 => Val::Float64(u64::load(mem, bytes)?),
|
Type::Float64 => Val::Float64(f64::load(mem, bytes)?),
|
||||||
Type::Char => Val::Char(char::load(mem, bytes)?),
|
Type::Char => Val::Char(char::load(mem, bytes)?),
|
||||||
Type::String => Val::String(Box::<str>::load(mem, bytes)?),
|
Type::String => Val::String(Box::<str>::load(mem, bytes)?),
|
||||||
Type::List(handle) => {
|
Type::List(handle) => {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ pub fn val(v: &WastVal<'_>, ty: &Type) -> Result<Val> {
|
|||||||
WastVal::S32(b) => Val::S32(*b),
|
WastVal::S32(b) => Val::S32(*b),
|
||||||
WastVal::U64(b) => Val::U64(*b),
|
WastVal::U64(b) => Val::U64(*b),
|
||||||
WastVal::S64(b) => Val::S64(*b),
|
WastVal::S64(b) => Val::S64(*b),
|
||||||
WastVal::Float32(b) => Val::Float32(b.bits),
|
WastVal::Float32(b) => Val::Float32(f32::from_bits(b.bits)),
|
||||||
WastVal::Float64(b) => Val::Float64(b.bits),
|
WastVal::Float64(b) => Val::Float64(f64::from_bits(b.bits)),
|
||||||
WastVal::Char(b) => Val::Char(*b),
|
WastVal::Char(b) => Val::Char(*b),
|
||||||
WastVal::String(s) => Val::String(s.to_string().into()),
|
WastVal::String(s) => Val::String(s.to_string().into()),
|
||||||
WastVal::List(vals) => match ty {
|
WastVal::List(vals) => match ty {
|
||||||
@@ -173,11 +173,11 @@ pub fn match_val(expected: &WastVal<'_>, actual: &Val) -> Result<()> {
|
|||||||
_ => mismatch(expected, actual),
|
_ => mismatch(expected, actual),
|
||||||
},
|
},
|
||||||
WastVal::Float32(e) => match 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),
|
_ => mismatch(expected, actual),
|
||||||
},
|
},
|
||||||
WastVal::Float64(e) => match 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),
|
_ => mismatch(expected, actual),
|
||||||
},
|
},
|
||||||
WastVal::Char(e) => match actual {
|
WastVal::Char(e) => match actual {
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ fn primitives() -> Result<()> {
|
|||||||
(Val::S64(-31415926535897), "s64", Param(Type::I64, Some(0))),
|
(Val::S64(-31415926535897), "s64", Param(Type::I64, Some(0))),
|
||||||
(Val::U64(31415926535897), "u64", 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",
|
"float32",
|
||||||
Param(Type::F32, Some(0)),
|
Param(Type::F32, Some(0)),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Val::Float64(3.14159265_f64.to_bits()),
|
Val::Float64(3.14159265),
|
||||||
"float64",
|
"float64",
|
||||||
Param(Type::F64, Some(0)),
|
Param(Type::F64, Some(0)),
|
||||||
),
|
),
|
||||||
@@ -59,10 +59,7 @@ fn primitives() -> Result<()> {
|
|||||||
let err = func
|
let err = func
|
||||||
.call_and_post_return(
|
.call_and_post_return(
|
||||||
&mut store,
|
&mut store,
|
||||||
&[
|
&[Val::Float64(3.14159265), Val::Float64(3.14159265)],
|
||||||
Val::Float64(3.14159265_f64.to_bits()),
|
|
||||||
Val::Float64(3.14159265_f64.to_bits()),
|
|
||||||
],
|
|
||||||
&mut output,
|
&mut output,
|
||||||
)
|
)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
@@ -135,7 +132,7 @@ fn lists() -> Result<()> {
|
|||||||
.new_val(Box::new([
|
.new_val(Box::new([
|
||||||
Val::U32(32343),
|
Val::U32(32343),
|
||||||
Val::U32(79023439),
|
Val::U32(79023439),
|
||||||
Val::Float32(3.14159265_f32.to_bits()),
|
Val::Float32(3.14159265),
|
||||||
]))
|
]))
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
|
||||||
@@ -167,7 +164,7 @@ fn records() -> Result<()> {
|
|||||||
let inner_type = &ty.unwrap_record().fields().nth(2).unwrap().ty;
|
let inner_type = &ty.unwrap_record().fields().nth(2).unwrap().ty;
|
||||||
let input = ty.unwrap_record().new_val([
|
let input = ty.unwrap_record().new_val([
|
||||||
("A", Val::U32(32343)),
|
("A", Val::U32(32343)),
|
||||||
("B", Val::Float64(3.14159265_f64.to_bits())),
|
("B", Val::Float64(3.14159265)),
|
||||||
(
|
(
|
||||||
"C",
|
"C",
|
||||||
inner_type
|
inner_type
|
||||||
@@ -186,7 +183,7 @@ fn records() -> Result<()> {
|
|||||||
.unwrap_record()
|
.unwrap_record()
|
||||||
.new_val([
|
.new_val([
|
||||||
("A", Val::S32(32343)),
|
("A", Val::S32(32343)),
|
||||||
("B", Val::Float64(3.14159265_f64.to_bits())),
|
("B", Val::Float64(3.14159265)),
|
||||||
(
|
(
|
||||||
"C",
|
"C",
|
||||||
inner_type
|
inner_type
|
||||||
@@ -204,7 +201,7 @@ fn records() -> Result<()> {
|
|||||||
.unwrap_record()
|
.unwrap_record()
|
||||||
.new_val([
|
.new_val([
|
||||||
("A", Val::U32(32343)),
|
("A", Val::U32(32343)),
|
||||||
("B", Val::Float64(3.14159265_f64.to_bits())),
|
("B", Val::Float64(3.14159265)),
|
||||||
(
|
(
|
||||||
"C",
|
"C",
|
||||||
inner_type
|
inner_type
|
||||||
@@ -224,10 +221,7 @@ fn records() -> Result<()> {
|
|||||||
|
|
||||||
let err = ty
|
let err = ty
|
||||||
.unwrap_record()
|
.unwrap_record()
|
||||||
.new_val([
|
.new_val([("A", Val::U32(32343)), ("B", Val::Float64(3.14159265))])
|
||||||
("A", Val::U32(32343)),
|
|
||||||
("B", Val::Float64(3.14159265_f64.to_bits())),
|
|
||||||
])
|
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
@@ -259,7 +253,7 @@ fn variants() -> Result<()> {
|
|||||||
let ty = &func.params(&store)[0];
|
let ty = &func.params(&store)[0];
|
||||||
let input = ty
|
let input = ty
|
||||||
.unwrap_variant()
|
.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)];
|
let mut output = [Val::Bool(false)];
|
||||||
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
|
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
|
||||||
|
|
||||||
@@ -481,14 +475,14 @@ fn everything() -> Result<()> {
|
|||||||
"J",
|
"J",
|
||||||
j_type
|
j_type
|
||||||
.unwrap_variant()
|
.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)),
|
("P", Val::S8(42)),
|
||||||
("Q", Val::S16(4242)),
|
("Q", Val::S16(4242)),
|
||||||
("R", Val::S32(42424242)),
|
("R", Val::S32(42424242)),
|
||||||
("S", Val::S64(424242424242424242)),
|
("S", Val::S64(424242424242424242)),
|
||||||
("T", Val::Float32(3.14159265_f32.to_bits())),
|
("T", Val::Float32(3.14159265)),
|
||||||
("U", Val::Float64(3.14159265_f64.to_bits())),
|
("U", Val::Float64(3.14159265)),
|
||||||
("V", Val::String(Box::from("wow, nice types"))),
|
("V", Val::String(Box::from("wow, nice types"))),
|
||||||
("W", Val::Char('🦀')),
|
("W", Val::Char('🦀')),
|
||||||
(
|
(
|
||||||
@@ -499,9 +493,7 @@ fn everything() -> Result<()> {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Z",
|
"Z",
|
||||||
z_type
|
z_type.unwrap_union().new_val(1, Val::Float64(3.14159265))?,
|
||||||
.unwrap_union()
|
|
||||||
.new_val(1, Val::Float64(3.14159265_f64.to_bits()))?,
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"AA",
|
"AA",
|
||||||
|
|||||||
Reference in New Issue
Block a user