diff --git a/crates/core/src/typed.rs b/crates/core/src/typed.rs index bdbd6a08db..94ab475ff3 100644 --- a/crates/core/src/typed.rs +++ b/crates/core/src/typed.rs @@ -66,16 +66,6 @@ impl TypedVal { pub fn untyped(&self) -> UntypedVal { self.value } - - /// Changes the [`ValType`] of `self` to `ty`. - /// - /// # Note - /// - /// This acts similar to a Wasm reinterpret cast and - /// the underlying `value` bits are unchanged. - pub fn reinterpret(self, ty: ValType) -> Self { - Self { ty, ..self } - } } impl From for TypedVal diff --git a/crates/core/src/wasm.rs b/crates/core/src/wasm.rs index cc7dcc7967..93dd0c338f 100644 --- a/crates/core/src/wasm.rs +++ b/crates/core/src/wasm.rs @@ -222,6 +222,7 @@ impl_untyped_val! { fn i32_wrap_i64(value: i64) -> i32 = |v| v as i32; fn i64_extend_i32_s(value: i32) -> i64 = i64::from; + fn i64_extend_i32_u(value: u32) -> u64 = u64::from; fn f32_demote_f64(value: f64) -> f32 = |v| v as f32; fn f64_promote_f32(value: f32) -> f64 = f64::from; @@ -283,6 +284,23 @@ impl_untyped_val! { fn i64_trunc_sat_f64_u(value: f64) -> u64 = TruncateSaturateInto::truncate_saturate_into; } +macro_rules! impl_reinterpret_cast { + ( $(fn $name:ident($from:ty) -> $to:ty);* $(;)? ) => { + $( + #[doc = concat!("Execute the `", stringify!($name), "` Wasm instruction.")] + pub fn $name(value: $from) -> $to { + <$to>::from_ne_bytes(<$from>::to_ne_bytes(value)) + } + )* + }; +} +impl_reinterpret_cast! { + fn i32_reinterpret_f32(f32) -> i32; + fn i64_reinterpret_f64(f64) -> i64; + fn f32_reinterpret_i32(i32) -> f32; + fn f64_reinterpret_i64(i64) -> f64; +} + macro_rules! gen_load_extend_fn { ( $( (fn $load_fn:ident, fn $load_at_fn:ident, $wrapped:ty => $ty:ty); )* diff --git a/crates/wasmi/src/engine/translator/func/mod.rs b/crates/wasmi/src/engine/translator/func/mod.rs index 72b4e10d75..2c5772bd3f 100644 --- a/crates/wasmi/src/engine/translator/func/mod.rs +++ b/crates/wasmi/src/engine/translator/func/mod.rs @@ -1976,25 +1976,11 @@ impl FuncTranslator { } /// Translates a Wasm `reinterpret` instruction. - fn translate_reinterpret(&mut self, ty: ValType) -> Result<(), Error> { - bail_unreachable!(self); - if let TypedProvider::Register(_) = self.stack.peek() { - // Nothing to do. - // - // We try to not manipulate the emulation stack if not needed. - return Ok(()); - } - // Case: At this point we know that the top-most stack item is a constant value. - // We pop it, change its type and push it back onto the stack. - let TypedProvider::Const(value) = self.stack.pop() else { - panic!("the top-most stack item was asserted to be a constant value but a register was found") - }; - self.stack.push_const(value.reinterpret(ty)); - Ok(()) - } - - /// Translates a Wasm `i64.extend_i32_u` instruction. - fn translate_i64_extend_i32_u(&mut self) -> Result<(), Error> { + fn translate_reinterpret(&mut self, consteval: fn(T) -> R) -> Result<(), Error> + where + T: From, + R: Into, + { bail_unreachable!(self); if let TypedProvider::Register(_) = self.stack.peek() { // Nothing to do. @@ -2007,8 +1993,7 @@ impl FuncTranslator { let TypedProvider::Const(value) = self.stack.pop() else { panic!("the top-most stack item was asserted to be a constant value but a register was found") }; - debug_assert_eq!(value.ty(), ValType::I32); - self.stack.push_const(u64::from(u32::from(value))); + self.stack.push_const(consteval(value.into())); Ok(()) } diff --git a/crates/wasmi/src/engine/translator/func/visit.rs b/crates/wasmi/src/engine/translator/func/visit.rs index 64e0e1aa96..064a920650 100644 --- a/crates/wasmi/src/engine/translator/func/visit.rs +++ b/crates/wasmi/src/engine/translator/func/visit.rs @@ -2844,7 +2844,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator { } fn visit_i64_extend_i32_u(&mut self) -> Self::Output { - self.translate_i64_extend_i32_u() + self.translate_reinterpret(wasm::i64_extend_i32_u) } fn visit_i64_trunc_f32_s(&mut self) -> Self::Output { @@ -2916,19 +2916,19 @@ impl<'a> VisitOperator<'a> for FuncTranslator { } fn visit_i32_reinterpret_f32(&mut self) -> Self::Output { - self.translate_reinterpret(ValType::I32) + self.translate_reinterpret(wasm::i32_reinterpret_f32) } fn visit_i64_reinterpret_f64(&mut self) -> Self::Output { - self.translate_reinterpret(ValType::I64) + self.translate_reinterpret(wasm::i64_reinterpret_f64) } fn visit_f32_reinterpret_i32(&mut self) -> Self::Output { - self.translate_reinterpret(ValType::F32) + self.translate_reinterpret(wasm::f32_reinterpret_i32) } fn visit_f64_reinterpret_i64(&mut self) -> Self::Output { - self.translate_reinterpret(ValType::F64) + self.translate_reinterpret(wasm::f64_reinterpret_i64) } fn visit_i32_extend8_s(&mut self) -> Self::Output {