use super::operation::*; use super::{MediumLevelExpressionIndex, MediumLevelILFunction, MediumLevelInstructionIndex}; use crate::architecture::CoreIntrinsic; use crate::rc::Ref; use crate::variable::{ConstantData, SSAVariable, Variable}; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; #[derive(Clone, Debug)] pub enum MediumLevelILLiftedOperand { ConstantData(ConstantData), Intrinsic(CoreIntrinsic), Expr(MediumLevelILLiftedInstruction), ExprList(Vec), Float(f64), Int(u64), IntList(Vec), TargetMap(BTreeMap), Var(Variable), VarList(Vec), VarSsa(SSAVariable), VarSsaList(Vec), InstructionIndex(MediumLevelInstructionIndex), } #[derive(Clone, PartialEq)] pub struct MediumLevelILLiftedInstruction { pub function: Ref, pub address: u64, pub instr_index: MediumLevelInstructionIndex, pub expr_index: MediumLevelExpressionIndex, pub size: usize, pub kind: MediumLevelILLiftedInstructionKind, } impl Debug for MediumLevelILLiftedInstruction { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MediumLevelILLiftedInstruction") .field("address", &self.address) .field("instr_index", &self.instr_index) .field("expr_index", &self.expr_index) .field("size", &self.size) .field("kind", &self.kind) .finish() } } #[derive(Clone, Debug, PartialEq)] pub enum MediumLevelILLiftedInstructionKind { Nop, Noret, Bp, Undef, Unimpl, If(LiftedIf), FloatConst(FloatConst), Const(Constant), ConstPtr(Constant), Import(Constant), ExternPtr(ExternPtr), ConstData(LiftedConstData), Jump(LiftedJump), RetHint(LiftedJump), StoreSsa(LiftedStoreSsa), StoreStructSsa(LiftedStoreStructSsa), StoreStruct(LiftedStoreStruct), Store(LiftedStore), JumpTo(LiftedJumpTo), Goto(Goto), FreeVarSlot(FreeVarSlot), SetVarField(LiftedSetVarField), SetVar(LiftedSetVar), FreeVarSlotSsa(FreeVarSlotSsa), SetVarSsaField(LiftedSetVarSsaField), SetVarAliasedField(LiftedSetVarSsaField), SetVarAliased(LiftedSetVarAliased), SetVarSsa(LiftedSetVarSsa), VarPhi(LiftedVarPhi), MemPhi(LiftedMemPhi), VarSplit(VarSplit), SetVarSplit(LiftedSetVarSplit), VarSplitSsa(VarSplitSsa), SetVarSplitSsa(LiftedSetVarSplitSsa), Add(LiftedBinaryOp), Sub(LiftedBinaryOp), And(LiftedBinaryOp), Or(LiftedBinaryOp), Xor(LiftedBinaryOp), Lsl(LiftedBinaryOp), Lsr(LiftedBinaryOp), Asr(LiftedBinaryOp), Rol(LiftedBinaryOp), Ror(LiftedBinaryOp), Mul(LiftedBinaryOp), MuluDp(LiftedBinaryOp), MulsDp(LiftedBinaryOp), Divu(LiftedBinaryOp), DivuDp(LiftedBinaryOp), Divs(LiftedBinaryOp), DivsDp(LiftedBinaryOp), Modu(LiftedBinaryOp), ModuDp(LiftedBinaryOp), Mods(LiftedBinaryOp), ModsDp(LiftedBinaryOp), CmpE(LiftedBinaryOp), CmpNe(LiftedBinaryOp), CmpSlt(LiftedBinaryOp), CmpUlt(LiftedBinaryOp), CmpSle(LiftedBinaryOp), CmpUle(LiftedBinaryOp), CmpSge(LiftedBinaryOp), CmpUge(LiftedBinaryOp), CmpSgt(LiftedBinaryOp), CmpUgt(LiftedBinaryOp), TestBit(LiftedBinaryOp), AddOverflow(LiftedBinaryOp), FcmpE(LiftedBinaryOp), FcmpNe(LiftedBinaryOp), FcmpLt(LiftedBinaryOp), FcmpLe(LiftedBinaryOp), FcmpGe(LiftedBinaryOp), FcmpGt(LiftedBinaryOp), FcmpO(LiftedBinaryOp), FcmpUo(LiftedBinaryOp), Fadd(LiftedBinaryOp), Fsub(LiftedBinaryOp), Fmul(LiftedBinaryOp), Fdiv(LiftedBinaryOp), Adc(LiftedBinaryOpCarry), Sbb(LiftedBinaryOpCarry), Rlc(LiftedBinaryOpCarry), Rrc(LiftedBinaryOpCarry), Call(LiftedCall), CallOutput(LiftedCallOutput), CallParam(LiftedCallParam), CallOutputSsa(LiftedCallOutputSsa), CallParamSsa(LiftedCallParamSsa), Tailcall(LiftedCall), Intrinsic(LiftedIntrinsic), Syscall(LiftedSyscallCall), IntrinsicSsa(LiftedIntrinsicSsa), MemoryIntrinsicSsa(LiftedMemoryIntrinsicSsa), MemoryIntrinsicOutputSsa(LiftedMemoryIntrinsicOutputSsa), CallSsa(LiftedCallSsa), TailcallSsa(LiftedCallSsa), CallUntypedSsa(LiftedCallUntypedSsa), TailcallUntypedSsa(LiftedCallUntypedSsa), SyscallSsa(LiftedSyscallSsa), SyscallUntypedSsa(LiftedSyscallUntypedSsa), CallUntyped(LiftedCallUntyped), TailcallUntyped(LiftedCallUntyped), SyscallUntyped(LiftedSyscallUntyped), SeparateParamList(LiftedSeparateParamList), SharedParamSlot(LiftedSharedParamSlot), Neg(LiftedUnaryOp), Not(LiftedUnaryOp), Bswap(LiftedUnaryOp), Popcnt(LiftedUnaryOp), Clz(LiftedUnaryOp), Ctz(LiftedUnaryOp), Rbit(LiftedUnaryOp), Cls(LiftedUnaryOp), Sx(LiftedUnaryOp), Zx(LiftedUnaryOp), LowPart(LiftedUnaryOp), BoolToInt(LiftedUnaryOp), UnimplMem(LiftedUnaryOp), Fsqrt(LiftedUnaryOp), Fneg(LiftedUnaryOp), Fabs(LiftedUnaryOp), FloatToInt(LiftedUnaryOp), IntToFloat(LiftedUnaryOp), FloatConv(LiftedUnaryOp), RoundToInt(LiftedUnaryOp), Floor(LiftedUnaryOp), Ceil(LiftedUnaryOp), Ftrunc(LiftedUnaryOp), Load(LiftedUnaryOp), LoadStruct(LiftedLoadStruct), LoadStructSsa(LiftedLoadStructSsa), LoadSsa(LiftedLoadSsa), Ret(LiftedRet), Var(Var), VarOutput(VarOutput), VarOutputField(VarOutputField), StoreOutput(LiftedStoreOutput), AddressOf(Var), PassByRef(LiftedUnaryOp), ReturnByRef(LiftedUnaryOp), VarField(Field), AddressOfField(Field), VarSsa(VarSsa), VarAliased(VarSsa), VarSsaField(VarSsaField), VarAliasedField(VarSsaField), VarOutputSsa(VarOutputSsa), VarOutputSsaField(VarOutputSsaField), VarOutputAliased(VarOutputAliased), VarOutputAliasedField(VarOutputAliasedField), Trap(Trap), BlockToExpand(LiftedBlockToExpand), // A placeholder for instructions that the Rust bindings do not yet support. // Distinct from `Unimpl` as that is a valid instruction. NotYetImplemented, } impl MediumLevelILLiftedInstruction { pub fn name(&self) -> &'static str { use MediumLevelILLiftedInstructionKind::*; match self.kind { Nop => "Nop", Noret => "Noret", Bp => "Bp", Undef => "Undef", Unimpl => "Unimpl", NotYetImplemented => "NotYetImplemented", If(_) => "If", FloatConst(_) => "FloatConst", Const(_) => "Const", ConstPtr(_) => "ConstPtr", Import(_) => "Import", ExternPtr(_) => "ExternPtr", ConstData(_) => "ConstData", Jump(_) => "Jump", RetHint(_) => "RetHint", StoreSsa(_) => "StoreSsa", StoreStructSsa(_) => "StoreStructSsa", StoreStruct(_) => "StoreStruct", Store(_) => "Store", JumpTo(_) => "JumpTo", Goto(_) => "Goto", FreeVarSlot(_) => "FreeVarSlot", SetVarField(_) => "SetVarField", SetVar(_) => "SetVar", FreeVarSlotSsa(_) => "FreeVarSlotSsa", SetVarSsaField(_) => "SetVarSsaField", SetVarAliasedField(_) => "SetVarAliasedField", SetVarAliased(_) => "SetVarAliased", SetVarSsa(_) => "SetVarSsa", VarPhi(_) => "VarPhi", MemPhi(_) => "MemPhi", VarSplit(_) => "VarSplit", SetVarSplit(_) => "SetVarSplit", VarSplitSsa(_) => "VarSplitSsa", SetVarSplitSsa(_) => "SetVarSplitSsa", Add(_) => "Add", Sub(_) => "Sub", And(_) => "And", Or(_) => "Or", Xor(_) => "Xor", Lsl(_) => "Lsl", Lsr(_) => "Lsr", Asr(_) => "Asr", Rol(_) => "Rol", Ror(_) => "Ror", Mul(_) => "Mul", MuluDp(_) => "MuluDp", MulsDp(_) => "MulsDp", Divu(_) => "Divu", DivuDp(_) => "DivuDp", Divs(_) => "Divs", DivsDp(_) => "DivsDp", Modu(_) => "Modu", ModuDp(_) => "ModuDp", Mods(_) => "Mods", ModsDp(_) => "ModsDp", CmpE(_) => "CmpE", CmpNe(_) => "CmpNe", CmpSlt(_) => "CmpSlt", CmpUlt(_) => "CmpUlt", CmpSle(_) => "CmpSle", CmpUle(_) => "CmpUle", CmpSge(_) => "CmpSge", CmpUge(_) => "CmpUge", CmpSgt(_) => "CmpSgt", CmpUgt(_) => "CmpUgt", TestBit(_) => "TestBit", AddOverflow(_) => "AddOverflow", FcmpE(_) => "FcmpE", FcmpNe(_) => "FcmpNe", FcmpLt(_) => "FcmpLt", FcmpLe(_) => "FcmpLe", FcmpGe(_) => "FcmpGe", FcmpGt(_) => "FcmpGt", FcmpO(_) => "FcmpO", FcmpUo(_) => "FcmpUo", Fadd(_) => "Fadd", Fsub(_) => "Fsub", Fmul(_) => "Fmul", Fdiv(_) => "Fdiv", Adc(_) => "Adc", Sbb(_) => "Sbb", Rlc(_) => "Rlc", Rrc(_) => "Rrc", Call(_) => "Call", CallOutput(_) => "CallOutput", CallParam(_) => "CallParam", CallOutputSsa(_) => "CallOutputSsa", CallParamSsa(_) => "CallParamSsa", Tailcall(_) => "Tailcall", Syscall(_) => "Syscall", Intrinsic(_) => "Intrinsic", IntrinsicSsa(_) => "IntrinsicSsa", MemoryIntrinsicSsa(_) => "MemoryIntrinsicSsa", MemoryIntrinsicOutputSsa(_) => "MemoryIntrinsicOutputSsa", CallSsa(_) => "CallSsa", TailcallSsa(_) => "TailcallSsa", CallUntypedSsa(_) => "CallUntypedSsa", TailcallUntypedSsa(_) => "TailcallUntypedSsa", SyscallSsa(_) => "SyscallSsa", SyscallUntypedSsa(_) => "SyscallUntypedSsa", CallUntyped(_) => "CallUntyped", TailcallUntyped(_) => "TailcallUntyped", SyscallUntyped(_) => "SyscallUntyped", SeparateParamList(_) => "SeparateParamList", SharedParamSlot(_) => "SharedParamSlot", VarOutput(_) => "VarOutput", VarOutputField(_) => "VarOutputField", StoreOutput(_) => "StoreOutput", Neg(_) => "Neg", Not(_) => "Not", Bswap(_) => "Bswap", Popcnt(_) => "Popcnt", Clz(_) => "Clz", Ctz(_) => "Ctz", Rbit(_) => "Rbit", Cls(_) => "Cls", Sx(_) => "Sx", Zx(_) => "Zx", LowPart(_) => "LowPart", BoolToInt(_) => "BoolToInt", UnimplMem(_) => "UnimplMem", Fsqrt(_) => "Fsqrt", Fneg(_) => "Fneg", Fabs(_) => "Fabs", FloatToInt(_) => "FloatToInt", IntToFloat(_) => "IntToFloat", FloatConv(_) => "FloatConv", RoundToInt(_) => "RoundToInt", Floor(_) => "Floor", Ceil(_) => "Ceil", Ftrunc(_) => "Ftrunc", Load(_) => "Load", LoadStruct(_) => "LoadStruct", LoadStructSsa(_) => "LoadStructSsa", LoadSsa(_) => "LoadSsa", Ret(_) => "Ret", Var(_) => "Var", AddressOf(_) => "AddressOf", PassByRef(_) => "PassByRef", ReturnByRef(_) => "ReturnByRef", VarField(_) => "VarField", AddressOfField(_) => "AddressOfField", VarSsa(_) => "VarSsa", VarAliased(_) => "VarAliased", VarSsaField(_) => "VarSsaField", VarAliasedField(_) => "VarAliasedField", VarOutputSsa(_) => "VarOutputSsa", VarOutputSsaField(_) => "VarOutputSsaField", VarOutputAliased(_) => "VarOutputAliased", VarOutputAliasedField(_) => "VarOutputAliasedField", Trap(_) => "Trap", BlockToExpand(_) => "BlockToExpand", } } pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> { use MediumLevelILLiftedInstructionKind::*; use MediumLevelILLiftedOperand as Operand; match &self.kind { Nop | Noret | Bp | Undef | Unimpl | NotYetImplemented => vec![], If(op) => vec![ ("condition", Operand::Expr(*op.condition.clone())), ("dest_true", Operand::InstructionIndex(op.dest_true)), ("dest_false", Operand::InstructionIndex(op.dest_false)), ], FloatConst(op) => vec![("constant", Operand::Float(op.constant))], Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))], ExternPtr(op) => vec![ ("constant", Operand::Int(op.constant)), ("offset", Operand::Int(op.offset)), ], ConstData(op) => vec![( "constant_data", Operand::ConstantData(op.constant_data.clone()), )], Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))], StoreSsa(op) => vec![ ("dest", Operand::Expr(*op.dest.clone())), ("dest_memory", Operand::Int(op.dest_memory)), ("src_memory", Operand::Int(op.src_memory)), ("src", Operand::Expr(*op.src.clone())), ], StoreStructSsa(op) => vec![ ("dest", Operand::Expr(*op.dest.clone())), ("offset", Operand::Int(op.offset)), ("dest_memory", Operand::Int(op.dest_memory)), ("src_memory", Operand::Int(op.src_memory)), ("src", Operand::Expr(*op.src.clone())), ], StoreStruct(op) => vec![ ("dest", Operand::Expr(*op.dest.clone())), ("offset", Operand::Int(op.offset)), ("src", Operand::Expr(*op.src.clone())), ], Store(op) => vec![ ("dest", Operand::Expr(*op.dest.clone())), ("src", Operand::Expr(*op.src.clone())), ], JumpTo(op) => vec![ ("dest", Operand::Expr(*op.dest.clone())), ("targets", Operand::TargetMap(op.targets.clone())), ], Goto(op) => vec![("dest", Operand::InstructionIndex(op.dest))], FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))], SetVarField(op) => vec![ ("dest", Operand::Var(op.dest)), ("offset", Operand::Int(op.offset)), ("src", Operand::Expr(*op.src.clone())), ], SetVar(op) => vec![ ("dest", Operand::Var(op.dest)), ("src", Operand::Expr(*op.src.clone())), ], FreeVarSlotSsa(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ], SetVarSsaField(op) | SetVarAliasedField(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ("offset", Operand::Int(op.offset)), ("src", Operand::Expr(*op.src.clone())), ], SetVarAliased(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ("src", Operand::Expr(*op.src.clone())), ], SetVarSsa(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("src", Operand::Expr(*op.src.clone())), ], VarPhi(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("src", Operand::VarSsaList(op.src.clone())), ], MemPhi(op) => vec![ ("dest_memory", Operand::Int(op.dest_memory)), ("src_memory", Operand::IntList(op.src_memory.clone())), ], VarSplit(op) => vec![ ("high", Operand::Var(op.high)), ("low", Operand::Var(op.low)), ], SetVarSplit(op) => vec![ ("high", Operand::Var(op.high)), ("low", Operand::Var(op.low)), ("src", Operand::Expr(*op.src.clone())), ], VarSplitSsa(op) => vec![ ("high", Operand::VarSsa(op.high)), ("low", Operand::VarSsa(op.low)), ], SetVarSplitSsa(op) => vec![ ("high", Operand::VarSsa(op.high)), ("low", Operand::VarSsa(op.low)), ("src", Operand::Expr(*op.src.clone())), ], Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op) | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op) | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op) | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op) | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op) | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op) | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![ ("left", Operand::Expr(*op.left.clone())), ("right", Operand::Expr(*op.right.clone())), ], Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![ ("left", Operand::Expr(*op.left.clone())), ("right", Operand::Expr(*op.right.clone())), ("carry", Operand::Expr(*op.carry.clone())), ], Call(op) | Tailcall(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ], CallOutput(op) => vec![("output", Operand::VarList(op.output.clone()))], CallParam(op) => vec![("params", Operand::ExprList(op.params.clone()))], CallOutputSsa(op) => vec![ ("output", Operand::VarSsaList(op.output.clone())), ("dest_memory", Operand::Int(op.dest_memory)), ], CallParamSsa(op) => vec![ ("params", Operand::ExprList(op.params.clone())), ("src_memory", Operand::Int(op.src_memory)), ], Syscall(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ], Intrinsic(op) => vec![ ("output", Operand::VarList(op.output.clone())), ("intrinsic", Operand::Intrinsic(op.intrinsic)), ("params", Operand::ExprList(op.params.clone())), ], IntrinsicSsa(op) => vec![ ("output", Operand::VarSsaList(op.output.clone())), ("intrinsic", Operand::Intrinsic(op.intrinsic)), ("params", Operand::ExprList(op.params.clone())), ], MemoryIntrinsicSsa(op) => vec![ ("output", Operand::Expr(*op.output.clone())), ("intrinsic", Operand::Intrinsic(op.intrinsic)), ("params", Operand::ExprList(op.params.clone())), ("src_memory", Operand::Int(op.src_memory)), ], MemoryIntrinsicOutputSsa(op) => vec![ ("dest_memory", Operand::Int(op.dest_memory)), ("output", Operand::VarSsaList(op.output.clone())), ], CallSsa(op) | TailcallSsa(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ("src_memory", Operand::Int(op.src_memory)), ], CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], SyscallSsa(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ("src_memory", Operand::Int(op.src_memory)), ], SyscallUntypedSsa(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], CallUntyped(op) | TailcallUntyped(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("dest", Operand::Expr(*op.dest.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], SyscallUntyped(op) => vec![ ("output", Operand::ExprList(op.output.clone())), ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], Neg(op) | Not(op) | Bswap(op) | Popcnt(op) | Clz(op) | Ctz(op) | Rbit(op) | Cls(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => { vec![("src", Operand::Expr(*op.src.clone()))] } LoadStruct(op) => vec![ ("src", Operand::Expr(*op.src.clone())), ("offset", Operand::Int(op.offset)), ], LoadStructSsa(op) => vec![ ("src", Operand::Expr(*op.src.clone())), ("offset", Operand::Int(op.offset)), ("src_memory", Operand::Int(op.src_memory)), ], LoadSsa(op) => vec![ ("src", Operand::Expr(*op.src.clone())), ("src_memory", Operand::Int(op.src_memory)), ], Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))], SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))], SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))], Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))], VarOutput(op) => vec![("dest", Operand::Var(op.dest))], VarOutputField(op) => vec![ ("dest", Operand::Var(op.dest)), ("offset", Operand::Int(op.offset)), ], StoreOutput(op) => vec![("dest", Operand::Expr(*op.dest.clone()))], PassByRef(op) => vec![("src", Operand::Expr(*op.src.clone()))], ReturnByRef(op) => vec![("src", Operand::Expr(*op.src.clone()))], VarField(op) | AddressOfField(op) => vec![ ("src", Operand::Var(op.src)), ("offset", Operand::Int(op.offset)), ], VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))], VarSsaField(op) | VarAliasedField(op) => vec![ ("src", Operand::VarSsa(op.src)), ("offset", Operand::Int(op.offset)), ], VarOutputSsa(op) => vec![("dest", Operand::VarSsa(op.dest))], VarOutputSsaField(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ("offset", Operand::Int(op.offset)), ], VarOutputAliased(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ], VarOutputAliasedField(op) => vec![ ("dest", Operand::VarSsa(op.dest)), ("prev", Operand::VarSsa(op.prev)), ("offset", Operand::Int(op.offset)), ], Trap(op) => vec![("vector", Operand::Int(op.vector))], BlockToExpand(op) => vec![("exprs", Operand::ExprList(op.exprs.clone()))], } } }