use super::{FuncAddr, GlobalAddr, LabelAddr, LocalAddr, TableAddr, TypeAddr, ValType};
use crate::{DataAddr, ElemAddr, MemAddr};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum BlockArgs {
Empty,
Type(ValType),
FuncType(u32),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct BlockArgsPacked([u8; 5]); impl BlockArgsPacked {
pub fn new(args: BlockArgs) -> Self {
let mut packed = [0; 5];
match args {
BlockArgs::Empty => packed[0] = 0,
BlockArgs::Type(t) => {
packed[0] = 1;
packed[1] = t.to_byte();
}
BlockArgs::FuncType(t) => {
packed[0] = 2;
packed[1..].copy_from_slice(&t.to_le_bytes());
}
}
Self(packed)
}
pub fn unpack(&self) -> BlockArgs {
match self.0[0] {
0 => BlockArgs::Empty,
1 => BlockArgs::Type(ValType::from_byte(self.0[1]).unwrap()),
2 => BlockArgs::FuncType(u32::from_le_bytes(self.0[1..].try_into().unwrap())),
_ => unreachable!(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct MemoryArg {
pub offset: u64,
pub mem_addr: MemAddr,
}
type BrTableDefault = u32;
type BrTableLen = u32;
type EndOffset = u32;
type ElseOffset = u32;
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum ConstInstruction {
I32Const(i32),
I64Const(i64),
F32Const(f32),
F64Const(f64),
GlobalGet(GlobalAddr),
RefNull(ValType),
RefFunc(FuncAddr),
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum Instruction {
BrLabel(LabelAddr),
I64XorConstRotl(i64),
LocalTeeGet(LocalAddr, LocalAddr),
LocalGet2(LocalAddr, LocalAddr),
LocalGet3(LocalAddr, LocalAddr, LocalAddr),
LocalGetSet(LocalAddr, LocalAddr),
Unreachable,
Nop,
Block(BlockArgs, EndOffset),
Loop(BlockArgs, EndOffset),
If(BlockArgsPacked, ElseOffset, EndOffset), Else(EndOffset),
EndBlockFrame,
Br(LabelAddr),
BrIf(LabelAddr),
BrTable(BrTableDefault, BrTableLen), Return,
Call(FuncAddr),
CallIndirect(TypeAddr, TableAddr),
Drop,
Select(Option<ValType>),
LocalGet(LocalAddr),
LocalSet(LocalAddr),
LocalTee(LocalAddr),
GlobalGet(GlobalAddr),
GlobalSet(GlobalAddr),
I32Load { offset: u64, mem_addr: MemAddr },
I64Load { offset: u64, mem_addr: MemAddr },
F32Load { offset: u64, mem_addr: MemAddr },
F64Load { offset: u64, mem_addr: MemAddr },
I32Load8S { offset: u64, mem_addr: MemAddr },
I32Load8U { offset: u64, mem_addr: MemAddr },
I32Load16S { offset: u64, mem_addr: MemAddr },
I32Load16U { offset: u64, mem_addr: MemAddr },
I64Load8S { offset: u64, mem_addr: MemAddr },
I64Load8U { offset: u64, mem_addr: MemAddr },
I64Load16S { offset: u64, mem_addr: MemAddr },
I64Load16U { offset: u64, mem_addr: MemAddr },
I64Load32S { offset: u64, mem_addr: MemAddr },
I64Load32U { offset: u64, mem_addr: MemAddr },
I32Store { offset: u64, mem_addr: MemAddr },
I64Store { offset: u64, mem_addr: MemAddr },
F32Store { offset: u64, mem_addr: MemAddr },
F64Store { offset: u64, mem_addr: MemAddr },
I32Store8 { offset: u64, mem_addr: MemAddr },
I32Store16 { offset: u64, mem_addr: MemAddr },
I64Store8 { offset: u64, mem_addr: MemAddr },
I64Store16 { offset: u64, mem_addr: MemAddr },
I64Store32 { offset: u64, mem_addr: MemAddr },
MemorySize(MemAddr, u8),
MemoryGrow(MemAddr, u8),
I32Const(i32),
I64Const(i64),
F32Const(f32),
F64Const(f64),
RefNull(ValType),
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,
I32And,
I32Or,
I32Xor,
I32Shl,
I32ShrS,
I32ShrU,
I32Rotl,
I32Rotr,
I64Clz,
I64Ctz,
I64Popcnt,
I64Add,
I64Sub,
I64Mul,
I64DivS,
I64DivU,
I64RemS,
I64RemU,
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,
I32ReinterpretF32,
I64ReinterpretF64,
F32ReinterpretI32,
F64ReinterpretI64,
I32TruncSatF32S,
I32TruncSatF32U,
I32TruncSatF64S,
I32TruncSatF64U,
I64TruncSatF32S,
I64TruncSatF32U,
I64TruncSatF64S,
I64TruncSatF64U,
TableInit(TableAddr, ElemAddr),
TableGet(TableAddr),
TableSet(TableAddr),
TableCopy { from: TableAddr, to: TableAddr },
TableGrow(TableAddr),
TableSize(TableAddr),
TableFill(TableAddr),
MemoryInit(MemAddr, DataAddr),
MemoryCopy(MemAddr, MemAddr),
MemoryFill(MemAddr),
DataDrop(DataAddr),
}
#[cfg(test)]
mod test_blockargs_packed {
use super::*;
#[test]
fn test_empty() {
let args = BlockArgs::Empty;
let packed = BlockArgsPacked::new(args);
assert_eq!(packed.unpack(), BlockArgs::Empty);
}
#[test]
fn test_val_type_i32() {
let args = BlockArgs::Type(ValType::I32);
let packed = BlockArgsPacked::new(args);
assert_eq!(packed.unpack(), BlockArgs::Type(ValType::I32));
}
#[test]
fn test_val_type_i64() {
let args = BlockArgs::Type(ValType::I64);
let packed = BlockArgsPacked::new(args);
assert_eq!(packed.unpack(), BlockArgs::Type(ValType::I64));
}
#[test]
fn test_val_type_f32() {
let args = BlockArgs::Type(ValType::F32);
let packed = BlockArgsPacked::new(args);
assert_eq!(packed.unpack(), BlockArgs::Type(ValType::F32));
}
#[test]
fn test_val_type_f64() {
let args = BlockArgs::Type(ValType::F64);
let packed = BlockArgsPacked::new(args);
assert_eq!(packed.unpack(), BlockArgs::Type(ValType::F64));
}
#[test]
fn test_func_type() {
let func_type = 123; let args = BlockArgs::FuncType(func_type);
let packed = BlockArgsPacked::new(args);
assert_eq!(packed.unpack(), BlockArgs::FuncType(func_type));
}
}