#![allow(dead_code)]
use super::IntoResult as _;
use crate::{
TrapCode,
ValType,
core::{IntoShiftAmount, ShiftAmount, Typed, TypedRawVal, wasm},
engine::eval,
ir::{Op, Slot},
};
use core::num::NonZero;
pub trait CommutativeBinaryOp: Sized {
type Result: Typed + Into<TypedRawVal>;
type Input: Typed + From<TypedRawVal>;
const VT: CommutativeBinaryOpVt = CommutativeBinaryOpVt {
result_ty: <Self::Result as Typed>::TY,
consteval: commutative_consteval_vt::<Self>,
op_rrr: Self::op_rrr,
op_rrs: Self::op_rrs,
op_rri: commutative_op_rri_vt::<Self>,
op_rss: Self::op_rss,
op_rsi: commutative_op_rsi_vt::<Self>,
};
fn consteval(lhs: Self::Input, rhs: Self::Input) -> Result<Self::Result, TrapCode>;
fn op_rrr() -> Option<Op> {
None
}
fn op_rrs(rhs: Slot) -> Op;
fn op_rri(rhs: Self::Input) -> Op;
fn op_rss(lhs: Slot, rhs: Slot) -> Op;
fn op_rsi(lhs: Slot, rhs: Self::Input) -> Op;
}
pub struct CommutativeBinaryOpVt {
pub result_ty: ValType,
pub consteval: fn(lhs: TypedRawVal, rhs: TypedRawVal) -> Result<TypedRawVal, TrapCode>,
pub op_rrr: fn() -> Option<Op>,
pub op_rrs: fn(rhs: Slot) -> Op,
pub op_rri: fn(rhs: TypedRawVal) -> Op,
pub op_rss: fn(lhs: Slot, rhs: Slot) -> Op,
pub op_rsi: fn(lhs: Slot, rhs: TypedRawVal) -> Op,
}
fn commutative_consteval_vt<T: CommutativeBinaryOp>(
lhs: TypedRawVal,
rhs: TypedRawVal,
) -> Result<TypedRawVal, TrapCode> {
T::consteval(lhs.into(), rhs.into()).map(Into::into)
}
fn commutative_op_rri_vt<T: CommutativeBinaryOp>(rhs: TypedRawVal) -> Op {
T::op_rri(rhs.into())
}
fn commutative_op_rsi_vt<T: CommutativeBinaryOp>(lhs: Slot, rhs: TypedRawVal) -> Op {
T::op_rsi(lhs, rhs.into())
}
pub trait BinaryOp: Sized {
type Result: Typed + Into<TypedRawVal>;
type Lhs: Typed + From<TypedRawVal>;
type Rhs: Typed + RhsImmediate;
const VT: BinaryOpVt = BinaryOpVt {
result_ty: <Self::Result as Typed>::TY,
decode_rhs: binary_decode_rhs_vt::<Self>,
consteval: binary_consteval_vt::<Self>,
op_rrr: Self::op_rrr,
op_rrs: Self::op_rrs,
op_rri: binary_op_rri_vt::<Self>,
op_rsr: Self::op_rsr,
op_rss: Self::op_rss,
op_rsi: binary_op_rsi_vt::<Self>,
op_rir: binary_op_rir_vt::<Self>,
op_ris: binary_op_ris_vt::<Self>,
};
fn decode_rhs(rhs: TypedRawVal) -> BinaryOpRhs<Self::Rhs>;
fn consteval(lhs: Self::Lhs, rhs: Self::Rhs) -> Result<Self::Result, TrapCode>;
fn op_rrr() -> Option<Op> {
None
}
fn op_rrs(rhs: Slot) -> Op;
fn op_rri(rhs: Self::Rhs) -> Op;
fn op_rsr(lhs: Slot) -> Op;
fn op_rss(lhs: Slot, rhs: Slot) -> Op;
fn op_rsi(lhs: Slot, rhs: Self::Rhs) -> Op;
fn op_rir(lhs: Self::Lhs) -> Op;
fn op_ris(lhs: Self::Lhs, rhs: Slot) -> Op;
}
pub struct BinaryOpVt {
pub result_ty: ValType,
pub decode_rhs: fn(rhs: TypedRawVal) -> BinaryOpRhs<TypedRawVal>,
pub consteval: fn(lhs: TypedRawVal, rhs: TypedRawVal) -> Result<TypedRawVal, TrapCode>,
pub op_rrr: fn() -> Option<Op>,
pub op_rrs: fn(rhs: Slot) -> Op,
pub op_rri: fn(rhs: TypedRawVal) -> Op,
pub op_rsr: fn(lhs: Slot) -> Op,
pub op_rss: fn(lhs: Slot, rhs: Slot) -> Op,
pub op_rsi: fn(lhs: Slot, rhs: TypedRawVal) -> Op,
pub op_rir: fn(lhs: TypedRawVal) -> Op,
pub op_ris: fn(lhs: TypedRawVal, rhs: Slot) -> Op,
}
fn binary_decode_rhs_vt<T: BinaryOp>(rhs: TypedRawVal) -> BinaryOpRhs<TypedRawVal> {
match T::decode_rhs(rhs) {
BinaryOpRhs::Value(rhs) => BinaryOpRhs::Value(rhs.into_typed()),
BinaryOpRhs::Trap(trap_code) => BinaryOpRhs::Trap(trap_code),
BinaryOpRhs::ReturnLhs => BinaryOpRhs::ReturnLhs,
}
}
fn binary_consteval_vt<T: BinaryOp>(
lhs: TypedRawVal,
rhs: TypedRawVal,
) -> Result<TypedRawVal, TrapCode> {
T::consteval(lhs.into(), <T::Rhs as RhsImmediate>::from_typed(rhs)).map(Into::into)
}
fn binary_op_rri_vt<T: BinaryOp>(rhs: TypedRawVal) -> Op {
T::op_rri(<T::Rhs as RhsImmediate>::from_typed(rhs))
}
fn binary_op_rsi_vt<T: BinaryOp>(lhs: Slot, rhs: TypedRawVal) -> Op {
T::op_rsi(lhs, <T::Rhs as RhsImmediate>::from_typed(rhs))
}
fn binary_op_rir_vt<T: BinaryOp>(lhs: TypedRawVal) -> Op {
T::op_rir(lhs.into())
}
fn binary_op_ris_vt<T: BinaryOp>(lhs: TypedRawVal, rhs: Slot) -> Op {
T::op_ris(lhs.into(), rhs)
}
pub trait RhsImmediate: Sized {
fn into_typed(self) -> TypedRawVal;
fn from_typed(value: TypedRawVal) -> Self;
}
macro_rules! impl_rhs_immediate_for {
( $($ty:ty),* $(,)? ) => {
$(
impl RhsImmediate for $ty {
fn into_typed(self) -> TypedRawVal {
self.into()
}
fn from_typed(value: TypedRawVal) -> Self {
value.into()
}
}
)*
};
}
impl_rhs_immediate_for!(i32, u32, i64, u64, f32, f64);
macro_rules! impl_rhs_immediate_for_nonzero {
( $($ty:ty),* $(,)? ) => {
$(
impl RhsImmediate for NonZero<$ty> {
fn into_typed(self) -> TypedRawVal {
self.into()
}
fn from_typed(value: TypedRawVal) -> Self {
match Self::new(<$ty>::from(value)) {
Some(value) => value,
None => unreachable!(),
}
}
}
)*
};
}
impl_rhs_immediate_for_nonzero!(i32, u32, i64, u64);
impl RhsImmediate for ShiftAmount {
fn into_typed(self) -> TypedRawVal {
u8::from(self).into()
}
fn from_typed(value: TypedRawVal) -> Self {
Self::from(u8::from(value))
}
}
macro_rules! impl_commutative_binary_op_for {
(
$(
impl CommutativeBinaryOp for $name:ident {
type Result = $res_ty:ty;
type Input = $input_ty:ty;
fn consteval = $consteval:expr;
$( fn op_rrr = $op_rrr:expr; )?
fn op_rrs = $op_rrs:expr;
fn op_rri = $op_rri:expr;
fn op_rss = $op_rss:expr;
fn op_rsi = $op_rsi:expr;
}
)*
) => {
$(
pub enum $name {}
impl CommutativeBinaryOp for $name {
type Result = $res_ty;
type Input = $input_ty;
fn consteval(lhs: Self::Input, rhs: Self::Input) -> Result<Self::Result, TrapCode> {
$consteval(lhs, rhs).into_result()
}
$(
fn op_rrr() -> Option<Op> {
Some($op_rrr)
}
)?
fn op_rrs(rhs: Slot) -> Op {
$op_rrs(rhs)
}
fn op_rri(rhs: Self::Input) -> Op {
$op_rri(rhs)
}
fn op_rss(lhs: Slot, rhs: Slot) -> Op {
$op_rss(lhs, rhs)
}
fn op_rsi(lhs: Slot, rhs: Self::Input) -> Op {
$op_rsi(lhs, rhs)
}
}
)*
};
}
macro_rules! impl_binary_op_for {
(
$(
impl BinaryOp for $name:ident {
type Result = $res_ty:ty;
type Lhs = $lhs_ty:ty;
type Rhs = $rhs_ty:ty;
fn decode_rhs = $decode_rhs:expr;
fn consteval = $consteval:expr;
$( fn op_rrr = $op_rrr:expr; )?
fn op_rrs = $op_rrs:expr;
fn op_rri = $op_rri:expr;
fn op_rsr = $op_rsr:expr;
fn op_rss = $op_rss:expr;
fn op_rsi = $op_rsi:expr;
fn op_rir = $op_rir:expr;
fn op_ris = $op_ris:expr;
}
)*
) => {
$(
pub enum $name {}
impl BinaryOp for $name {
type Result = $res_ty;
type Lhs = $lhs_ty;
type Rhs = $rhs_ty;
fn decode_rhs(rhs: TypedRawVal) -> BinaryOpRhs<Self::Rhs> {
$decode_rhs(rhs)
}
fn consteval(lhs: Self::Lhs, rhs: Self::Rhs) -> Result<Self::Result, TrapCode> {
$consteval(lhs, rhs).into_result()
}
$(
fn op_rrr() -> Option<Op> {
Some($op_rrr)
}
)?
fn op_rrs(rhs: Slot) -> Op {
$op_rrs(rhs)
}
fn op_rri(rhs: Self::Rhs) -> Op {
$op_rri(rhs)
}
fn op_rsr(lhs: Slot) -> Op {
$op_rsr(lhs)
}
fn op_rss(lhs: Slot, rhs: Slot) -> Op {
$op_rss(lhs, rhs)
}
fn op_rsi(lhs: Slot, rhs: Self::Rhs) -> Op {
$op_rsi(lhs, rhs)
}
fn op_rir(lhs: Self::Lhs) -> Op {
$op_rir(lhs)
}
fn op_ris(lhs: Self::Lhs, rhs: Slot) -> Op {
$op_ris(lhs, rhs)
}
}
)*
};
}
impl_commutative_binary_op_for! {
impl CommutativeBinaryOp for I32Eq {
type Result = bool;
type Input = i32;
fn consteval = wasm::i32_eq;
fn op_rrs = Op::i32_eq_rrs;
fn op_rri = Op::i32_eq_rri;
fn op_rss = Op::i32_eq_rss;
fn op_rsi = Op::i32_eq_rsi;
}
impl CommutativeBinaryOp for I32NotEq {
type Result = bool;
type Input = i32;
fn consteval = wasm::i32_ne;
fn op_rrs = Op::i32_not_eq_rrs;
fn op_rri = Op::i32_not_eq_rri;
fn op_rss = Op::i32_not_eq_rss;
fn op_rsi = Op::i32_not_eq_rsi;
}
impl CommutativeBinaryOp for I32And {
type Result = bool;
type Input = i32;
fn consteval = eval::wasmi_i32_and;
fn op_rrs = Op::i32_and_rrs;
fn op_rri = Op::i32_and_rri;
fn op_rss = Op::i32_and_rss;
fn op_rsi = Op::i32_and_rsi;
}
impl CommutativeBinaryOp for I32NotAnd {
type Result = bool;
type Input = i32;
fn consteval = eval::wasmi_i32_not_and;
fn op_rrs = Op::i32_not_and_rrs;
fn op_rri = Op::i32_not_and_rri;
fn op_rss = Op::i32_not_and_rss;
fn op_rsi = Op::i32_not_and_rsi;
}
impl CommutativeBinaryOp for I32Or {
type Result = bool;
type Input = i32;
fn consteval = eval::wasmi_i32_or;
fn op_rrs = Op::i32_or_rrs;
fn op_rri = Op::i32_or_rri;
fn op_rss = Op::i32_or_rss;
fn op_rsi = Op::i32_or_rsi;
}
impl CommutativeBinaryOp for I32NotOr {
type Result = bool;
type Input = i32;
fn consteval = eval::wasmi_i32_not_or;
fn op_rrs = Op::i32_not_or_rrs;
fn op_rri = Op::i32_not_or_rri;
fn op_rss = Op::i32_not_or_rss;
fn op_rsi = Op::i32_not_or_rsi;
}
impl CommutativeBinaryOp for I32Add {
type Result = i32;
type Input = i32;
fn consteval = wasm::i32_add;
fn op_rrr = Op::i32_mul_rri(2);
fn op_rrs = Op::i32_add_rrs;
fn op_rri = Op::i32_add_rri;
fn op_rss = Op::i32_add_rss;
fn op_rsi = Op::i32_add_rsi;
}
impl CommutativeBinaryOp for I32Mul {
type Result = i32;
type Input = i32;
fn consteval = wasm::i32_mul;
fn op_rrr = Op::i32_mul_rrr();
fn op_rrs = Op::i32_mul_rrs;
fn op_rri = Op::i32_mul_rri;
fn op_rss = Op::i32_mul_rss;
fn op_rsi = Op::i32_mul_rsi;
}
impl CommutativeBinaryOp for I32BitAnd {
type Result = i32;
type Input = i32;
fn consteval = wasm::i32_bitand;
fn op_rrs = Op::i32_bitand_rrs;
fn op_rri = Op::i32_bitand_rri;
fn op_rss = Op::i32_bitand_rss;
fn op_rsi = Op::i32_bitand_rsi;
}
impl CommutativeBinaryOp for I32BitOr {
type Result = i32;
type Input = i32;
fn consteval = wasm::i32_bitor;
fn op_rrs = Op::i32_bitor_rrs;
fn op_rri = Op::i32_bitor_rri;
fn op_rss = Op::i32_bitor_rss;
fn op_rsi = Op::i32_bitor_rsi;
}
impl CommutativeBinaryOp for I32BitXor {
type Result = i32;
type Input = i32;
fn consteval = wasm::i32_bitxor;
fn op_rrs = Op::i32_bitxor_rrs;
fn op_rri = Op::i32_bitxor_rri;
fn op_rss = Op::i32_bitxor_rss;
fn op_rsi = Op::i32_bitxor_rsi;
}
impl CommutativeBinaryOp for I64Eq {
type Result = bool;
type Input = i64;
fn consteval = wasm::i64_eq;
fn op_rrs = Op::i64_eq_rrs;
fn op_rri = Op::i64_eq_rri;
fn op_rss = Op::i64_eq_rss;
fn op_rsi = Op::i64_eq_rsi;
}
impl CommutativeBinaryOp for I64NotEq {
type Result = bool;
type Input = i64;
fn consteval = wasm::i64_ne;
fn op_rrs = Op::i64_not_eq_rrs;
fn op_rri = Op::i64_not_eq_rri;
fn op_rss = Op::i64_not_eq_rss;
fn op_rsi = Op::i64_not_eq_rsi;
}
impl CommutativeBinaryOp for I64And {
type Result = bool;
type Input = i64;
fn consteval = eval::wasmi_i64_and;
fn op_rrs = Op::i64_and_rrs;
fn op_rri = Op::i64_and_rri;
fn op_rss = Op::i64_and_rss;
fn op_rsi = Op::i64_and_rsi;
}
impl CommutativeBinaryOp for I64NotAnd {
type Result = bool;
type Input = i64;
fn consteval = eval::wasmi_i64_not_and;
fn op_rrs = Op::i64_not_and_rrs;
fn op_rri = Op::i64_not_and_rri;
fn op_rss = Op::i64_not_and_rss;
fn op_rsi = Op::i64_not_and_rsi;
}
impl CommutativeBinaryOp for I64Or {
type Result = bool;
type Input = i64;
fn consteval = eval::wasmi_i64_or;
fn op_rrs = Op::i64_or_rrs;
fn op_rri = Op::i64_or_rri;
fn op_rss = Op::i64_or_rss;
fn op_rsi = Op::i64_or_rsi;
}
impl CommutativeBinaryOp for I64NotOr {
type Result = bool;
type Input = i64;
fn consteval = eval::wasmi_i64_not_or;
fn op_rrs = Op::i64_not_or_rrs;
fn op_rri = Op::i64_not_or_rri;
fn op_rss = Op::i64_not_or_rss;
fn op_rsi = Op::i64_not_or_rsi;
}
impl CommutativeBinaryOp for I64Add {
type Result = i64;
type Input = i64;
fn consteval = wasm::i64_add;
fn op_rrr = Op::i64_mul_rri(2);
fn op_rrs = Op::i64_add_rrs;
fn op_rri = Op::i64_add_rri;
fn op_rss = Op::i64_add_rss;
fn op_rsi = Op::i64_add_rsi;
}
impl CommutativeBinaryOp for I64Mul {
type Result = i64;
type Input = i64;
fn consteval = wasm::i64_mul;
fn op_rrr = Op::i64_mul_rrr();
fn op_rrs = Op::i64_mul_rrs;
fn op_rri = Op::i64_mul_rri;
fn op_rss = Op::i64_mul_rss;
fn op_rsi = Op::i64_mul_rsi;
}
impl CommutativeBinaryOp for I64BitAnd {
type Result = i64;
type Input = i64;
fn consteval = wasm::i64_bitand;
fn op_rrs = Op::i64_bitand_rrs;
fn op_rri = Op::i64_bitand_rri;
fn op_rss = Op::i64_bitand_rss;
fn op_rsi = Op::i64_bitand_rsi;
}
impl CommutativeBinaryOp for I64BitOr {
type Result = i64;
type Input = i64;
fn consteval = wasm::i64_bitor;
fn op_rrs = Op::i64_bitor_rrs;
fn op_rri = Op::i64_bitor_rri;
fn op_rss = Op::i64_bitor_rss;
fn op_rsi = Op::i64_bitor_rsi;
}
impl CommutativeBinaryOp for I64BitXor {
type Result = i64;
type Input = i64;
fn consteval = wasm::i64_bitxor;
fn op_rrs = Op::i64_bitxor_rrs;
fn op_rri = Op::i64_bitxor_rri;
fn op_rss = Op::i64_bitxor_rss;
fn op_rsi = Op::i64_bitxor_rsi;
}
impl CommutativeBinaryOp for F32Eq {
type Result = bool;
type Input = f32;
fn consteval = wasm::f32_eq;
fn op_rrs = Op::f32_eq_rrs;
fn op_rri = Op::f32_eq_rri;
fn op_rss = Op::f32_eq_rss;
fn op_rsi = Op::f32_eq_rsi;
}
impl CommutativeBinaryOp for F32NotEq {
type Result = bool;
type Input = f32;
fn consteval = wasm::f32_ne;
fn op_rrs = Op::f32_not_eq_rrs;
fn op_rri = Op::f32_not_eq_rri;
fn op_rss = Op::f32_not_eq_rss;
fn op_rsi = Op::f32_not_eq_rsi;
}
impl CommutativeBinaryOp for F64Eq {
type Result = bool;
type Input = f64;
fn consteval = wasm::f64_eq;
fn op_rrs = Op::f64_eq_rrs;
fn op_rri = Op::f64_eq_rri;
fn op_rss = Op::f64_eq_rss;
fn op_rsi = Op::f64_eq_rsi;
}
impl CommutativeBinaryOp for F64NotEq {
type Result = bool;
type Input = f64;
fn consteval = wasm::f64_ne;
fn op_rrs = Op::f64_not_eq_rrs;
fn op_rri = Op::f64_not_eq_rri;
fn op_rss = Op::f64_not_eq_rss;
fn op_rsi = Op::f64_not_eq_rsi;
}
}
impl_binary_op_for! {
impl BinaryOp for I32Lt {
type Result = bool;
type Lhs = i32;
type Rhs = i32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i32_lt_s;
fn op_rrs = Op::i32_lt_rrs;
fn op_rri = Op::i32_lt_rri;
fn op_rsr = Op::i32_lt_rsr;
fn op_rss = Op::i32_lt_rss;
fn op_rsi = Op::i32_lt_rsi;
fn op_rir = Op::i32_lt_rir;
fn op_ris = Op::i32_lt_ris;
}
impl BinaryOp for I32Le {
type Result = bool;
type Lhs = i32;
type Rhs = i32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i32_le_s;
fn op_rrs = Op::i32_le_rrs;
fn op_rri = Op::i32_le_rri;
fn op_rsr = Op::i32_le_rsr;
fn op_rss = Op::i32_le_rss;
fn op_rsi = Op::i32_le_rsi;
fn op_rir = Op::i32_le_rir;
fn op_ris = Op::i32_le_ris;
}
impl BinaryOp for U32Lt {
type Result = bool;
type Lhs = u32;
type Rhs = u32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i32_lt_u;
fn op_rrs = Op::u32_lt_rrs;
fn op_rri = Op::u32_lt_rri;
fn op_rsr = Op::u32_lt_rsr;
fn op_rss = Op::u32_lt_rss;
fn op_rsi = Op::u32_lt_rsi;
fn op_rir = Op::u32_lt_rir;
fn op_ris = Op::u32_lt_ris;
}
impl BinaryOp for U32Le {
type Result = bool;
type Lhs = u32;
type Rhs = u32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i32_le_u;
fn op_rrs = Op::u32_le_rrs;
fn op_rri = Op::u32_le_rri;
fn op_rsr = Op::u32_le_rsr;
fn op_rss = Op::u32_le_rss;
fn op_rsi = Op::u32_le_rsi;
fn op_rir = Op::u32_le_rir;
fn op_ris = Op::u32_le_ris;
}
impl BinaryOp for I32Sub {
type Result = i32;
type Lhs = i32;
type Rhs = i32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i32_sub;
fn op_rrs = Op::i32_sub_rrs;
fn op_rri = i32_sub_rri;
fn op_rsr = Op::i32_sub_rsr;
fn op_rss = Op::i32_sub_rss;
fn op_rsi = i32_sub_rsi;
fn op_rir = Op::i32_sub_rir;
fn op_ris = Op::i32_sub_ris;
}
impl BinaryOp for I32Div {
type Result = i32;
type Lhs = i32;
type Rhs = NonZero<i32>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_i32_div_ssi;
fn op_rrs = Op::i32_div_rrs;
fn op_rri = Op::i32_div_rri;
fn op_rsr = Op::i32_div_rsr;
fn op_rss = Op::i32_div_rss;
fn op_rsi = Op::i32_div_rsi;
fn op_rir = Op::i32_div_rir;
fn op_ris = Op::i32_div_ris;
}
impl BinaryOp for U32Div {
type Result = u32;
type Lhs = u32;
type Rhs = NonZero<u32>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_u32_div_ssi;
fn op_rrs = Op::u32_div_rrs;
fn op_rri = Op::u32_div_rri;
fn op_rsr = Op::u32_div_rsr;
fn op_rss = Op::u32_div_rss;
fn op_rsi = Op::u32_div_rsi;
fn op_rir = Op::u32_div_rir;
fn op_ris = Op::u32_div_ris;
}
impl BinaryOp for I32Rem {
type Result = i32;
type Lhs = i32;
type Rhs = NonZero<i32>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_i32_rem_ssi;
fn op_rrs = Op::i32_rem_rrs;
fn op_rri = Op::i32_rem_rri;
fn op_rsr = Op::i32_rem_rsr;
fn op_rss = Op::i32_rem_rss;
fn op_rsi = Op::i32_rem_rsi;
fn op_rir = Op::i32_rem_rir;
fn op_ris = Op::i32_rem_ris;
}
impl BinaryOp for U32Rem {
type Result = u32;
type Lhs = u32;
type Rhs = NonZero<u32>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_u32_rem_ssi;
fn op_rrs = Op::u32_rem_rrs;
fn op_rri = Op::u32_rem_rri;
fn op_rsr = Op::u32_rem_rsr;
fn op_rss = Op::u32_rem_rss;
fn op_rsi = Op::u32_rem_rsi;
fn op_rir = Op::u32_rem_rir;
fn op_ris = Op::u32_rem_ris;
}
impl BinaryOp for I32Shl {
type Result = i32;
type Lhs = i32;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i32>;
fn consteval = eval::wasmi_i32_shl_ssi;
fn op_rrs = Op::i32_shl_rrs;
fn op_rri = Op::i32_shl_rri;
fn op_rsr = Op::i32_shl_rsr;
fn op_rss = Op::i32_shl_rss;
fn op_rsi = Op::i32_shl_rsi;
fn op_rir = Op::i32_shl_rir;
fn op_ris = Op::i32_shl_ris;
}
impl BinaryOp for I32Shr {
type Result = i32;
type Lhs = i32;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i32>;
fn consteval = eval::wasmi_i32_shr_ssi;
fn op_rrs = Op::i32_shr_rrs;
fn op_rri = Op::i32_shr_rri;
fn op_rsr = Op::i32_shr_rsr;
fn op_rss = Op::i32_shr_rss;
fn op_rsi = Op::i32_shr_rsi;
fn op_rir = Op::i32_shr_rir;
fn op_ris = Op::i32_shr_ris;
}
impl BinaryOp for U32Shr {
type Result = u32;
type Lhs = u32;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<u32>;
fn consteval = eval::wasmi_u32_shr_ssi;
fn op_rrs = Op::u32_shr_rrs;
fn op_rri = Op::u32_shr_rri;
fn op_rsr = Op::u32_shr_rsr;
fn op_rss = Op::u32_shr_rss;
fn op_rsi = Op::u32_shr_rsi;
fn op_rir = Op::u32_shr_rir;
fn op_ris = Op::u32_shr_ris;
}
impl BinaryOp for I32Rotl {
type Result = i32;
type Lhs = i32;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i32>;
fn consteval = eval::wasmi_i32_rotl_ssi;
fn op_rrs = Op::i32_rotl_rrs;
fn op_rri = Op::i32_rotl_rri;
fn op_rsr = Op::i32_rotl_rsr;
fn op_rss = Op::i32_rotl_rss;
fn op_rsi = Op::i32_rotl_rsi;
fn op_rir = Op::i32_rotl_rir;
fn op_ris = Op::i32_rotl_ris;
}
impl BinaryOp for I32Rotr {
type Result = i32;
type Lhs = i32;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i32>;
fn consteval = eval::wasmi_i32_rotr_ssi;
fn op_rrs = Op::i32_rotr_rrs;
fn op_rri = Op::i32_rotr_rri;
fn op_rsr = Op::i32_rotr_rsr;
fn op_rss = Op::i32_rotr_rss;
fn op_rsi = Op::i32_rotr_rsi;
fn op_rir = Op::i32_rotr_rir;
fn op_ris = Op::i32_rotr_ris;
}
impl BinaryOp for I64Lt {
type Result = bool;
type Lhs = i64;
type Rhs = i64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i64_lt_s;
fn op_rrs = Op::i64_lt_rrs;
fn op_rri = Op::i64_lt_rri;
fn op_rsr = Op::i64_lt_rsr;
fn op_rss = Op::i64_lt_rss;
fn op_rsi = Op::i64_lt_rsi;
fn op_rir = Op::i64_lt_rir;
fn op_ris = Op::i64_lt_ris;
}
impl BinaryOp for I64Le {
type Result = bool;
type Lhs = i64;
type Rhs = i64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i64_le_s;
fn op_rrs = Op::i64_le_rrs;
fn op_rri = Op::i64_le_rri;
fn op_rsr = Op::i64_le_rsr;
fn op_rss = Op::i64_le_rss;
fn op_rsi = Op::i64_le_rsi;
fn op_rir = Op::i64_le_rir;
fn op_ris = Op::i64_le_ris;
}
impl BinaryOp for U64Lt {
type Result = bool;
type Lhs = u64;
type Rhs = u64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i64_lt_u;
fn op_rrs = Op::u64_lt_rrs;
fn op_rri = Op::u64_lt_rri;
fn op_rsr = Op::u64_lt_rsr;
fn op_rss = Op::u64_lt_rss;
fn op_rsi = Op::u64_lt_rsi;
fn op_rir = Op::u64_lt_rir;
fn op_ris = Op::u64_lt_ris;
}
impl BinaryOp for U64Le {
type Result = bool;
type Lhs = u64;
type Rhs = u64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i64_le_u;
fn op_rrs = Op::u64_le_rrs;
fn op_rri = Op::u64_le_rri;
fn op_rsr = Op::u64_le_rsr;
fn op_rss = Op::u64_le_rss;
fn op_rsi = Op::u64_le_rsi;
fn op_rir = Op::u64_le_rir;
fn op_ris = Op::u64_le_ris;
}
impl BinaryOp for I64Sub {
type Result = i64;
type Lhs = i64;
type Rhs = i64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::i64_sub;
fn op_rrs = Op::i64_sub_rrs;
fn op_rri = i64_sub_rri;
fn op_rsr = Op::i64_sub_rsr;
fn op_rss = Op::i64_sub_rss;
fn op_rsi = i64_sub_rsi;
fn op_rir = Op::i64_sub_rir;
fn op_ris = Op::i64_sub_ris;
}
impl BinaryOp for I64Div {
type Result = i64;
type Lhs = i64;
type Rhs = NonZero<i64>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_i64_div_ssi;
fn op_rrs = Op::i64_div_rrs;
fn op_rri = Op::i64_div_rri;
fn op_rsr = Op::i64_div_rsr;
fn op_rss = Op::i64_div_rss;
fn op_rsi = Op::i64_div_rsi;
fn op_rir = Op::i64_div_rir;
fn op_ris = Op::i64_div_ris;
}
impl BinaryOp for U64Div {
type Result = u64;
type Lhs = u64;
type Rhs = NonZero<u64>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_u64_div_ssi;
fn op_rrs = Op::u64_div_rrs;
fn op_rri = Op::u64_div_rri;
fn op_rsr = Op::u64_div_rsr;
fn op_rss = Op::u64_div_rss;
fn op_rsi = Op::u64_div_rsi;
fn op_rir = Op::u64_div_rir;
fn op_ris = Op::u64_div_ris;
}
impl BinaryOp for I64Rem {
type Result = i64;
type Lhs = i64;
type Rhs = NonZero<i64>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_i64_rem_ssi;
fn op_rrs = Op::i64_rem_rrs;
fn op_rri = Op::i64_rem_rri;
fn op_rsr = Op::i64_rem_rsr;
fn op_rss = Op::i64_rem_rss;
fn op_rsi = Op::i64_rem_rsi;
fn op_rir = Op::i64_rem_rir;
fn op_ris = Op::i64_rem_ris;
}
impl BinaryOp for U64Rem {
type Result = u64;
type Lhs = u64;
type Rhs = NonZero<u64>;
fn decode_rhs = decode_rhs_as_divisor;
fn consteval = eval::wasmi_u64_rem_ssi;
fn op_rrs = Op::u64_rem_rrs;
fn op_rri = Op::u64_rem_rri;
fn op_rsr = Op::u64_rem_rsr;
fn op_rss = Op::u64_rem_rss;
fn op_rsi = Op::u64_rem_rsi;
fn op_rir = Op::u64_rem_rir;
fn op_ris = Op::u64_rem_ris;
}
impl BinaryOp for I64Shl {
type Result = i64;
type Lhs = i64;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i64>;
fn consteval = eval::wasmi_i64_shl_ssi;
fn op_rrs = Op::i64_shl_rrs;
fn op_rri = Op::i64_shl_rri;
fn op_rsr = Op::i64_shl_rsr;
fn op_rss = Op::i64_shl_rss;
fn op_rsi = Op::i64_shl_rsi;
fn op_rir = Op::i64_shl_rir;
fn op_ris = Op::i64_shl_ris;
}
impl BinaryOp for I64Shr {
type Result = i64;
type Lhs = i64;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i64>;
fn consteval = eval::wasmi_i64_shr_ssi;
fn op_rrs = Op::i64_shr_rrs;
fn op_rri = Op::i64_shr_rri;
fn op_rsr = Op::i64_shr_rsr;
fn op_rss = Op::i64_shr_rss;
fn op_rsi = Op::i64_shr_rsi;
fn op_rir = Op::i64_shr_rir;
fn op_ris = Op::i64_shr_ris;
}
impl BinaryOp for U64Shr {
type Result = u64;
type Lhs = u64;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<u64>;
fn consteval = eval::wasmi_u64_shr_ssi;
fn op_rrs = Op::u64_shr_rrs;
fn op_rri = Op::u64_shr_rri;
fn op_rsr = Op::u64_shr_rsr;
fn op_rss = Op::u64_shr_rss;
fn op_rsi = Op::u64_shr_rsi;
fn op_rir = Op::u64_shr_rir;
fn op_ris = Op::u64_shr_ris;
}
impl BinaryOp for I64Rotl {
type Result = i64;
type Lhs = i64;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i64>;
fn consteval = eval::wasmi_i64_rotl_ssi;
fn op_rrs = Op::i64_rotl_rrs;
fn op_rri = Op::i64_rotl_rri;
fn op_rsr = Op::i64_rotl_rsr;
fn op_rss = Op::i64_rotl_rss;
fn op_rsi = Op::i64_rotl_rsi;
fn op_rir = Op::i64_rotl_rir;
fn op_ris = Op::i64_rotl_ris;
}
impl BinaryOp for I64Rotr {
type Result = i64;
type Lhs = i64;
type Rhs = ShiftAmount;
fn decode_rhs = decode_rhs_as_shift_amount::<i64>;
fn consteval = eval::wasmi_i64_rotr_ssi;
fn op_rrs = Op::i64_rotr_rrs;
fn op_rri = Op::i64_rotr_rri;
fn op_rsr = Op::i64_rotr_rsr;
fn op_rss = Op::i64_rotr_rss;
fn op_rsi = Op::i64_rotr_rsi;
fn op_rir = Op::i64_rotr_rir;
fn op_ris = Op::i64_rotr_ris;
}
impl BinaryOp for F32Lt {
type Result = bool;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_lt;
fn op_rrs = Op::f32_lt_rrs;
fn op_rri = Op::f32_lt_rri;
fn op_rsr = Op::f32_lt_rsr;
fn op_rss = Op::f32_lt_rss;
fn op_rsi = Op::f32_lt_rsi;
fn op_rir = Op::f32_lt_rir;
fn op_ris = Op::f32_lt_ris;
}
impl BinaryOp for F32Le {
type Result = bool;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_le;
fn op_rrs = Op::f32_le_rrs;
fn op_rri = Op::f32_le_rri;
fn op_rsr = Op::f32_le_rsr;
fn op_rss = Op::f32_le_rss;
fn op_rsi = Op::f32_le_rsi;
fn op_rir = Op::f32_le_rir;
fn op_ris = Op::f32_le_ris;
}
impl BinaryOp for F32NotLt {
type Result = bool;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = eval::wasmi_f32_not_lt;
fn op_rrs = Op::f32_not_lt_rrs;
fn op_rri = Op::f32_not_lt_rri;
fn op_rsr = Op::f32_not_lt_rsr;
fn op_rss = Op::f32_not_lt_rss;
fn op_rsi = Op::f32_not_lt_rsi;
fn op_rir = Op::f32_not_lt_rir;
fn op_ris = Op::f32_not_lt_ris;
}
impl BinaryOp for F32NotLe {
type Result = bool;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = eval::wasmi_f32_not_le;
fn op_rrs = Op::f32_not_le_rrs;
fn op_rri = Op::f32_not_le_rri;
fn op_rsr = Op::f32_not_le_rsr;
fn op_rss = Op::f32_not_le_rss;
fn op_rsi = Op::f32_not_le_rsi;
fn op_rir = Op::f32_not_le_rir;
fn op_ris = Op::f32_not_le_ris;
}
impl BinaryOp for F32Add {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_add;
fn op_rrs = Op::f32_add_rrs;
fn op_rri = Op::f32_add_rri;
fn op_rsr = Op::f32_add_rsr;
fn op_rss = Op::f32_add_rss;
fn op_rsi = Op::f32_add_rsi;
fn op_rir = Op::f32_add_rir;
fn op_ris = Op::f32_add_ris;
}
impl BinaryOp for F32Sub {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_sub;
fn op_rrs = Op::f32_sub_rrs;
fn op_rri = Op::f32_sub_rri;
fn op_rsr = Op::f32_sub_rsr;
fn op_rss = Op::f32_sub_rss;
fn op_rsi = Op::f32_sub_rsi;
fn op_rir = Op::f32_sub_rir;
fn op_ris = Op::f32_sub_ris;
}
impl BinaryOp for F32Mul {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_mul;
fn op_rrr = Op::f32_mul_rrr();
fn op_rrs = Op::f32_mul_rrs;
fn op_rri = Op::f32_mul_rri;
fn op_rsr = Op::f32_mul_rsr;
fn op_rss = Op::f32_mul_rss;
fn op_rsi = Op::f32_mul_rsi;
fn op_rir = Op::f32_mul_rir;
fn op_ris = Op::f32_mul_ris;
}
impl BinaryOp for F32Div {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_div;
fn op_rrs = Op::f32_div_rrs;
fn op_rri = Op::f32_div_rri;
fn op_rsr = Op::f32_div_rsr;
fn op_rss = Op::f32_div_rss;
fn op_rsi = Op::f32_div_rsi;
fn op_rir = Op::f32_div_rir;
fn op_ris = Op::f32_div_ris;
}
impl BinaryOp for F32Min {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_min;
fn op_rrs = Op::f32_min_rrs;
fn op_rri = Op::f32_min_rri;
fn op_rsr = Op::f32_min_rsr;
fn op_rss = Op::f32_min_rss;
fn op_rsi = Op::f32_min_rsi;
fn op_rir = Op::f32_min_rir;
fn op_ris = Op::f32_min_ris;
}
impl BinaryOp for F32Max {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_max;
fn op_rrs = Op::f32_max_rrs;
fn op_rri = Op::f32_max_rri;
fn op_rsr = Op::f32_max_rsr;
fn op_rss = Op::f32_max_rss;
fn op_rsi = Op::f32_max_rsi;
fn op_rir = Op::f32_max_rir;
fn op_ris = Op::f32_max_ris;
}
impl BinaryOp for F32Copysign {
type Result = f32;
type Lhs = f32;
type Rhs = f32;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f32_copysign;
fn op_rrs = Op::f32_copysign_rrs;
fn op_rri = f32_copysign_rri;
fn op_rsr = Op::f32_copysign_rsr;
fn op_rss = Op::f32_copysign_rss;
fn op_rsi = f32_copysign_rsi;
fn op_rir = Op::f32_copysign_rir;
fn op_ris = Op::f32_copysign_ris;
}
impl BinaryOp for F64Lt {
type Result = bool;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_lt;
fn op_rrs = Op::f64_lt_rrs;
fn op_rri = Op::f64_lt_rri;
fn op_rsr = Op::f64_lt_rsr;
fn op_rss = Op::f64_lt_rss;
fn op_rsi = Op::f64_lt_rsi;
fn op_rir = Op::f64_lt_rir;
fn op_ris = Op::f64_lt_ris;
}
impl BinaryOp for F64Le {
type Result = bool;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_le;
fn op_rrs = Op::f64_le_rrs;
fn op_rri = Op::f64_le_rri;
fn op_rsr = Op::f64_le_rsr;
fn op_rss = Op::f64_le_rss;
fn op_rsi = Op::f64_le_rsi;
fn op_rir = Op::f64_le_rir;
fn op_ris = Op::f64_le_ris;
}
impl BinaryOp for F64NotLt {
type Result = bool;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = eval::wasmi_f64_not_lt;
fn op_rrs = Op::f64_not_lt_rrs;
fn op_rri = Op::f64_not_lt_rri;
fn op_rsr = Op::f64_not_lt_rsr;
fn op_rss = Op::f64_not_lt_rss;
fn op_rsi = Op::f64_not_lt_rsi;
fn op_rir = Op::f64_not_lt_rir;
fn op_ris = Op::f64_not_lt_ris;
}
impl BinaryOp for F64NotLe {
type Result = bool;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = eval::wasmi_f64_not_le;
fn op_rrs = Op::f64_not_le_rrs;
fn op_rri = Op::f64_not_le_rri;
fn op_rsr = Op::f64_not_le_rsr;
fn op_rss = Op::f64_not_le_rss;
fn op_rsi = Op::f64_not_le_rsi;
fn op_rir = Op::f64_not_le_rir;
fn op_ris = Op::f64_not_le_ris;
}
impl BinaryOp for F64Add {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_add;
fn op_rrs = Op::f64_add_rrs;
fn op_rri = Op::f64_add_rri;
fn op_rsr = Op::f64_add_rsr;
fn op_rss = Op::f64_add_rss;
fn op_rsi = Op::f64_add_rsi;
fn op_rir = Op::f64_add_rir;
fn op_ris = Op::f64_add_ris;
}
impl BinaryOp for F64Sub {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_sub;
fn op_rrs = Op::f64_sub_rrs;
fn op_rri = Op::f64_sub_rri;
fn op_rsr = Op::f64_sub_rsr;
fn op_rss = Op::f64_sub_rss;
fn op_rsi = Op::f64_sub_rsi;
fn op_rir = Op::f64_sub_rir;
fn op_ris = Op::f64_sub_ris;
}
impl BinaryOp for F64Mul {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_mul;
fn op_rrr = Op::f64_mul_rrr();
fn op_rrs = Op::f64_mul_rrs;
fn op_rri = Op::f64_mul_rri;
fn op_rsr = Op::f64_mul_rsr;
fn op_rss = Op::f64_mul_rss;
fn op_rsi = Op::f64_mul_rsi;
fn op_rir = Op::f64_mul_rir;
fn op_ris = Op::f64_mul_ris;
}
impl BinaryOp for F64Div {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_div;
fn op_rrs = Op::f64_div_rrs;
fn op_rri = Op::f64_div_rri;
fn op_rsr = Op::f64_div_rsr;
fn op_rss = Op::f64_div_rss;
fn op_rsi = Op::f64_div_rsi;
fn op_rir = Op::f64_div_rir;
fn op_ris = Op::f64_div_ris;
}
impl BinaryOp for F64Min {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_min;
fn op_rrs = Op::f64_min_rrs;
fn op_rri = Op::f64_min_rri;
fn op_rsr = Op::f64_min_rsr;
fn op_rss = Op::f64_min_rss;
fn op_rsi = Op::f64_min_rsi;
fn op_rir = Op::f64_min_rir;
fn op_ris = Op::f64_min_ris;
}
impl BinaryOp for F64Max {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_max;
fn op_rrs = Op::f64_max_rrs;
fn op_rri = Op::f64_max_rri;
fn op_rsr = Op::f64_max_rsr;
fn op_rss = Op::f64_max_rss;
fn op_rsi = Op::f64_max_rsi;
fn op_rir = Op::f64_max_rir;
fn op_ris = Op::f64_max_ris;
}
impl BinaryOp for F64Copysign {
type Result = f64;
type Lhs = f64;
type Rhs = f64;
fn decode_rhs = decode_rhs_as_value;
fn consteval = wasm::f64_copysign;
fn op_rrs = Op::f64_copysign_rrs;
fn op_rri = f64_copysign_rri;
fn op_rsr = Op::f64_copysign_rsr;
fn op_rss = Op::f64_copysign_rss;
fn op_rsi = f64_copysign_rsi;
fn op_rir = Op::f64_copysign_rir;
fn op_ris = Op::f64_copysign_ris;
}
}
macro_rules! impl_cmp_op_for {
(
$(
impl BinaryOp for $name:ident as $binop:ty;
)*
) => {
$(
pub enum $name {}
impl BinaryOp for $name {
type Result = <$binop as BinaryOp>::Result;
type Lhs = <$binop as BinaryOp>::Lhs;
type Rhs = <$binop as BinaryOp>::Rhs;
fn decode_rhs(rhs: TypedRawVal) -> BinaryOpRhs<<$binop as BinaryOp>::Rhs> {
<$binop as BinaryOp>::decode_rhs(rhs)
}
fn consteval(lhs: Self::Lhs, rhs: Self::Rhs) -> Result<Self::Result, TrapCode> {
<$binop as BinaryOp>::consteval(rhs, lhs)
}
fn op_rrs(rhs: Slot) -> Op {
<$binop as BinaryOp>::op_rsr(rhs)
}
fn op_rri(rhs: Self::Rhs) -> Op {
<$binop as BinaryOp>::op_rir(rhs)
}
fn op_rsr(lhs: Slot) -> Op {
<$binop as BinaryOp>::op_rrs(lhs)
}
fn op_rss(lhs: Slot, rhs: Slot) -> Op {
<$binop as BinaryOp>::op_rss(rhs, lhs)
}
fn op_rsi(lhs: Slot, rhs: Self::Rhs) -> Op {
<$binop as BinaryOp>::op_ris(rhs, lhs)
}
fn op_rir(lhs: Self::Lhs) -> Op {
<$binop as BinaryOp>::op_rri(lhs)
}
fn op_ris(lhs: Self::Lhs, rhs: Slot) -> Op {
<$binop as BinaryOp>::op_rsi(rhs, lhs)
}
}
)*
};
}
impl_cmp_op_for! {
impl BinaryOp for I32Gt as I32Lt;
impl BinaryOp for U32Gt as U32Lt;
impl BinaryOp for I32Ge as I32Le;
impl BinaryOp for U32Ge as U32Le;
impl BinaryOp for I64Gt as I64Lt;
impl BinaryOp for U64Gt as U64Lt;
impl BinaryOp for I64Ge as I64Le;
impl BinaryOp for U64Ge as U64Le;
impl BinaryOp for F32Gt as F32Lt;
impl BinaryOp for F32Ge as F32Le;
impl BinaryOp for F64Gt as F64Lt;
impl BinaryOp for F64Ge as F64Le;
}
pub enum BinaryOpRhs<T> {
Value(T),
Trap(TrapCode),
ReturnLhs,
}
fn decode_rhs_as_value<T>(value: TypedRawVal) -> BinaryOpRhs<T>
where
T: From<TypedRawVal>,
{
BinaryOpRhs::Value(T::from(value))
}
fn decode_rhs_as_divisor<T: DecodeRhsAsDivisor>(value: TypedRawVal) -> BinaryOpRhs<T> {
DecodeRhsAsDivisor::decode_rhs_as_divisor(value)
}
trait DecodeRhsAsDivisor: Sized {
fn decode_rhs_as_divisor(value: TypedRawVal) -> BinaryOpRhs<Self>;
}
macro_rules! impl_decode_rhs_as_divisor_for {
( $($ty:ty),* $(,)? ) => {
$(
impl DecodeRhsAsDivisor for NonZero<$ty> {
fn decode_rhs_as_divisor(value: TypedRawVal) -> BinaryOpRhs<Self> {
match Self::new(<$ty>::from(value)) {
Some(value) => BinaryOpRhs::Value(value),
None => BinaryOpRhs::Trap(TrapCode::IntegerDivisionByZero),
}
}
}
)*
};
}
impl_decode_rhs_as_divisor_for!(i32, i64, u32, u64);
fn decode_rhs_as_shift_amount<T>(value: TypedRawVal) -> BinaryOpRhs<ShiftAmount>
where
T: IntoShiftAmount<ShiftSource: From<TypedRawVal>>,
{
let shift_source = <<T as IntoShiftAmount>::ShiftSource>::from(value);
match <T as IntoShiftAmount>::into_shift_amount(shift_source) {
Some(value) => BinaryOpRhs::Value(value),
None => BinaryOpRhs::ReturnLhs,
}
}
fn f32_copysign_rri(rhs: f32) -> Op {
match rhs.is_sign_positive() {
true => Op::f32_abs_rr(),
false => Op::f32_nabs_rr(),
}
}
fn f32_copysign_rsi(lhs: Slot, rhs: f32) -> Op {
match rhs.is_sign_positive() {
true => Op::f32_abs_rs(lhs),
false => Op::f32_nabs_rs(lhs),
}
}
fn f64_copysign_rri(rhs: f64) -> Op {
match rhs.is_sign_positive() {
true => Op::f64_abs_rr(),
false => Op::f64_nabs_rr(),
}
}
fn f64_copysign_rsi(lhs: Slot, rhs: f64) -> Op {
match rhs.is_sign_positive() {
true => Op::f64_abs_rs(lhs),
false => Op::f64_nabs_rs(lhs),
}
}
fn i32_sub_rri(rhs: i32) -> Op {
Op::i32_add_rri(rhs.wrapping_neg())
}
fn i32_sub_rsi(lhs: Slot, rhs: i32) -> Op {
Op::i32_add_rsi(lhs, rhs.wrapping_neg())
}
fn i64_sub_rri(rhs: i64) -> Op {
Op::i64_add_rri(rhs.wrapping_neg())
}
fn i64_sub_rsi(lhs: Slot, rhs: i64) -> Op {
Op::i64_add_rsi(lhs, rhs.wrapping_neg())
}