binaryninja/medium_level_il/
lift.rs

1use super::operation::*;
2use super::{MediumLevelExpressionIndex, MediumLevelILFunction, MediumLevelInstructionIndex};
3use crate::architecture::CoreIntrinsic;
4use crate::rc::Ref;
5use crate::variable::{ConstantData, SSAVariable, Variable};
6use std::collections::BTreeMap;
7use std::fmt::{Debug, Formatter};
8
9#[derive(Clone, Debug)]
10pub enum MediumLevelILLiftedOperand {
11    ConstantData(ConstantData),
12    Intrinsic(CoreIntrinsic),
13    Expr(MediumLevelILLiftedInstruction),
14    ExprList(Vec<MediumLevelILLiftedInstruction>),
15    Float(f64),
16    Int(u64),
17    IntList(Vec<u64>),
18    TargetMap(BTreeMap<u64, MediumLevelInstructionIndex>),
19    Var(Variable),
20    VarList(Vec<Variable>),
21    VarSsa(SSAVariable),
22    VarSsaList(Vec<SSAVariable>),
23    InstructionIndex(MediumLevelInstructionIndex),
24}
25
26#[derive(Clone, PartialEq)]
27pub struct MediumLevelILLiftedInstruction {
28    pub function: Ref<MediumLevelILFunction>,
29    pub address: u64,
30    pub instr_index: MediumLevelInstructionIndex,
31    pub expr_index: MediumLevelExpressionIndex,
32    pub size: usize,
33    pub kind: MediumLevelILLiftedInstructionKind,
34}
35
36impl Debug for MediumLevelILLiftedInstruction {
37    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38        f.debug_struct("MediumLevelILLiftedInstruction")
39            .field("address", &self.address)
40            .field("instr_index", &self.instr_index)
41            .field("expr_index", &self.expr_index)
42            .field("size", &self.size)
43            .field("kind", &self.kind)
44            .finish()
45    }
46}
47
48#[derive(Clone, Debug, PartialEq)]
49pub enum MediumLevelILLiftedInstructionKind {
50    Nop,
51    Noret,
52    Bp,
53    Undef,
54    Unimpl,
55    If(LiftedIf),
56    FloatConst(FloatConst),
57    Const(Constant),
58    ConstPtr(Constant),
59    Import(Constant),
60    ExternPtr(ExternPtr),
61    ConstData(LiftedConstData),
62    Jump(LiftedJump),
63    RetHint(LiftedJump),
64    StoreSsa(LiftedStoreSsa),
65    StoreStructSsa(LiftedStoreStructSsa),
66    StoreStruct(LiftedStoreStruct),
67    Store(LiftedStore),
68    JumpTo(LiftedJumpTo),
69    Goto(Goto),
70    FreeVarSlot(FreeVarSlot),
71    SetVarField(LiftedSetVarField),
72    SetVar(LiftedSetVar),
73    FreeVarSlotSsa(FreeVarSlotSsa),
74    SetVarSsaField(LiftedSetVarSsaField),
75    SetVarAliasedField(LiftedSetVarSsaField),
76    SetVarAliased(LiftedSetVarAliased),
77    SetVarSsa(LiftedSetVarSsa),
78    VarPhi(LiftedVarPhi),
79    MemPhi(LiftedMemPhi),
80    VarSplit(VarSplit),
81    SetVarSplit(LiftedSetVarSplit),
82    VarSplitSsa(VarSplitSsa),
83    SetVarSplitSsa(LiftedSetVarSplitSsa),
84    Add(LiftedBinaryOp),
85    Sub(LiftedBinaryOp),
86    And(LiftedBinaryOp),
87    Or(LiftedBinaryOp),
88    Xor(LiftedBinaryOp),
89    Lsl(LiftedBinaryOp),
90    Lsr(LiftedBinaryOp),
91    Asr(LiftedBinaryOp),
92    Rol(LiftedBinaryOp),
93    Ror(LiftedBinaryOp),
94    Mul(LiftedBinaryOp),
95    MuluDp(LiftedBinaryOp),
96    MulsDp(LiftedBinaryOp),
97    Divu(LiftedBinaryOp),
98    DivuDp(LiftedBinaryOp),
99    Divs(LiftedBinaryOp),
100    DivsDp(LiftedBinaryOp),
101    Modu(LiftedBinaryOp),
102    ModuDp(LiftedBinaryOp),
103    Mods(LiftedBinaryOp),
104    ModsDp(LiftedBinaryOp),
105    MinSigned(LiftedBinaryOp),
106    MaxSigned(LiftedBinaryOp),
107    MinUnsigned(LiftedBinaryOp),
108    MaxUnsigned(LiftedBinaryOp),
109    CmpE(LiftedBinaryOp),
110    CmpNe(LiftedBinaryOp),
111    CmpSlt(LiftedBinaryOp),
112    CmpUlt(LiftedBinaryOp),
113    CmpSle(LiftedBinaryOp),
114    CmpUle(LiftedBinaryOp),
115    CmpSge(LiftedBinaryOp),
116    CmpUge(LiftedBinaryOp),
117    CmpSgt(LiftedBinaryOp),
118    CmpUgt(LiftedBinaryOp),
119    TestBit(LiftedBinaryOp),
120    AddOverflow(LiftedBinaryOp),
121    FcmpE(LiftedBinaryOp),
122    FcmpNe(LiftedBinaryOp),
123    FcmpLt(LiftedBinaryOp),
124    FcmpLe(LiftedBinaryOp),
125    FcmpGe(LiftedBinaryOp),
126    FcmpGt(LiftedBinaryOp),
127    FcmpO(LiftedBinaryOp),
128    FcmpUo(LiftedBinaryOp),
129    Fadd(LiftedBinaryOp),
130    Fsub(LiftedBinaryOp),
131    Fmul(LiftedBinaryOp),
132    Fdiv(LiftedBinaryOp),
133    Adc(LiftedBinaryOpCarry),
134    Sbb(LiftedBinaryOpCarry),
135    Rlc(LiftedBinaryOpCarry),
136    Rrc(LiftedBinaryOpCarry),
137    Call(LiftedCall),
138    CallOutput(LiftedCallOutput),
139    CallParam(LiftedCallParam),
140    CallOutputSsa(LiftedCallOutputSsa),
141    CallParamSsa(LiftedCallParamSsa),
142    Tailcall(LiftedCall),
143    Intrinsic(LiftedIntrinsic),
144    Syscall(LiftedSyscallCall),
145    IntrinsicSsa(LiftedIntrinsicSsa),
146    MemoryIntrinsicSsa(LiftedMemoryIntrinsicSsa),
147    MemoryIntrinsicOutputSsa(LiftedMemoryIntrinsicOutputSsa),
148    CallSsa(LiftedCallSsa),
149    TailcallSsa(LiftedCallSsa),
150    CallUntypedSsa(LiftedCallUntypedSsa),
151    TailcallUntypedSsa(LiftedCallUntypedSsa),
152    SyscallSsa(LiftedSyscallSsa),
153    SyscallUntypedSsa(LiftedSyscallUntypedSsa),
154    CallUntyped(LiftedCallUntyped),
155    TailcallUntyped(LiftedCallUntyped),
156    SyscallUntyped(LiftedSyscallUntyped),
157    SeparateParamList(LiftedSeparateParamList),
158    SharedParamSlot(LiftedSharedParamSlot),
159    Neg(LiftedUnaryOp),
160    Not(LiftedUnaryOp),
161    Bswap(LiftedUnaryOp),
162    Popcnt(LiftedUnaryOp),
163    Clz(LiftedUnaryOp),
164    Ctz(LiftedUnaryOp),
165    Rbit(LiftedUnaryOp),
166    Cls(LiftedUnaryOp),
167    Abs(LiftedUnaryOp),
168    Sx(LiftedUnaryOp),
169    Zx(LiftedUnaryOp),
170    LowPart(LiftedUnaryOp),
171    BoolToInt(LiftedUnaryOp),
172    UnimplMem(LiftedUnaryOp),
173    Fsqrt(LiftedUnaryOp),
174    Fneg(LiftedUnaryOp),
175    Fabs(LiftedUnaryOp),
176    FloatToInt(LiftedUnaryOp),
177    IntToFloat(LiftedUnaryOp),
178    FloatConv(LiftedUnaryOp),
179    RoundToInt(LiftedUnaryOp),
180    Floor(LiftedUnaryOp),
181    Ceil(LiftedUnaryOp),
182    Ftrunc(LiftedUnaryOp),
183    Load(LiftedUnaryOp),
184    LoadStruct(LiftedLoadStruct),
185    LoadStructSsa(LiftedLoadStructSsa),
186    LoadSsa(LiftedLoadSsa),
187    Ret(LiftedRet),
188    Var(Var),
189    VarOutput(VarOutput),
190    VarOutputField(VarOutputField),
191    StoreOutput(LiftedStoreOutput),
192    AddressOf(Var),
193    PassByRef(LiftedUnaryOp),
194    ReturnByRef(LiftedUnaryOp),
195    VarField(Field),
196    AddressOfField(Field),
197    VarSsa(VarSsa),
198    VarAliased(VarSsa),
199    VarSsaField(VarSsaField),
200    VarAliasedField(VarSsaField),
201    VarOutputSsa(VarOutputSsa),
202    VarOutputSsaField(VarOutputSsaField),
203    VarOutputAliased(VarOutputAliased),
204    VarOutputAliasedField(VarOutputAliasedField),
205    Trap(Trap),
206    BlockToExpand(LiftedBlockToExpand),
207    // A placeholder for instructions that the Rust bindings do not yet support.
208    // Distinct from `Unimpl` as that is a valid instruction.
209    NotYetImplemented,
210}
211
212impl MediumLevelILLiftedInstruction {
213    pub fn name(&self) -> &'static str {
214        use MediumLevelILLiftedInstructionKind::*;
215        match self.kind {
216            Nop => "Nop",
217            Noret => "Noret",
218            Bp => "Bp",
219            Undef => "Undef",
220            Unimpl => "Unimpl",
221            NotYetImplemented => "NotYetImplemented",
222            If(_) => "If",
223            FloatConst(_) => "FloatConst",
224            Const(_) => "Const",
225            ConstPtr(_) => "ConstPtr",
226            Import(_) => "Import",
227            ExternPtr(_) => "ExternPtr",
228            ConstData(_) => "ConstData",
229            Jump(_) => "Jump",
230            RetHint(_) => "RetHint",
231            StoreSsa(_) => "StoreSsa",
232            StoreStructSsa(_) => "StoreStructSsa",
233            StoreStruct(_) => "StoreStruct",
234            Store(_) => "Store",
235            JumpTo(_) => "JumpTo",
236            Goto(_) => "Goto",
237            FreeVarSlot(_) => "FreeVarSlot",
238            SetVarField(_) => "SetVarField",
239            SetVar(_) => "SetVar",
240            FreeVarSlotSsa(_) => "FreeVarSlotSsa",
241            SetVarSsaField(_) => "SetVarSsaField",
242            SetVarAliasedField(_) => "SetVarAliasedField",
243            SetVarAliased(_) => "SetVarAliased",
244            SetVarSsa(_) => "SetVarSsa",
245            VarPhi(_) => "VarPhi",
246            MemPhi(_) => "MemPhi",
247            VarSplit(_) => "VarSplit",
248            SetVarSplit(_) => "SetVarSplit",
249            VarSplitSsa(_) => "VarSplitSsa",
250            SetVarSplitSsa(_) => "SetVarSplitSsa",
251            Add(_) => "Add",
252            Sub(_) => "Sub",
253            And(_) => "And",
254            Or(_) => "Or",
255            Xor(_) => "Xor",
256            Lsl(_) => "Lsl",
257            Lsr(_) => "Lsr",
258            Asr(_) => "Asr",
259            Rol(_) => "Rol",
260            Ror(_) => "Ror",
261            Mul(_) => "Mul",
262            MuluDp(_) => "MuluDp",
263            MulsDp(_) => "MulsDp",
264            Divu(_) => "Divu",
265            DivuDp(_) => "DivuDp",
266            Divs(_) => "Divs",
267            DivsDp(_) => "DivsDp",
268            Modu(_) => "Modu",
269            ModuDp(_) => "ModuDp",
270            Mods(_) => "Mods",
271            ModsDp(_) => "ModsDp",
272            MinSigned(_) => "MinSigned",
273            MaxSigned(_) => "MaxSigned",
274            MinUnsigned(_) => "MinUnsigned",
275            MaxUnsigned(_) => "MaxUnsigned",
276            CmpE(_) => "CmpE",
277            CmpNe(_) => "CmpNe",
278            CmpSlt(_) => "CmpSlt",
279            CmpUlt(_) => "CmpUlt",
280            CmpSle(_) => "CmpSle",
281            CmpUle(_) => "CmpUle",
282            CmpSge(_) => "CmpSge",
283            CmpUge(_) => "CmpUge",
284            CmpSgt(_) => "CmpSgt",
285            CmpUgt(_) => "CmpUgt",
286            TestBit(_) => "TestBit",
287            AddOverflow(_) => "AddOverflow",
288            FcmpE(_) => "FcmpE",
289            FcmpNe(_) => "FcmpNe",
290            FcmpLt(_) => "FcmpLt",
291            FcmpLe(_) => "FcmpLe",
292            FcmpGe(_) => "FcmpGe",
293            FcmpGt(_) => "FcmpGt",
294            FcmpO(_) => "FcmpO",
295            FcmpUo(_) => "FcmpUo",
296            Fadd(_) => "Fadd",
297            Fsub(_) => "Fsub",
298            Fmul(_) => "Fmul",
299            Fdiv(_) => "Fdiv",
300            Adc(_) => "Adc",
301            Sbb(_) => "Sbb",
302            Rlc(_) => "Rlc",
303            Rrc(_) => "Rrc",
304            Call(_) => "Call",
305            CallOutput(_) => "CallOutput",
306            CallParam(_) => "CallParam",
307            CallOutputSsa(_) => "CallOutputSsa",
308            CallParamSsa(_) => "CallParamSsa",
309            Tailcall(_) => "Tailcall",
310            Syscall(_) => "Syscall",
311            Intrinsic(_) => "Intrinsic",
312            IntrinsicSsa(_) => "IntrinsicSsa",
313            MemoryIntrinsicSsa(_) => "MemoryIntrinsicSsa",
314            MemoryIntrinsicOutputSsa(_) => "MemoryIntrinsicOutputSsa",
315            CallSsa(_) => "CallSsa",
316            TailcallSsa(_) => "TailcallSsa",
317            CallUntypedSsa(_) => "CallUntypedSsa",
318            TailcallUntypedSsa(_) => "TailcallUntypedSsa",
319            SyscallSsa(_) => "SyscallSsa",
320            SyscallUntypedSsa(_) => "SyscallUntypedSsa",
321            CallUntyped(_) => "CallUntyped",
322            TailcallUntyped(_) => "TailcallUntyped",
323            SyscallUntyped(_) => "SyscallUntyped",
324            SeparateParamList(_) => "SeparateParamList",
325            SharedParamSlot(_) => "SharedParamSlot",
326            VarOutput(_) => "VarOutput",
327            VarOutputField(_) => "VarOutputField",
328            StoreOutput(_) => "StoreOutput",
329            Neg(_) => "Neg",
330            Not(_) => "Not",
331            Bswap(_) => "Bswap",
332            Popcnt(_) => "Popcnt",
333            Clz(_) => "Clz",
334            Ctz(_) => "Ctz",
335            Rbit(_) => "Rbit",
336            Cls(_) => "Cls",
337            Abs(_) => "Abs",
338            Sx(_) => "Sx",
339            Zx(_) => "Zx",
340            LowPart(_) => "LowPart",
341            BoolToInt(_) => "BoolToInt",
342            UnimplMem(_) => "UnimplMem",
343            Fsqrt(_) => "Fsqrt",
344            Fneg(_) => "Fneg",
345            Fabs(_) => "Fabs",
346            FloatToInt(_) => "FloatToInt",
347            IntToFloat(_) => "IntToFloat",
348            FloatConv(_) => "FloatConv",
349            RoundToInt(_) => "RoundToInt",
350            Floor(_) => "Floor",
351            Ceil(_) => "Ceil",
352            Ftrunc(_) => "Ftrunc",
353            Load(_) => "Load",
354            LoadStruct(_) => "LoadStruct",
355            LoadStructSsa(_) => "LoadStructSsa",
356            LoadSsa(_) => "LoadSsa",
357            Ret(_) => "Ret",
358            Var(_) => "Var",
359            AddressOf(_) => "AddressOf",
360            PassByRef(_) => "PassByRef",
361            ReturnByRef(_) => "ReturnByRef",
362            VarField(_) => "VarField",
363            AddressOfField(_) => "AddressOfField",
364            VarSsa(_) => "VarSsa",
365            VarAliased(_) => "VarAliased",
366            VarSsaField(_) => "VarSsaField",
367            VarAliasedField(_) => "VarAliasedField",
368            VarOutputSsa(_) => "VarOutputSsa",
369            VarOutputSsaField(_) => "VarOutputSsaField",
370            VarOutputAliased(_) => "VarOutputAliased",
371            VarOutputAliasedField(_) => "VarOutputAliasedField",
372            Trap(_) => "Trap",
373            BlockToExpand(_) => "BlockToExpand",
374        }
375    }
376
377    pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> {
378        use MediumLevelILLiftedInstructionKind::*;
379        use MediumLevelILLiftedOperand as Operand;
380        match &self.kind {
381            Nop | Noret | Bp | Undef | Unimpl | NotYetImplemented => vec![],
382            If(op) => vec![
383                ("condition", Operand::Expr(*op.condition.clone())),
384                ("dest_true", Operand::InstructionIndex(op.dest_true)),
385                ("dest_false", Operand::InstructionIndex(op.dest_false)),
386            ],
387            FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
388            Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
389            ExternPtr(op) => vec![
390                ("constant", Operand::Int(op.constant)),
391                ("offset", Operand::Int(op.offset)),
392            ],
393            ConstData(op) => vec![(
394                "constant_data",
395                Operand::ConstantData(op.constant_data.clone()),
396            )],
397            Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
398            StoreSsa(op) => vec![
399                ("dest", Operand::Expr(*op.dest.clone())),
400                ("dest_memory", Operand::Int(op.dest_memory)),
401                ("src_memory", Operand::Int(op.src_memory)),
402                ("src", Operand::Expr(*op.src.clone())),
403            ],
404            StoreStructSsa(op) => vec![
405                ("dest", Operand::Expr(*op.dest.clone())),
406                ("offset", Operand::Int(op.offset)),
407                ("dest_memory", Operand::Int(op.dest_memory)),
408                ("src_memory", Operand::Int(op.src_memory)),
409                ("src", Operand::Expr(*op.src.clone())),
410            ],
411            StoreStruct(op) => vec![
412                ("dest", Operand::Expr(*op.dest.clone())),
413                ("offset", Operand::Int(op.offset)),
414                ("src", Operand::Expr(*op.src.clone())),
415            ],
416            Store(op) => vec![
417                ("dest", Operand::Expr(*op.dest.clone())),
418                ("src", Operand::Expr(*op.src.clone())),
419            ],
420            JumpTo(op) => vec![
421                ("dest", Operand::Expr(*op.dest.clone())),
422                ("targets", Operand::TargetMap(op.targets.clone())),
423            ],
424            Goto(op) => vec![("dest", Operand::InstructionIndex(op.dest))],
425            FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))],
426            SetVarField(op) => vec![
427                ("dest", Operand::Var(op.dest)),
428                ("offset", Operand::Int(op.offset)),
429                ("src", Operand::Expr(*op.src.clone())),
430            ],
431            SetVar(op) => vec![
432                ("dest", Operand::Var(op.dest)),
433                ("src", Operand::Expr(*op.src.clone())),
434            ],
435            FreeVarSlotSsa(op) => vec![
436                ("dest", Operand::VarSsa(op.dest)),
437                ("prev", Operand::VarSsa(op.prev)),
438            ],
439            SetVarSsaField(op) | SetVarAliasedField(op) => vec![
440                ("dest", Operand::VarSsa(op.dest)),
441                ("prev", Operand::VarSsa(op.prev)),
442                ("offset", Operand::Int(op.offset)),
443                ("src", Operand::Expr(*op.src.clone())),
444            ],
445            SetVarAliased(op) => vec![
446                ("dest", Operand::VarSsa(op.dest)),
447                ("prev", Operand::VarSsa(op.prev)),
448                ("src", Operand::Expr(*op.src.clone())),
449            ],
450            SetVarSsa(op) => vec![
451                ("dest", Operand::VarSsa(op.dest)),
452                ("src", Operand::Expr(*op.src.clone())),
453            ],
454            VarPhi(op) => vec![
455                ("dest", Operand::VarSsa(op.dest)),
456                ("src", Operand::VarSsaList(op.src.clone())),
457            ],
458            MemPhi(op) => vec![
459                ("dest_memory", Operand::Int(op.dest_memory)),
460                ("src_memory", Operand::IntList(op.src_memory.clone())),
461            ],
462            VarSplit(op) => vec![
463                ("high", Operand::Var(op.high)),
464                ("low", Operand::Var(op.low)),
465            ],
466            SetVarSplit(op) => vec![
467                ("high", Operand::Var(op.high)),
468                ("low", Operand::Var(op.low)),
469                ("src", Operand::Expr(*op.src.clone())),
470            ],
471            VarSplitSsa(op) => vec![
472                ("high", Operand::VarSsa(op.high)),
473                ("low", Operand::VarSsa(op.low)),
474            ],
475            SetVarSplitSsa(op) => vec![
476                ("high", Operand::VarSsa(op.high)),
477                ("low", Operand::VarSsa(op.low)),
478                ("src", Operand::Expr(*op.src.clone())),
479            ],
480            Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
481            | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
482            | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op)
483            | MinSigned(op) | MaxSigned(op) | MinUnsigned(op) | MaxUnsigned(op) | CmpE(op)
484            | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
485            | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
486            | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
487            | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![
488                ("left", Operand::Expr(*op.left.clone())),
489                ("right", Operand::Expr(*op.right.clone())),
490            ],
491            Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![
492                ("left", Operand::Expr(*op.left.clone())),
493                ("right", Operand::Expr(*op.right.clone())),
494                ("carry", Operand::Expr(*op.carry.clone())),
495            ],
496            Call(op) | Tailcall(op) => vec![
497                ("output", Operand::ExprList(op.output.clone())),
498                ("dest", Operand::Expr(*op.dest.clone())),
499                ("params", Operand::ExprList(op.params.clone())),
500            ],
501            CallOutput(op) => vec![("output", Operand::VarList(op.output.clone()))],
502            CallParam(op) => vec![("params", Operand::ExprList(op.params.clone()))],
503            CallOutputSsa(op) => vec![
504                ("output", Operand::VarSsaList(op.output.clone())),
505                ("dest_memory", Operand::Int(op.dest_memory)),
506            ],
507            CallParamSsa(op) => vec![
508                ("params", Operand::ExprList(op.params.clone())),
509                ("src_memory", Operand::Int(op.src_memory)),
510            ],
511            Syscall(op) => vec![
512                ("output", Operand::ExprList(op.output.clone())),
513                ("params", Operand::ExprList(op.params.clone())),
514            ],
515            Intrinsic(op) => vec![
516                ("output", Operand::VarList(op.output.clone())),
517                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
518                ("params", Operand::ExprList(op.params.clone())),
519            ],
520            IntrinsicSsa(op) => vec![
521                ("output", Operand::VarSsaList(op.output.clone())),
522                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
523                ("params", Operand::ExprList(op.params.clone())),
524            ],
525            MemoryIntrinsicSsa(op) => vec![
526                ("output", Operand::Expr(*op.output.clone())),
527                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
528                ("params", Operand::ExprList(op.params.clone())),
529                ("src_memory", Operand::Int(op.src_memory)),
530            ],
531            MemoryIntrinsicOutputSsa(op) => vec![
532                ("dest_memory", Operand::Int(op.dest_memory)),
533                ("output", Operand::VarSsaList(op.output.clone())),
534            ],
535            CallSsa(op) | TailcallSsa(op) => vec![
536                ("output", Operand::ExprList(op.output.clone())),
537                ("dest", Operand::Expr(*op.dest.clone())),
538                ("params", Operand::ExprList(op.params.clone())),
539                ("src_memory", Operand::Int(op.src_memory)),
540            ],
541            CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![
542                ("output", Operand::ExprList(op.output.clone())),
543                ("dest", Operand::Expr(*op.dest.clone())),
544                ("params", Operand::ExprList(op.params.clone())),
545                ("stack", Operand::Expr(*op.stack.clone())),
546            ],
547            SyscallSsa(op) => vec![
548                ("output", Operand::ExprList(op.output.clone())),
549                ("params", Operand::ExprList(op.params.clone())),
550                ("src_memory", Operand::Int(op.src_memory)),
551            ],
552            SyscallUntypedSsa(op) => vec![
553                ("output", Operand::ExprList(op.output.clone())),
554                ("params", Operand::ExprList(op.params.clone())),
555                ("stack", Operand::Expr(*op.stack.clone())),
556            ],
557            CallUntyped(op) | TailcallUntyped(op) => vec![
558                ("output", Operand::ExprList(op.output.clone())),
559                ("dest", Operand::Expr(*op.dest.clone())),
560                ("params", Operand::ExprList(op.params.clone())),
561                ("stack", Operand::Expr(*op.stack.clone())),
562            ],
563            SyscallUntyped(op) => vec![
564                ("output", Operand::ExprList(op.output.clone())),
565                ("params", Operand::ExprList(op.params.clone())),
566                ("stack", Operand::Expr(*op.stack.clone())),
567            ],
568            Neg(op) | Not(op) | Bswap(op) | Popcnt(op) | Clz(op) | Ctz(op) | Rbit(op) | Cls(op)
569            | Abs(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
570            | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
571            | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
572                vec![("src", Operand::Expr(*op.src.clone()))]
573            }
574            LoadStruct(op) => vec![
575                ("src", Operand::Expr(*op.src.clone())),
576                ("offset", Operand::Int(op.offset)),
577            ],
578            LoadStructSsa(op) => vec![
579                ("src", Operand::Expr(*op.src.clone())),
580                ("offset", Operand::Int(op.offset)),
581                ("src_memory", Operand::Int(op.src_memory)),
582            ],
583            LoadSsa(op) => vec![
584                ("src", Operand::Expr(*op.src.clone())),
585                ("src_memory", Operand::Int(op.src_memory)),
586            ],
587            Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
588            SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))],
589            SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))],
590            Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))],
591            VarOutput(op) => vec![("dest", Operand::Var(op.dest))],
592            VarOutputField(op) => vec![
593                ("dest", Operand::Var(op.dest)),
594                ("offset", Operand::Int(op.offset)),
595            ],
596            StoreOutput(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
597            PassByRef(op) => vec![("src", Operand::Expr(*op.src.clone()))],
598            ReturnByRef(op) => vec![("src", Operand::Expr(*op.src.clone()))],
599            VarField(op) | AddressOfField(op) => vec![
600                ("src", Operand::Var(op.src)),
601                ("offset", Operand::Int(op.offset)),
602            ],
603            VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))],
604            VarSsaField(op) | VarAliasedField(op) => vec![
605                ("src", Operand::VarSsa(op.src)),
606                ("offset", Operand::Int(op.offset)),
607            ],
608            VarOutputSsa(op) => vec![("dest", Operand::VarSsa(op.dest))],
609            VarOutputSsaField(op) => vec![
610                ("dest", Operand::VarSsa(op.dest)),
611                ("prev", Operand::VarSsa(op.prev)),
612                ("offset", Operand::Int(op.offset)),
613            ],
614            VarOutputAliased(op) => vec![
615                ("dest", Operand::VarSsa(op.dest)),
616                ("prev", Operand::VarSsa(op.prev)),
617            ],
618            VarOutputAliasedField(op) => vec![
619                ("dest", Operand::VarSsa(op.dest)),
620                ("prev", Operand::VarSsa(op.prev)),
621                ("offset", Operand::Int(op.offset)),
622            ],
623            Trap(op) => vec![("vector", Operand::Int(op.vector))],
624            BlockToExpand(op) => vec![("exprs", Operand::ExprList(op.exprs.clone()))],
625        }
626    }
627}