use super::{FuncAddr, GlobalAddr, LocalAddr, TableAddr, TypeAddr, ValueCounts, WasmType};
use crate::{ConstIdx, DataAddr, ElemAddr, ExternAddr, MemAddr};
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
#[repr(Rust, packed)]
pub struct MemoryArg {
offset: u64,
mem_addr: MemAddr,
}
impl MemoryArg {
#[inline]
pub const fn new(offset: u64, mem_addr: MemAddr) -> Self {
Self { offset, mem_addr }
}
#[inline]
pub const fn offset(self) -> u64 {
self.offset
}
#[inline]
pub const fn mem_addr(self) -> MemAddr {
self.mem_addr
}
}
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub enum ConstInstruction {
I32Const(i32),
I64Const(i64),
F32Const(f32),
F64Const(f64),
V128Const(i128),
GlobalGet(GlobalAddr),
RefFunc(Option<FuncAddr>),
RefExtern(Option<ExternAddr>),
I32Add,
I32Sub,
I32Mul,
I64Add,
I64Sub,
I64Mul,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub enum CmpOp {
Eq,
Ne,
LtS,
LtU,
GtS,
GtU,
LeS,
LeU,
GeS,
GeU,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub enum BinOp {
IAdd,
ISub,
IMul,
IAnd,
IOr,
IXor,
IShl,
IShrS,
IShrU,
IRotl,
IRotr,
FAdd,
FSub,
FMul,
FDiv,
FMin,
FMax,
FCopysign,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub enum BinOp128 {
And,
AndNot,
Or,
Xor,
I64x2Add,
I64x2Mul,
}
#[rustfmt::skip]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub enum Instruction {
LocalCopy32(LocalAddr, LocalAddr), LocalCopy64(LocalAddr, LocalAddr), LocalCopy128(LocalAddr, LocalAddr),
AddConst32(i32), AddConst64(i64),
IncLocal32(LocalAddr, i32), IncLocal64(LocalAddr, i64),
BinOpLocalLocal32(BinOp, LocalAddr, LocalAddr), BinOpLocalLocal64(BinOp, LocalAddr, LocalAddr),
BinOpLocalLocal128(BinOp128, LocalAddr, LocalAddr),
BinOpLocalLocalSet32(BinOp, LocalAddr, LocalAddr, LocalAddr),
BinOpLocalLocalSet64(BinOp, LocalAddr, LocalAddr, LocalAddr),
BinOpLocalLocalSet128(BinOp128, LocalAddr, LocalAddr, LocalAddr),
BinOpLocalLocalTee32(BinOp, LocalAddr, LocalAddr, LocalAddr),
BinOpLocalLocalTee64(BinOp, LocalAddr, LocalAddr, LocalAddr),
BinOpLocalLocalTee128(BinOp128, LocalAddr, LocalAddr, LocalAddr),
BinOpLocalConst32(BinOp, LocalAddr, i32), BinOpLocalConst64(BinOp, LocalAddr, i64),
BinOpLocalConst128(BinOp128, LocalAddr, ConstIdx),
BinOpLocalConstSet32(BinOp, LocalAddr, i32, LocalAddr),
BinOpLocalConstSet64(BinOp, LocalAddr, i64, LocalAddr),
BinOpLocalConstSet128(BinOp128, LocalAddr, ConstIdx, LocalAddr),
BinOpLocalConstTee32(BinOp, LocalAddr, i32, LocalAddr),
BinOpLocalConstTee64(BinOp, LocalAddr, i64, LocalAddr),
BinOpLocalConstTee128(BinOp128, LocalAddr, ConstIdx, LocalAddr),
BinOpStackGlobal32(BinOp, u32),
BinOpStackGlobal64(BinOp, u32),
SetLocalConst32(LocalAddr, i32), SetLocalConst64(LocalAddr, i64), SetLocalConst128(LocalAddr, ConstIdx),
StoreLocalLocal32(MemoryArg, u8, u8),
StoreLocalLocal64(MemoryArg, u8, u8),
StoreLocalLocal128(MemoryArg, u8, u8),
LoadLocal32(MemoryArg, u8),
LoadLocalTee32(MemoryArg, u8, u8),
LoadLocalSet32(MemoryArg, u8, u8),
LoadLocalTee128(MemoryArg, u8, u8),
LoadLocalSet128(MemoryArg, u8, u8),
AndConstTee32(i32, LocalAddr),
SubConstTee32(i32, LocalAddr),
AndConstTee64(i64, LocalAddr),
SubConstTee64(i64, LocalAddr),
MulAccLocal32(LocalAddr),
MulAccLocal64(LocalAddr),
FMulAccLocal32(LocalAddr),
FMulAccLocal64(LocalAddr),
I32Add3,
I64Add3,
FMaStoreF32(MemoryArg),
FMaStoreF64(MemoryArg),
Unreachable,
Nop,
MergeBarrier,
Jump(u32),
JumpIfZero32(u32),
JumpIfNonZero32(u32),
JumpIfZero64(u32),
JumpIfNonZero64(u32),
JumpIfLocalZero32 { target_ip: u32, local: LocalAddr },
JumpIfLocalNonZero32 { target_ip: u32, local: LocalAddr },
JumpIfLocalZero64 { target_ip: u32, local: LocalAddr },
JumpIfLocalNonZero64 { target_ip: u32, local: LocalAddr },
JumpCmpStackConst32 { target_ip: u32, imm: i32, op: CmpOp },
JumpCmpStackConst64 { target_ip: u32, imm: i64, op: CmpOp },
JumpCmpLocalConst32 { target_ip: u32, local: LocalAddr, imm: i32, op: CmpOp },
JumpCmpLocalConst64 { target_ip: u32, local: LocalAddr, imm: i32, op: CmpOp },
JumpCmpLocalLocal32 { target_ip: u32, left: LocalAddr, right: LocalAddr, op: CmpOp },
JumpCmpLocalLocal64 { target_ip: u32, left: LocalAddr, right: LocalAddr, op: CmpOp },
DropKeep { base32: u16, keep32: u8, base64: u16, keep64: u8, base128: u16, keep128: u8 },
DropKeep32(u16, u16),
DropKeep64(u16, u16),
DropKeep128(u16, u16),
BranchTable(u32, u32, u32), Return,
ReturnVoid,
Return32,
Return64,
Return128,
Call(FuncAddr),
CallSelf,
CallIndirect(TypeAddr, TableAddr),
ReturnCall(FuncAddr),
ReturnCallSelf,
ReturnCallIndirect(TypeAddr, TableAddr),
Drop32, Select32,
Drop64, Select64,
Drop128, Select128,
SelectMulti(ValueCounts),
GlobalGet(GlobalAddr),
LocalGet32(LocalAddr), LocalSet32(LocalAddr), LocalTee32(LocalAddr), GlobalSet32(GlobalAddr),
LocalGet64(LocalAddr), LocalSet64(LocalAddr), LocalTee64(LocalAddr), GlobalSet64(GlobalAddr),
LocalGet128(LocalAddr), LocalSet128(LocalAddr), LocalTee128(LocalAddr), GlobalSet128(GlobalAddr),
I32Load(MemoryArg),
I64Load(MemoryArg),
F32Load(MemoryArg),
F64Load(MemoryArg),
I32Load8S(MemoryArg),
I32Load8U(MemoryArg),
I32Load16S(MemoryArg),
I32Load16U(MemoryArg),
I64Load8S(MemoryArg),
I64Load8U(MemoryArg),
I64Load16S(MemoryArg),
I64Load16U(MemoryArg),
I64Load32S(MemoryArg),
I64Load32U(MemoryArg),
I32Store(MemoryArg),
I64Store(MemoryArg),
F32Store(MemoryArg),
F64Store(MemoryArg),
I32Store8(MemoryArg),
I32Store16(MemoryArg),
I64Store8(MemoryArg),
I64Store16(MemoryArg),
I64Store32(MemoryArg),
MemorySize(MemAddr),
MemoryGrow(MemAddr),
Const32(i32),
Const64(i64),
RefNull(WasmType),
RefFunc(FuncAddr),
RefIsNull,
I32Eqz, I32Eq, I32Ne, I32LtS, I32LtU, I32GtS, I32GtU, I32LeS, I32LeU, I32GeS, I32GeU,
I64Eqz, I64Eq, I64Ne, I64LtS, I64LtU, I64GtS, I64GtU, I64LeS, I64LeU, I64GeS, I64GeU,
F32Eq, F32Ne, F32Lt, F32Gt, F32Le, F32Ge,
F64Eq, F64Ne, F64Lt, F64Gt, F64Le, F64Ge,
I32Clz, I32Ctz, I32Popcnt, I32Add, I32Sub, I32Mul, I32DivS, I32DivU, I32RemS, I32RemU,
I64Clz, I64Ctz, I64Popcnt, I64Add, I64Sub, I64Mul, I64DivS, I64DivU, I64RemS, I64RemU,
I32And, I32Or, I32Xor, I32Shl, I32ShrS, I32ShrU, I32Rotl, I32Rotr,
I64And, I64Or, I64Xor, I64Shl, I64ShrS, I64ShrU, I64Rotl, I64Rotr,
F32Abs, F32Neg, F32Ceil, F32Floor, F32Trunc, F32Nearest, F32Sqrt, F32Add, F32Sub, F32Mul, F32Div, F32Min, F32Max, F32Copysign,
F64Abs, F64Neg, F64Ceil, F64Floor, F64Trunc, F64Nearest, F64Sqrt, F64Add, F64Sub, F64Mul, F64Div, F64Min, F64Max, F64Copysign,
I32WrapI64, I32TruncF32S, I32TruncF32U, I32TruncF64S, I32TruncF64U, I32Extend8S, I32Extend16S,
I64Extend8S, I64Extend16S, I64Extend32S, I64ExtendI32S, I64ExtendI32U, I64TruncF32S, I64TruncF32U, I64TruncF64S, I64TruncF64U,
F32ConvertI32S, F32ConvertI32U, F32ConvertI64S, F32ConvertI64U, F32DemoteF64,
F64ConvertI32S, F64ConvertI32U, F64ConvertI64S, F64ConvertI64U, F64PromoteF32,
I32TruncSatF32S, I32TruncSatF32U, I32TruncSatF64S, I32TruncSatF64U,
I64TruncSatF32S, I64TruncSatF32U, I64TruncSatF64S, I64TruncSatF64U,
TableInit(ElemAddr, TableAddr),
TableGet(TableAddr),
TableSet(TableAddr),
TableCopy { dst_table: TableAddr, src_table: TableAddr },
TableGrow(TableAddr),
TableSize(TableAddr),
TableFill(TableAddr),
MemoryInit(MemAddr, DataAddr),
MemoryCopy { dst_mem: MemAddr, src_mem: MemAddr },
MemoryFill(MemAddr),
MemoryFillImm(MemAddr, u8, i32),
DataDrop(DataAddr),
ElemDrop(ElemAddr),
I64Add128, I64Sub128, I64MulWideS, I64MulWideU,
V128Load(MemoryArg),
V128Load8x8S(MemoryArg), V128Load8x8U(MemoryArg),
V128Load16x4S(MemoryArg), V128Load16x4U(MemoryArg),
V128Load32x2S(MemoryArg), V128Load32x2U(MemoryArg),
V128Load8Splat(MemoryArg), V128Load16Splat(MemoryArg), V128Load32Splat(MemoryArg), V128Load64Splat(MemoryArg),
V128Load8Lane(MemoryArg, u8), V128Load16Lane(MemoryArg, u8), V128Load32Lane(MemoryArg, u8), V128Load64Lane(MemoryArg, u8),
V128Load32Zero(MemoryArg), V128Load64Zero(MemoryArg),
V128Store(MemoryArg), V128Store8Lane(MemoryArg, u8), V128Store16Lane(MemoryArg, u8), V128Store32Lane(MemoryArg, u8), V128Store64Lane(MemoryArg, u8),
I8x16Shuffle(ConstIdx),
Const128(ConstIdx),
I8x16ExtractLaneS(u8), I8x16ExtractLaneU(u8), I8x16ReplaceLane(u8),
I16x8ExtractLaneS(u8), I16x8ExtractLaneU(u8), I16x8ReplaceLane(u8),
I32x4ExtractLane(u8), I32x4ReplaceLane(u8),
I64x2ExtractLane(u8), I64x2ReplaceLane(u8),
F32x4ExtractLane(u8), F32x4ReplaceLane(u8),
F64x2ExtractLane(u8), F64x2ReplaceLane(u8),
V128Not, V128And, V128AndNot, V128Or, V128Xor, V128Bitselect, V128AnyTrue, I8x16Swizzle,
I8x16Splat, I8x16Eq, I8x16Ne, I8x16LtS, I8x16LtU, I8x16GtS, I8x16GtU, I8x16LeS, I8x16LeU, I8x16GeS, I8x16GeU,
I16x8Splat, I16x8Eq, I16x8Ne, I16x8LtS, I16x8LtU, I16x8GtS, I16x8GtU, I16x8LeS, I16x8LeU, I16x8GeS, I16x8GeU,
I32x4Splat, I32x4Eq, I32x4Ne, I32x4LtS, I32x4LtU, I32x4GtS, I32x4GtU, I32x4LeS, I32x4LeU, I32x4GeS, I32x4GeU,
I64x2Splat, I64x2Eq, I64x2Ne, I64x2LtS, I64x2GtS, I64x2LeS, I64x2GeS,
F32x4Splat, F32x4Eq, F32x4Ne, F32x4Lt, F32x4Gt, F32x4Le, F32x4Ge,
F64x2Splat, F64x2Eq, F64x2Ne, F64x2Lt, F64x2Gt, F64x2Le, F64x2Ge,
I8x16Abs, I8x16Neg, I8x16AllTrue, I8x16Bitmask, I8x16Shl, I8x16ShrS, I8x16ShrU, I8x16Add, I8x16Sub, I8x16MinS, I8x16MinU, I8x16MaxS, I8x16MaxU,
I16x8Abs, I16x8Neg, I16x8AllTrue, I16x8Bitmask, I16x8Shl, I16x8ShrS, I16x8ShrU, I16x8Add, I16x8Sub, I16x8MinS, I16x8MinU, I16x8MaxS, I16x8MaxU,
I32x4Abs, I32x4Neg, I32x4AllTrue, I32x4Bitmask, I32x4Shl, I32x4ShrS, I32x4ShrU, I32x4Add, I32x4Sub, I32x4MinS, I32x4MinU, I32x4MaxS, I32x4MaxU,
I64x2Abs, I64x2Neg, I64x2AllTrue, I64x2Bitmask, I64x2Shl, I64x2ShrS, I64x2ShrU, I64x2Add, I64x2Sub, I64x2Mul,
I8x16NarrowI16x8S, I8x16NarrowI16x8U, I8x16AddSatS, I8x16AddSatU, I8x16SubSatS, I8x16SubSatU, I8x16AvgrU,
I16x8NarrowI32x4S, I16x8NarrowI32x4U, I16x8AddSatS, I16x8AddSatU, I16x8SubSatS, I16x8SubSatU, I16x8AvgrU,
I16x8ExtAddPairwiseI8x16S, I16x8ExtAddPairwiseI8x16U, I16x8Mul,
I32x4ExtAddPairwiseI16x8S, I32x4ExtAddPairwiseI16x8U, I32x4Mul,
I16x8ExtMulLowI8x16S, I16x8ExtMulLowI8x16U, I16x8ExtMulHighI8x16S, I16x8ExtMulHighI8x16U,
I32x4ExtMulLowI16x8S, I32x4ExtMulLowI16x8U, I32x4ExtMulHighI16x8S, I32x4ExtMulHighI16x8U,
I64x2ExtMulLowI32x4S, I64x2ExtMulLowI32x4U, I64x2ExtMulHighI32x4S, I64x2ExtMulHighI32x4U,
I16x8ExtendLowI8x16S, I16x8ExtendLowI8x16U, I16x8ExtendHighI8x16S, I16x8ExtendHighI8x16U,
I32x4ExtendLowI16x8S, I32x4ExtendLowI16x8U, I32x4ExtendHighI16x8S, I32x4ExtendHighI16x8U,
I64x2ExtendLowI32x4S, I64x2ExtendLowI32x4U, I64x2ExtendHighI32x4S, I64x2ExtendHighI32x4U,
I8x16Popcnt, I16x8Q15MulrSatS, I32x4DotI16x8S,
F32x4Ceil, F32x4Floor, F32x4Trunc, F32x4Nearest, F32x4Abs, F32x4Neg, F32x4Sqrt, F32x4Add, F32x4Sub, F32x4Mul, F32x4Div, F32x4Min, F32x4Max, F32x4PMin, F32x4PMax,
F64x2Ceil, F64x2Floor, F64x2Trunc, F64x2Nearest, F64x2Abs, F64x2Neg, F64x2Sqrt, F64x2Add, F64x2Sub, F64x2Mul, F64x2Div, F64x2Min, F64x2Max, F64x2PMin, F64x2PMax,
I32x4TruncSatF32x4S, I32x4TruncSatF32x4U,
F32x4ConvertI32x4S, F32x4ConvertI32x4U,
I32x4TruncSatF64x2SZero, I32x4TruncSatF64x2UZero,
F64x2ConvertLowI32x4S, F64x2ConvertLowI32x4U,
F32x4DemoteF64x2Zero, F64x2PromoteLowF32x4,
I8x16RelaxedSwizzle,
I32x4RelaxedTruncF32x4S, I32x4RelaxedTruncF32x4U,
I32x4RelaxedTruncF64x2SZero, I32x4RelaxedTruncF64x2UZero,
F32x4RelaxedMadd, F32x4RelaxedNmadd,
F64x2RelaxedMadd, F64x2RelaxedNmadd,
I8x16RelaxedLaneselect,
I16x8RelaxedLaneselect,
I32x4RelaxedLaneselect,
I64x2RelaxedLaneselect,
F32x4RelaxedMin, F32x4RelaxedMax,
F64x2RelaxedMin, F64x2RelaxedMax,
I16x8RelaxedQ15mulrS,
I16x8RelaxedDotI8x16I7x16S,
I32x4RelaxedDotI8x16I7x16AddS
}
impl Instruction {
#[inline]
pub const fn memory_addr(&self) -> Option<MemAddr> {
match self {
Self::StoreLocalLocal32(arg, ..)
| Self::StoreLocalLocal64(arg, ..)
| Self::StoreLocalLocal128(arg, ..)
| Self::LoadLocal32(arg, ..)
| Self::LoadLocalTee32(arg, ..)
| Self::LoadLocalSet32(arg, ..)
| Self::LoadLocalTee128(arg, ..)
| Self::LoadLocalSet128(arg, ..)
| Self::I32Load(arg)
| Self::I64Load(arg)
| Self::F32Load(arg)
| Self::F64Load(arg)
| Self::I32Load8S(arg)
| Self::I32Load8U(arg)
| Self::I32Load16S(arg)
| Self::I32Load16U(arg)
| Self::I64Load8S(arg)
| Self::I64Load8U(arg)
| Self::I64Load16S(arg)
| Self::I64Load16U(arg)
| Self::I64Load32S(arg)
| Self::I64Load32U(arg)
| Self::I32Store(arg)
| Self::I64Store(arg)
| Self::F32Store(arg)
| Self::F64Store(arg)
| Self::FMaStoreF32(arg)
| Self::FMaStoreF64(arg)
| Self::I32Store8(arg)
| Self::I32Store16(arg)
| Self::I64Store8(arg)
| Self::I64Store16(arg)
| Self::I64Store32(arg)
| Self::V128Load(arg)
| Self::V128Load8x8S(arg)
| Self::V128Load8x8U(arg)
| Self::V128Load16x4S(arg)
| Self::V128Load16x4U(arg)
| Self::V128Load32x2S(arg)
| Self::V128Load32x2U(arg)
| Self::V128Load8Splat(arg)
| Self::V128Load16Splat(arg)
| Self::V128Load32Splat(arg)
| Self::V128Load64Splat(arg)
| Self::V128Load8Lane(arg, ..)
| Self::V128Load16Lane(arg, ..)
| Self::V128Load32Lane(arg, ..)
| Self::V128Load64Lane(arg, ..)
| Self::V128Load32Zero(arg)
| Self::V128Load64Zero(arg)
| Self::V128Store(arg)
| Self::V128Store8Lane(arg, ..)
| Self::V128Store16Lane(arg, ..)
| Self::V128Store32Lane(arg, ..)
| Self::V128Store64Lane(arg, ..) => Some(arg.mem_addr()),
Self::MemorySize(mem)
| Self::MemoryGrow(mem)
| Self::MemoryInit(mem, ..)
| Self::MemoryFill(mem)
| Self::MemoryFillImm(mem, ..) => Some(*mem),
Self::MemoryCopy { dst_mem, src_mem } => Some(if *dst_mem >= *src_mem { *dst_mem } else { *src_mem }),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::Instruction;
#[test]
fn instruction_layout_size_is_stable() {
assert_eq!(core::mem::size_of::<Instruction>(), 16);
}
}