Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions crates/core/src/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> From<T> for TypedVal
Expand Down
18 changes: 18 additions & 0 deletions crates/core/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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); )*
Expand Down
27 changes: 6 additions & 21 deletions crates/wasmi/src/engine/translator/func/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, R>(&mut self, consteval: fn(T) -> R) -> Result<(), Error>
where
T: From<TypedVal>,
R: Into<TypedVal>,
{
bail_unreachable!(self);
if let TypedProvider::Register(_) = self.stack.peek() {
// Nothing to do.
Expand All @@ -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(())
}

Expand Down
10 changes: 5 additions & 5 deletions crates/wasmi/src/engine/translator/func/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down