wasmtime/runtime/wave/
core.rs1use crate::prelude::*;
2use std::borrow::Cow;
3
4use super::{canonicalize_nan32, canonicalize_nan64, unwrap_val};
5use wasm_wave::wasm::{WasmFunc, WasmType, WasmTypeKind, WasmValue, WasmValueError};
6
7impl WasmType for crate::ValType {
8 fn kind(&self) -> WasmTypeKind {
9 match self {
10 Self::I32 => WasmTypeKind::S32,
11 Self::I64 => WasmTypeKind::S64,
12 Self::F32 => WasmTypeKind::F32,
13 Self::F64 => WasmTypeKind::F64,
14 Self::V128 => WasmTypeKind::Tuple,
15
16 Self::Ref(_) => WasmTypeKind::Unsupported,
17 }
18 }
19
20 fn tuple_element_types(&self) -> Box<dyn Iterator<Item = Self> + '_> {
21 match *self {
22 Self::V128 => {}
23 _ => panic!("tuple_element_types called on non-tuple type"),
24 }
25 Box::new([Self::I64, Self::I64].into_iter())
26 }
27}
28
29impl WasmValue for crate::Val {
30 type Type = crate::ValType;
31
32 fn kind(&self) -> WasmTypeKind {
33 match self {
34 Self::I32(_) => WasmTypeKind::S32,
35 Self::I64(_) => WasmTypeKind::S64,
36 Self::F32(_) => WasmTypeKind::F32,
37 Self::F64(_) => WasmTypeKind::F64,
38 Self::V128(_) => WasmTypeKind::Tuple,
39 Self::FuncRef(_) => WasmTypeKind::Unsupported,
40 Self::ExternRef(_) => WasmTypeKind::Unsupported,
41 Self::AnyRef(_) => WasmTypeKind::Unsupported,
42 Self::ExnRef(_) => WasmTypeKind::Unsupported,
43 Self::ContRef(_) => WasmTypeKind::Unsupported,
44 }
45 }
46
47 fn make_s32(val: i32) -> Self {
48 Self::I32(val)
49 }
50 fn make_s64(val: i64) -> Self {
51 Self::I64(val)
52 }
53 fn make_f32(val: f32) -> Self {
54 let val = canonicalize_nan32(val);
55 Self::F32(val.to_bits())
56 }
57 fn make_f64(val: f64) -> Self {
58 let val = canonicalize_nan64(val);
59 Self::F64(val.to_bits())
60 }
61 fn make_tuple(
62 ty: &Self::Type,
63 vals: impl IntoIterator<Item = Self>,
64 ) -> Result<Self, WasmValueError> {
65 match *ty {
66 Self::Type::V128 => {}
67 _ => {
68 return Err(WasmValueError::Other(
69 "tuples only used for v128 (v64x2)".to_string(),
70 ));
71 }
72 }
73 let [l_val, h_val]: [Self; 2] = vals
74 .into_iter()
75 .collect::<Vec<_>>()
76 .try_into()
77 .map_err(|_| WasmValueError::Other("expected 2 values".to_string()))?;
78
79 let (Some(l), Some(h)) = (l_val.i64(), h_val.i64()) else {
80 return Err(WasmValueError::Other("expected 2 i64s (v64x2)".to_string()));
81 };
82 Ok(Self::V128(((h as u128) << 64 | (l as u128)).into()))
83 }
84
85 fn unwrap_s32(&self) -> i32 {
86 *unwrap_val!(self, Self::I32, "s32")
87 }
88
89 fn unwrap_s64(&self) -> i64 {
90 *unwrap_val!(self, Self::I64, "s64")
91 }
92
93 fn unwrap_f32(&self) -> f32 {
94 let val = f32::from_bits(*unwrap_val!(self, Self::F32, "f32"));
95 canonicalize_nan32(val)
96 }
97
98 fn unwrap_f64(&self) -> f64 {
99 let val = f64::from_bits(*unwrap_val!(self, Self::F64, "f64"));
100 canonicalize_nan64(val)
101 }
102 #[expect(clippy::cast_possible_truncation, reason = "handled losslessly here")]
103 fn unwrap_tuple(&self) -> Box<dyn Iterator<Item = Cow<'_, Self>> + '_> {
104 let v = unwrap_val!(self, Self::V128, "tuple").as_u128();
105 let low = v as i64;
106 let high = (v >> 64) as i64;
107 Box::new(
108 [Self::I64(low), Self::I64(high)]
109 .into_iter()
110 .map(Cow::Owned),
111 )
112 }
113}
114
115impl WasmFunc for crate::FuncType {
116 type Type = crate::ValType;
117
118 fn params(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> {
119 Box::new(self.params())
120 }
121
122 fn results(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> {
123 Box::new(self.results())
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 #[test]
130 fn core_vals_smoke_test() {
131 use crate::Val;
132 for (val, want) in [
133 (Val::I32(10), "10"),
134 (Val::I64(-10), "-10"),
135 (1.5f32.into(), "1.5"),
136 (f32::NAN.into(), "nan"),
137 (f32::INFINITY.into(), "inf"),
138 (f32::NEG_INFINITY.into(), "-inf"),
139 ((-1.5f64).into(), "-1.5"),
140 (f32::NAN.into(), "nan"),
141 (f32::INFINITY.into(), "inf"),
142 (f32::NEG_INFINITY.into(), "-inf"),
143 (
144 Val::V128(0x1234567890abcdef1122334455667788.into()),
145 "(1234605616436508552, 1311768467294899695)",
146 ),
147 ] {
148 let got = wasm_wave::to_string(&val)
149 .unwrap_or_else(|err| panic!("failed to serialize {val:?}: {err}"));
150 assert_eq!(got, want, "for {val:?}");
151 }
152 }
153}