Skip to main content

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