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    CmpE(LiftedBinaryOp),
106    CmpNe(LiftedBinaryOp),
107    CmpSlt(LiftedBinaryOp),
108    CmpUlt(LiftedBinaryOp),
109    CmpSle(LiftedBinaryOp),
110    CmpUle(LiftedBinaryOp),
111    CmpSge(LiftedBinaryOp),
112    CmpUge(LiftedBinaryOp),
113    CmpSgt(LiftedBinaryOp),
114    CmpUgt(LiftedBinaryOp),
115    TestBit(LiftedBinaryOp),
116    AddOverflow(LiftedBinaryOp),
117    FcmpE(LiftedBinaryOp),
118    FcmpNe(LiftedBinaryOp),
119    FcmpLt(LiftedBinaryOp),
120    FcmpLe(LiftedBinaryOp),
121    FcmpGe(LiftedBinaryOp),
122    FcmpGt(LiftedBinaryOp),
123    FcmpO(LiftedBinaryOp),
124    FcmpUo(LiftedBinaryOp),
125    Fadd(LiftedBinaryOp),
126    Fsub(LiftedBinaryOp),
127    Fmul(LiftedBinaryOp),
128    Fdiv(LiftedBinaryOp),
129    Adc(LiftedBinaryOpCarry),
130    Sbb(LiftedBinaryOpCarry),
131    Rlc(LiftedBinaryOpCarry),
132    Rrc(LiftedBinaryOpCarry),
133    Call(LiftedCall),
134    CallOutput(LiftedCallOutput),
135    CallParam(LiftedCallParam),
136    CallOutputSsa(LiftedCallOutputSsa),
137    CallParamSsa(LiftedCallParamSsa),
138    Tailcall(LiftedCall),
139    Intrinsic(LiftedIntrinsic),
140    Syscall(LiftedSyscallCall),
141    IntrinsicSsa(LiftedIntrinsicSsa),
142    MemoryIntrinsicSsa(LiftedMemoryIntrinsicSsa),
143    MemoryIntrinsicOutputSsa(LiftedMemoryIntrinsicOutputSsa),
144    CallSsa(LiftedCallSsa),
145    TailcallSsa(LiftedCallSsa),
146    CallUntypedSsa(LiftedCallUntypedSsa),
147    TailcallUntypedSsa(LiftedCallUntypedSsa),
148    SyscallSsa(LiftedSyscallSsa),
149    SyscallUntypedSsa(LiftedSyscallUntypedSsa),
150    CallUntyped(LiftedCallUntyped),
151    TailcallUntyped(LiftedCallUntyped),
152    SyscallUntyped(LiftedSyscallUntyped),
153    SeparateParamList(LiftedSeparateParamList),
154    SharedParamSlot(LiftedSharedParamSlot),
155    Neg(LiftedUnaryOp),
156    Not(LiftedUnaryOp),
157    Sx(LiftedUnaryOp),
158    Zx(LiftedUnaryOp),
159    LowPart(LiftedUnaryOp),
160    BoolToInt(LiftedUnaryOp),
161    UnimplMem(LiftedUnaryOp),
162    Fsqrt(LiftedUnaryOp),
163    Fneg(LiftedUnaryOp),
164    Fabs(LiftedUnaryOp),
165    FloatToInt(LiftedUnaryOp),
166    IntToFloat(LiftedUnaryOp),
167    FloatConv(LiftedUnaryOp),
168    RoundToInt(LiftedUnaryOp),
169    Floor(LiftedUnaryOp),
170    Ceil(LiftedUnaryOp),
171    Ftrunc(LiftedUnaryOp),
172    Load(LiftedUnaryOp),
173    LoadStruct(LiftedLoadStruct),
174    LoadStructSsa(LiftedLoadStructSsa),
175    LoadSsa(LiftedLoadSsa),
176    Ret(LiftedRet),
177    Var(Var),
178    AddressOf(Var),
179    VarField(Field),
180    AddressOfField(Field),
181    VarSsa(VarSsa),
182    VarAliased(VarSsa),
183    VarSsaField(VarSsaField),
184    VarAliasedField(VarSsaField),
185    Trap(Trap),
186    // A placeholder for instructions that the Rust bindings do not yet support.
187    // Distinct from `Unimpl` as that is a valid instruction.
188    NotYetImplemented,
189}
190
191impl MediumLevelILLiftedInstruction {
192    pub fn name(&self) -> &'static str {
193        use MediumLevelILLiftedInstructionKind::*;
194        match self.kind {
195            Nop => "Nop",
196            Noret => "Noret",
197            Bp => "Bp",
198            Undef => "Undef",
199            Unimpl => "Unimpl",
200            NotYetImplemented => "NotYetImplemented",
201            If(_) => "If",
202            FloatConst(_) => "FloatConst",
203            Const(_) => "Const",
204            ConstPtr(_) => "ConstPtr",
205            Import(_) => "Import",
206            ExternPtr(_) => "ExternPtr",
207            ConstData(_) => "ConstData",
208            Jump(_) => "Jump",
209            RetHint(_) => "RetHint",
210            StoreSsa(_) => "StoreSsa",
211            StoreStructSsa(_) => "StoreStructSsa",
212            StoreStruct(_) => "StoreStruct",
213            Store(_) => "Store",
214            JumpTo(_) => "JumpTo",
215            Goto(_) => "Goto",
216            FreeVarSlot(_) => "FreeVarSlot",
217            SetVarField(_) => "SetVarField",
218            SetVar(_) => "SetVar",
219            FreeVarSlotSsa(_) => "FreeVarSlotSsa",
220            SetVarSsaField(_) => "SetVarSsaField",
221            SetVarAliasedField(_) => "SetVarAliasedField",
222            SetVarAliased(_) => "SetVarAliased",
223            SetVarSsa(_) => "SetVarSsa",
224            VarPhi(_) => "VarPhi",
225            MemPhi(_) => "MemPhi",
226            VarSplit(_) => "VarSplit",
227            SetVarSplit(_) => "SetVarSplit",
228            VarSplitSsa(_) => "VarSplitSsa",
229            SetVarSplitSsa(_) => "SetVarSplitSsa",
230            Add(_) => "Add",
231            Sub(_) => "Sub",
232            And(_) => "And",
233            Or(_) => "Or",
234            Xor(_) => "Xor",
235            Lsl(_) => "Lsl",
236            Lsr(_) => "Lsr",
237            Asr(_) => "Asr",
238            Rol(_) => "Rol",
239            Ror(_) => "Ror",
240            Mul(_) => "Mul",
241            MuluDp(_) => "MuluDp",
242            MulsDp(_) => "MulsDp",
243            Divu(_) => "Divu",
244            DivuDp(_) => "DivuDp",
245            Divs(_) => "Divs",
246            DivsDp(_) => "DivsDp",
247            Modu(_) => "Modu",
248            ModuDp(_) => "ModuDp",
249            Mods(_) => "Mods",
250            ModsDp(_) => "ModsDp",
251            CmpE(_) => "CmpE",
252            CmpNe(_) => "CmpNe",
253            CmpSlt(_) => "CmpSlt",
254            CmpUlt(_) => "CmpUlt",
255            CmpSle(_) => "CmpSle",
256            CmpUle(_) => "CmpUle",
257            CmpSge(_) => "CmpSge",
258            CmpUge(_) => "CmpUge",
259            CmpSgt(_) => "CmpSgt",
260            CmpUgt(_) => "CmpUgt",
261            TestBit(_) => "TestBit",
262            AddOverflow(_) => "AddOverflow",
263            FcmpE(_) => "FcmpE",
264            FcmpNe(_) => "FcmpNe",
265            FcmpLt(_) => "FcmpLt",
266            FcmpLe(_) => "FcmpLe",
267            FcmpGe(_) => "FcmpGe",
268            FcmpGt(_) => "FcmpGt",
269            FcmpO(_) => "FcmpO",
270            FcmpUo(_) => "FcmpUo",
271            Fadd(_) => "Fadd",
272            Fsub(_) => "Fsub",
273            Fmul(_) => "Fmul",
274            Fdiv(_) => "Fdiv",
275            Adc(_) => "Adc",
276            Sbb(_) => "Sbb",
277            Rlc(_) => "Rlc",
278            Rrc(_) => "Rrc",
279            Call(_) => "Call",
280            CallOutput(_) => "CallOutput",
281            CallParam(_) => "CallParam",
282            CallOutputSsa(_) => "CallOutputSsa",
283            CallParamSsa(_) => "CallParamSsa",
284            Tailcall(_) => "Tailcall",
285            Syscall(_) => "Syscall",
286            Intrinsic(_) => "Intrinsic",
287            IntrinsicSsa(_) => "IntrinsicSsa",
288            MemoryIntrinsicSsa(_) => "MemoryIntrinsicSsa",
289            MemoryIntrinsicOutputSsa(_) => "MemoryIntrinsicOutputSsa",
290            CallSsa(_) => "CallSsa",
291            TailcallSsa(_) => "TailcallSsa",
292            CallUntypedSsa(_) => "CallUntypedSsa",
293            TailcallUntypedSsa(_) => "TailcallUntypedSsa",
294            SyscallSsa(_) => "SyscallSsa",
295            SyscallUntypedSsa(_) => "SyscallUntypedSsa",
296            CallUntyped(_) => "CallUntyped",
297            TailcallUntyped(_) => "TailcallUntyped",
298            SyscallUntyped(_) => "SyscallUntyped",
299            SeparateParamList(_) => "SeparateParamList",
300            SharedParamSlot(_) => "SharedParamSlot",
301            Neg(_) => "Neg",
302            Not(_) => "Not",
303            Sx(_) => "Sx",
304            Zx(_) => "Zx",
305            LowPart(_) => "LowPart",
306            BoolToInt(_) => "BoolToInt",
307            UnimplMem(_) => "UnimplMem",
308            Fsqrt(_) => "Fsqrt",
309            Fneg(_) => "Fneg",
310            Fabs(_) => "Fabs",
311            FloatToInt(_) => "FloatToInt",
312            IntToFloat(_) => "IntToFloat",
313            FloatConv(_) => "FloatConv",
314            RoundToInt(_) => "RoundToInt",
315            Floor(_) => "Floor",
316            Ceil(_) => "Ceil",
317            Ftrunc(_) => "Ftrunc",
318            Load(_) => "Load",
319            LoadStruct(_) => "LoadStruct",
320            LoadStructSsa(_) => "LoadStructSsa",
321            LoadSsa(_) => "LoadSsa",
322            Ret(_) => "Ret",
323            Var(_) => "Var",
324            AddressOf(_) => "AddressOf",
325            VarField(_) => "VarField",
326            AddressOfField(_) => "AddressOfField",
327            VarSsa(_) => "VarSsa",
328            VarAliased(_) => "VarAliased",
329            VarSsaField(_) => "VarSsaField",
330            VarAliasedField(_) => "VarAliasedField",
331            Trap(_) => "Trap",
332        }
333    }
334
335    pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> {
336        use MediumLevelILLiftedInstructionKind::*;
337        use MediumLevelILLiftedOperand as Operand;
338        match &self.kind {
339            Nop | Noret | Bp | Undef | Unimpl | NotYetImplemented => vec![],
340            If(op) => vec![
341                ("condition", Operand::Expr(*op.condition.clone())),
342                ("dest_true", Operand::InstructionIndex(op.dest_true)),
343                ("dest_false", Operand::InstructionIndex(op.dest_false)),
344            ],
345            FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
346            Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
347            ExternPtr(op) => vec![
348                ("constant", Operand::Int(op.constant)),
349                ("offset", Operand::Int(op.offset)),
350            ],
351            ConstData(op) => vec![(
352                "constant_data",
353                Operand::ConstantData(op.constant_data.clone()),
354            )],
355            Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
356            StoreSsa(op) => vec![
357                ("dest", Operand::Expr(*op.dest.clone())),
358                ("dest_memory", Operand::Int(op.dest_memory)),
359                ("src_memory", Operand::Int(op.src_memory)),
360                ("src", Operand::Expr(*op.src.clone())),
361            ],
362            StoreStructSsa(op) => vec![
363                ("dest", Operand::Expr(*op.dest.clone())),
364                ("offset", Operand::Int(op.offset)),
365                ("dest_memory", Operand::Int(op.dest_memory)),
366                ("src_memory", Operand::Int(op.src_memory)),
367                ("src", Operand::Expr(*op.src.clone())),
368            ],
369            StoreStruct(op) => vec![
370                ("dest", Operand::Expr(*op.dest.clone())),
371                ("offset", Operand::Int(op.offset)),
372                ("src", Operand::Expr(*op.src.clone())),
373            ],
374            Store(op) => vec![
375                ("dest", Operand::Expr(*op.dest.clone())),
376                ("src", Operand::Expr(*op.src.clone())),
377            ],
378            JumpTo(op) => vec![
379                ("dest", Operand::Expr(*op.dest.clone())),
380                ("targets", Operand::TargetMap(op.targets.clone())),
381            ],
382            Goto(op) => vec![("dest", Operand::InstructionIndex(op.dest))],
383            FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))],
384            SetVarField(op) => vec![
385                ("dest", Operand::Var(op.dest)),
386                ("offset", Operand::Int(op.offset)),
387                ("src", Operand::Expr(*op.src.clone())),
388            ],
389            SetVar(op) => vec![
390                ("dest", Operand::Var(op.dest)),
391                ("src", Operand::Expr(*op.src.clone())),
392            ],
393            FreeVarSlotSsa(op) => vec![
394                ("dest", Operand::VarSsa(op.dest)),
395                ("prev", Operand::VarSsa(op.prev)),
396            ],
397            SetVarSsaField(op) | SetVarAliasedField(op) => vec![
398                ("dest", Operand::VarSsa(op.dest)),
399                ("prev", Operand::VarSsa(op.prev)),
400                ("offset", Operand::Int(op.offset)),
401                ("src", Operand::Expr(*op.src.clone())),
402            ],
403            SetVarAliased(op) => vec![
404                ("dest", Operand::VarSsa(op.dest)),
405                ("prev", Operand::VarSsa(op.prev)),
406                ("src", Operand::Expr(*op.src.clone())),
407            ],
408            SetVarSsa(op) => vec![
409                ("dest", Operand::VarSsa(op.dest)),
410                ("src", Operand::Expr(*op.src.clone())),
411            ],
412            VarPhi(op) => vec![
413                ("dest", Operand::VarSsa(op.dest)),
414                ("src", Operand::VarSsaList(op.src.clone())),
415            ],
416            MemPhi(op) => vec![
417                ("dest_memory", Operand::Int(op.dest_memory)),
418                ("src_memory", Operand::IntList(op.src_memory.clone())),
419            ],
420            VarSplit(op) => vec![
421                ("high", Operand::Var(op.high)),
422                ("low", Operand::Var(op.low)),
423            ],
424            SetVarSplit(op) => vec![
425                ("high", Operand::Var(op.high)),
426                ("low", Operand::Var(op.low)),
427                ("src", Operand::Expr(*op.src.clone())),
428            ],
429            VarSplitSsa(op) => vec![
430                ("high", Operand::VarSsa(op.high)),
431                ("low", Operand::VarSsa(op.low)),
432            ],
433            SetVarSplitSsa(op) => vec![
434                ("high", Operand::VarSsa(op.high)),
435                ("low", Operand::VarSsa(op.low)),
436                ("src", Operand::Expr(*op.src.clone())),
437            ],
438            Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
439            | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
440            | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
441            | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
442            | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
443            | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
444            | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![
445                ("left", Operand::Expr(*op.left.clone())),
446                ("right", Operand::Expr(*op.right.clone())),
447            ],
448            Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![
449                ("left", Operand::Expr(*op.left.clone())),
450                ("right", Operand::Expr(*op.right.clone())),
451                ("carry", Operand::Expr(*op.carry.clone())),
452            ],
453            Call(op) | Tailcall(op) => vec![
454                ("output", Operand::VarList(op.output.clone())),
455                ("dest", Operand::Expr(*op.dest.clone())),
456                ("params", Operand::ExprList(op.params.clone())),
457            ],
458            CallOutput(op) => vec![("output", Operand::VarList(op.output.clone()))],
459            CallParam(op) => vec![("params", Operand::ExprList(op.params.clone()))],
460            CallOutputSsa(op) => vec![
461                ("output", Operand::VarSsaList(op.output.clone())),
462                ("dest_memory", Operand::Int(op.dest_memory)),
463            ],
464            CallParamSsa(op) => vec![
465                ("params", Operand::ExprList(op.params.clone())),
466                ("src_memory", Operand::Int(op.src_memory)),
467            ],
468            Syscall(op) => vec![
469                ("output", Operand::VarList(op.output.clone())),
470                ("params", Operand::ExprList(op.params.clone())),
471            ],
472            Intrinsic(op) => vec![
473                ("output", Operand::VarList(op.output.clone())),
474                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
475                ("params", Operand::ExprList(op.params.clone())),
476            ],
477            IntrinsicSsa(op) => vec![
478                ("output", Operand::VarSsaList(op.output.clone())),
479                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
480                ("params", Operand::ExprList(op.params.clone())),
481            ],
482            MemoryIntrinsicSsa(op) => vec![
483                ("output", Operand::Expr(*op.output.clone())),
484                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
485                ("params", Operand::ExprList(op.params.clone())),
486                ("src_memory", Operand::Int(op.src_memory)),
487            ],
488            MemoryIntrinsicOutputSsa(op) => vec![
489                ("dest_memory", Operand::Int(op.dest_memory)),
490                ("output", Operand::VarSsaList(op.output.clone())),
491            ],
492            CallSsa(op) | TailcallSsa(op) => vec![
493                ("output", Operand::VarSsaList(op.output.clone())),
494                ("dest", Operand::Expr(*op.dest.clone())),
495                ("params", Operand::ExprList(op.params.clone())),
496                ("src_memory", Operand::Int(op.src_memory)),
497            ],
498            CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![
499                ("output", Operand::VarSsaList(op.output.clone())),
500                ("dest", Operand::Expr(*op.dest.clone())),
501                ("params", Operand::ExprList(op.params.clone())),
502                ("stack", Operand::Expr(*op.stack.clone())),
503            ],
504            SyscallSsa(op) => vec![
505                ("output", Operand::VarSsaList(op.output.clone())),
506                ("params", Operand::ExprList(op.params.clone())),
507                ("src_memory", Operand::Int(op.src_memory)),
508            ],
509            SyscallUntypedSsa(op) => vec![
510                ("output", Operand::VarSsaList(op.output.clone())),
511                ("params", Operand::ExprList(op.params.clone())),
512                ("stack", Operand::Expr(*op.stack.clone())),
513            ],
514            CallUntyped(op) | TailcallUntyped(op) => vec![
515                ("output", Operand::VarList(op.output.clone())),
516                ("dest", Operand::Expr(*op.dest.clone())),
517                ("params", Operand::ExprList(op.params.clone())),
518                ("stack", Operand::Expr(*op.stack.clone())),
519            ],
520            SyscallUntyped(op) => vec![
521                ("output", Operand::VarList(op.output.clone())),
522                ("params", Operand::ExprList(op.params.clone())),
523                ("stack", Operand::Expr(*op.stack.clone())),
524            ],
525            Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
526            | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
527            | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
528                vec![("src", Operand::Expr(*op.src.clone()))]
529            }
530            LoadStruct(op) => vec![
531                ("src", Operand::Expr(*op.src.clone())),
532                ("offset", Operand::Int(op.offset)),
533            ],
534            LoadStructSsa(op) => vec![
535                ("src", Operand::Expr(*op.src.clone())),
536                ("offset", Operand::Int(op.offset)),
537                ("src_memory", Operand::Int(op.src_memory)),
538            ],
539            LoadSsa(op) => vec![
540                ("src", Operand::Expr(*op.src.clone())),
541                ("src_memory", Operand::Int(op.src_memory)),
542            ],
543            Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
544            SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))],
545            SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))],
546            Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))],
547            VarField(op) | AddressOfField(op) => vec![
548                ("src", Operand::Var(op.src)),
549                ("offset", Operand::Int(op.offset)),
550            ],
551            VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))],
552            VarSsaField(op) | VarAliasedField(op) => vec![
553                ("src", Operand::VarSsa(op.src)),
554                ("offset", Operand::Int(op.offset)),
555            ],
556            Trap(op) => vec![("vector", Operand::Int(op.vector))],
557        }
558    }
559}