use crate::canon::IrHeap;
pub(crate) use super::op_types::*;
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub(crate) enum Op {
Unreachable,
Nop,
Br(BranchTarget, Slot),
BrIf(BranchTarget, Slot),
BrIfNot(BranchTarget, Slot),
BrIfCmp {
kind: CmpKind,
negate: bool,
ip: u32,
lhs: Slot,
rhs: Slot,
},
BrIfCmpImm {
kind: CmpKind,
negate: bool,
ip: u32,
lhs: Slot,
imm: i32,
},
BrTable(BrTableRange, Slot),
Call(FuncIdx, Slot),
CallInternal(u32, Slot),
CallIndirect {
type_idx: TypeIdx,
table: TableIdx,
s: Slot,
},
CallRef(TypeIdx, Slot),
ReturnCall(FuncIdx, Slot),
ReturnCallIndirect {
type_idx: TypeIdx,
table: TableIdx,
s: Slot,
},
ReturnCallRef(TypeIdx, Slot),
BrOnNull(BranchTarget, Slot),
BrOnNonNull(BranchTarget, Slot),
Throw(u32, Slot),
ThrowRef(Slot),
Select(Slot),
Copy(Slot, Slot),
GlobalGet(Slot, GlobalIdx),
GlobalSet(Slot, GlobalIdx),
I32Load(LoadArg),
I64Load(LoadArg),
F32Load(LoadArg),
F64Load(LoadArg),
I32Load8S(LoadArg),
I32Load8U(LoadArg),
I32Load16S(LoadArg),
I32Load16U(LoadArg),
I64Load8S(LoadArg),
I64Load8U(LoadArg),
I64Load16S(LoadArg),
I64Load16U(LoadArg),
I64Load32S(LoadArg),
I64Load32U(LoadArg),
I32Store(StoreArg),
I64Store(StoreArg),
F32Store(StoreArg),
F64Store(StoreArg),
I32Store8(StoreArg),
I32Store16(StoreArg),
I64Store8(StoreArg),
I64Store16(StoreArg),
I64Store32(StoreArg),
MemorySize(u32, Slot),
MemoryGrow(u32, Slot),
MemoryInit(DataIdx, u32, Slot),
DataDrop(DataIdx),
MemoryCopy(u32, u32, Slot),
MemoryFill(u32, Slot),
TableInit {
elem: ElemIdx,
table: TableIdx,
s: Slot,
},
TableCopy {
dst_table: TableIdx,
src_table: TableIdx,
s: Slot,
},
ElemDrop(ElemIdx),
RefNull(IrHeap, Slot),
RefFunc(FuncIdx, Slot),
RefIsNull(Slot),
RefAsNonNull(Slot),
TableGet(TableIdx, Slot),
TableSet(TableIdx, Slot),
TableSize(TableIdx, Slot),
TableGrow(TableIdx, Slot),
TableFill(TableIdx, Slot),
I32AddImm(Slot, Slot, i32),
I32MulImm(Slot, Slot, i32),
I32AndImm(Slot, Slot, i32),
I32OrImm(Slot, Slot, i32),
I32XorImm(Slot, Slot, i32),
I32ShlImm(Slot, Slot, i32),
I32ShrSImm(Slot, Slot, i32),
I32ShrUImm(Slot, Slot, i32),
I32CmpImm {
kind: CmpKind,
dst: Slot,
lhs: Slot,
imm: i32,
},
I32Const(Slot, i32),
I64Const(Slot, i64),
F32Const(Slot, u32),
F64Const(Slot, u64),
I32Eqz(Slot, Slot),
I32Eq(Slot, Slot, Slot),
I32Ne(Slot, Slot, Slot),
I32LtS(Slot, Slot, Slot),
I32LtU(Slot, Slot, Slot),
I32GtS(Slot, Slot, Slot),
I32GtU(Slot, Slot, Slot),
I32LeS(Slot, Slot, Slot),
I32LeU(Slot, Slot, Slot),
I32GeS(Slot, Slot, Slot),
I32GeU(Slot, Slot, Slot),
I32Clz(Slot, Slot),
I32Ctz(Slot, Slot),
I32Popcnt(Slot, Slot),
I32Add(Slot, Slot, Slot),
I32Sub(Slot, Slot, Slot),
I32Mul(Slot, Slot, Slot),
I32DivS(Slot, Slot, Slot),
I32DivU(Slot, Slot, Slot),
I32RemS(Slot, Slot, Slot),
I32RemU(Slot, Slot, Slot),
I32And(Slot, Slot, Slot),
I32Or(Slot, Slot, Slot),
I32Xor(Slot, Slot, Slot),
I32Shl(Slot, Slot, Slot),
I32ShrS(Slot, Slot, Slot),
I32ShrU(Slot, Slot, Slot),
I32Rotl(Slot, Slot, Slot),
I32Rotr(Slot, Slot, Slot),
I64Eqz(Slot, Slot),
I64Eq(Slot, Slot, Slot),
I64Ne(Slot, Slot, Slot),
I64LtS(Slot, Slot, Slot),
I64LtU(Slot, Slot, Slot),
I64GtS(Slot, Slot, Slot),
I64GtU(Slot, Slot, Slot),
I64LeS(Slot, Slot, Slot),
I64LeU(Slot, Slot, Slot),
I64GeS(Slot, Slot, Slot),
I64GeU(Slot, Slot, Slot),
I64Clz(Slot, Slot),
I64Ctz(Slot, Slot),
I64Popcnt(Slot, Slot),
I64Add(Slot, Slot, Slot),
I64Sub(Slot, Slot, Slot),
I64Mul(Slot, Slot, Slot),
I64DivS(Slot, Slot, Slot),
I64DivU(Slot, Slot, Slot),
I64RemS(Slot, Slot, Slot),
I64RemU(Slot, Slot, Slot),
I64And(Slot, Slot, Slot),
I64Or(Slot, Slot, Slot),
I64Xor(Slot, Slot, Slot),
I64Shl(Slot, Slot, Slot),
I64ShrS(Slot, Slot, Slot),
I64ShrU(Slot, Slot, Slot),
I64Rotl(Slot, Slot, Slot),
I64Rotr(Slot, Slot, Slot),
F32Eq(Slot, Slot, Slot),
F32Ne(Slot, Slot, Slot),
F32Lt(Slot, Slot, Slot),
F32Gt(Slot, Slot, Slot),
F32Le(Slot, Slot, Slot),
F32Ge(Slot, Slot, Slot),
F32Abs(Slot, Slot),
F32Neg(Slot, Slot),
F32Ceil(Slot, Slot),
F32Floor(Slot, Slot),
F32Trunc(Slot, Slot),
F32Nearest(Slot, Slot),
F32Sqrt(Slot, Slot),
F32Add(Slot, Slot, Slot),
F32Sub(Slot, Slot, Slot),
F32Mul(Slot, Slot, Slot),
F32Div(Slot, Slot, Slot),
F32Min(Slot, Slot, Slot),
F32Max(Slot, Slot, Slot),
F32Copysign(Slot, Slot, Slot),
F64Eq(Slot, Slot, Slot),
F64Ne(Slot, Slot, Slot),
F64Lt(Slot, Slot, Slot),
F64Gt(Slot, Slot, Slot),
F64Le(Slot, Slot, Slot),
F64Ge(Slot, Slot, Slot),
F64Abs(Slot, Slot),
F64Neg(Slot, Slot),
F64Ceil(Slot, Slot),
F64Floor(Slot, Slot),
F64Trunc(Slot, Slot),
F64Nearest(Slot, Slot),
F64Sqrt(Slot, Slot),
F64Add(Slot, Slot, Slot),
F64Sub(Slot, Slot, Slot),
F64Mul(Slot, Slot, Slot),
F64Div(Slot, Slot, Slot),
F64Min(Slot, Slot, Slot),
F64Max(Slot, Slot, Slot),
F64Copysign(Slot, Slot, Slot),
I32WrapI64(Slot, Slot),
I32TruncF32S(Slot, Slot),
I32TruncF32U(Slot, Slot),
I32TruncF64S(Slot, Slot),
I32TruncF64U(Slot, Slot),
I64ExtendI32S(Slot, Slot),
I64ExtendI32U(Slot, Slot),
I64TruncF32S(Slot, Slot),
I64TruncF32U(Slot, Slot),
I64TruncF64S(Slot, Slot),
I64TruncF64U(Slot, Slot),
F32ConvertI32S(Slot, Slot),
F32ConvertI32U(Slot, Slot),
F32ConvertI64S(Slot, Slot),
F32ConvertI64U(Slot, Slot),
F32DemoteF64(Slot, Slot),
F64ConvertI32S(Slot, Slot),
F64ConvertI32U(Slot, Slot),
F64ConvertI64S(Slot, Slot),
F64ConvertI64U(Slot, Slot),
F64PromoteF32(Slot, Slot),
I32ReinterpretF32(Slot, Slot),
I64ReinterpretF64(Slot, Slot),
F32ReinterpretI32(Slot, Slot),
F64ReinterpretI64(Slot, Slot),
I32Extend8S(Slot, Slot),
I32Extend16S(Slot, Slot),
I64Extend8S(Slot, Slot),
I64Extend16S(Slot, Slot),
I64Extend32S(Slot, Slot),
I32TruncSatF32S(Slot, Slot),
I32TruncSatF32U(Slot, Slot),
I32TruncSatF64S(Slot, Slot),
I32TruncSatF64U(Slot, Slot),
I64TruncSatF32S(Slot, Slot),
I64TruncSatF32U(Slot, Slot),
I64TruncSatF64S(Slot, Slot),
I64TruncSatF64U(Slot, Slot),
StructNew(TypeIdx, Slot),
StructNewDefault(TypeIdx, Slot),
StructGet {
ty: TypeIdx,
field: u32,
top: Slot,
},
StructGetS {
ty: TypeIdx,
field: u32,
top: Slot,
},
StructGetU {
ty: TypeIdx,
field: u32,
top: Slot,
},
StructSet {
ty: TypeIdx,
field: u32,
top: Slot,
},
ArrayNew(TypeIdx, Slot),
ArrayNewDefault(TypeIdx, Slot),
ArrayNewFixed {
ty: TypeIdx,
n: u32,
top: Slot,
},
ArrayNewData {
ty: TypeIdx,
data: DataIdx,
top: Slot,
},
ArrayNewElem {
ty: TypeIdx,
elem: ElemIdx,
top: Slot,
},
ArrayGet(TypeIdx, Slot),
ArrayGetS(TypeIdx, Slot),
ArrayGetU(TypeIdx, Slot),
ArraySet(TypeIdx, Slot),
ArrayLen(Slot),
ArrayFill(TypeIdx, Slot),
ArrayCopy {
dst: TypeIdx,
src: TypeIdx,
top: Slot,
},
ArrayInitData {
ty: TypeIdx,
data: DataIdx,
top: Slot,
},
ArrayInitElem {
ty: TypeIdx,
elem: ElemIdx,
top: Slot,
},
RefI31(Slot),
I31GetS(Slot),
I31GetU(Slot),
RefTest {
ty: IrHeap,
nullable: bool,
top: Slot,
},
RefCast {
ty: IrHeap,
nullable: bool,
top: Slot,
},
RefEq(Slot),
AnyConvertExtern(Slot),
ExternConvertAny(Slot),
BrOnCast {
heap: u32,
target: u32,
top: Slot,
},
BrOnCastFail {
heap: u32,
target: u32,
top: Slot,
},
#[cfg(feature = "simd")]
Simd(super::op_simd::SimdOp, Slot),
}
impl Op {
pub(crate) fn window_top(&self) -> Option<Slot> {
match *self {
Op::StructNew(_, top)
| Op::StructNewDefault(_, top)
| Op::StructGet { top, .. }
| Op::StructGetS { top, .. }
| Op::StructGetU { top, .. }
| Op::StructSet { top, .. }
| Op::ArrayNew(_, top)
| Op::ArrayNewDefault(_, top)
| Op::ArrayNewFixed { top, .. }
| Op::ArrayNewData { top, .. }
| Op::ArrayNewElem { top, .. }
| Op::ArrayGet(_, top)
| Op::ArrayGetS(_, top)
| Op::ArrayGetU(_, top)
| Op::ArraySet(_, top)
| Op::ArrayLen(top)
| Op::ArrayFill(_, top)
| Op::ArrayCopy { top, .. }
| Op::ArrayInitData { top, .. }
| Op::ArrayInitElem { top, .. }
| Op::RefI31(top)
| Op::I31GetS(top)
| Op::I31GetU(top)
| Op::RefTest { top, .. }
| Op::RefCast { top, .. }
| Op::RefEq(top)
| Op::AnyConvertExtern(top)
| Op::ExternConvertAny(top)
| Op::BrOnCast { top, .. }
| Op::BrOnCastFail { top, .. } => Some(top),
#[cfg(feature = "simd")]
Op::Simd(_, top) => Some(top),
_ => None,
}
}
}
pub(crate) use super::code::CompiledFunc;
macro_rules! first_field_of {
($b:ident; $($v:ident)*) => { $(Op::$v($b, ..))|* };
}
impl Op {
pub(crate) fn dst_mut(&mut self) -> Option<&mut Slot> {
match self {
first_field_of!(d;
I32Eqz I32Eq I32Ne I32LtS I32LtU I32GtS I32GtU I32LeS I32LeU I32GeS I32GeU I32Clz
I32Ctz I32Popcnt I32Add I32Sub I32Mul I32DivS I32DivU I32RemS I32RemU I32And I32Or
I32Xor I32Shl I32ShrS I32ShrU I32Rotl I32Rotr I64Eqz I64Eq I64Ne I64LtS I64LtU
I64GtS I64GtU I64LeS I64LeU I64GeS I64GeU I64Clz I64Ctz I64Popcnt I64Add I64Sub
I64Mul I64DivS I64DivU I64RemS I64RemU I64And I64Or I64Xor I64Shl I64ShrS I64ShrU
I64Rotl I64Rotr F32Eq F32Ne F32Lt F32Gt F32Le F32Ge F32Abs F32Neg F32Ceil F32Floor
F32Trunc F32Nearest F32Sqrt F32Add F32Sub F32Mul F32Div F32Min F32Max F32Copysign
F64Eq F64Ne F64Lt F64Gt F64Le F64Ge F64Abs F64Neg F64Ceil F64Floor F64Trunc
F64Nearest F64Sqrt F64Add F64Sub F64Mul F64Div F64Min F64Max F64Copysign
I32WrapI64 I32TruncF32S I32TruncF32U I32TruncF64S I32TruncF64U I64ExtendI32S
I64ExtendI32U I64TruncF32S I64TruncF32U I64TruncF64S I64TruncF64U F32ConvertI32S
F32ConvertI32U F32ConvertI64S F32ConvertI64U F32DemoteF64 F64ConvertI32S
F64ConvertI32U F64ConvertI64S F64ConvertI64U F64PromoteF32 I32ReinterpretF32
I64ReinterpretF64 F32ReinterpretI32 F64ReinterpretI64 I32Extend8S I32Extend16S
I64Extend8S I64Extend16S I64Extend32S I32TruncSatF32S I32TruncSatF32U
I32TruncSatF64S I32TruncSatF64U I64TruncSatF32S I64TruncSatF32U I64TruncSatF64S
I64TruncSatF64U I32Const I64Const F32Const F64Const GlobalGet I32AddImm I32MulImm
I32AndImm I32OrImm I32XorImm I32ShlImm I32ShrSImm I32ShrUImm
) => Some(d),
first_field_of!(m;
I32Load I64Load F32Load F64Load I32Load8S I32Load8U I32Load16S I32Load16U
I64Load8S I64Load8U I64Load16S I64Load16U I64Load32S I64Load32U
) => (m.offset != BIG_MEMARG).then_some(&mut m.dst),
Op::I32CmpImm { dst, .. } => Some(dst),
_ => None,
}
}
}
const _: () = assert!(std::mem::size_of::<Op>() == 16);
const _: () = assert!(!std::mem::needs_drop::<Op>());