1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
use std::collections::BTreeMap;

use crate::architecture::CoreIntrinsic;
use crate::rc::Ref;
use crate::types::{ConstantData, SSAVariable, Variable};

use super::operation::*;
use super::MediumLevelILFunction;

#[derive(Clone)]
pub enum MediumLevelILLiftedOperand {
    ConstantData(ConstantData),
    Intrinsic(CoreIntrinsic),
    Expr(MediumLevelILLiftedInstruction),
    ExprList(Vec<MediumLevelILLiftedInstruction>),
    Float(f64),
    Int(u64),
    IntList(Vec<u64>),
    TargetMap(BTreeMap<u64, u64>),
    Var(Variable),
    VarList(Vec<Variable>),
    VarSsa(SSAVariable),
    VarSsaList(Vec<SSAVariable>),
}

#[derive(Clone, Debug, PartialEq)]
pub struct MediumLevelILLiftedInstruction {
    pub function: Ref<MediumLevelILFunction>,
    pub address: u64,
    pub index: usize,
    pub size: usize,
    pub kind: MediumLevelILLiftedInstructionKind,
}

#[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),
    Tailcall(LiftedCall),
    Intrinsic(LiftedIntrinsic),
    Syscall(LiftedSyscallCall),
    IntrinsicSsa(LiftedIntrinsicSsa),
    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),
    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),
    AddressOf(Var),
    VarField(Field),
    AddressOfField(Field),
    VarSsa(VarSsa),
    VarAliased(VarSsa),
    VarSsaField(VarSsaField),
    VarAliasedField(VarSsaField),
    Trap(Trap),
}

impl MediumLevelILLiftedInstruction {
    pub fn name(&self) -> &'static str {
        use MediumLevelILLiftedInstructionKind::*;
        match self.kind {
            Nop => "Nop",
            Noret => "Noret",
            Bp => "Bp",
            Undef => "Undef",
            Unimpl => "Unimpl",
            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",
            Tailcall(_) => "Tailcall",
            Syscall(_) => "Syscall",
            Intrinsic(_) => "Intrinsic",
            IntrinsicSsa(_) => "IntrinsicSsa",
            CallSsa(_) => "CallSsa",
            TailcallSsa(_) => "TailcallSsa",
            CallUntypedSsa(_) => "CallUntypedSsa",
            TailcallUntypedSsa(_) => "TailcallUntypedSsa",
            SyscallSsa(_) => "SyscallSsa",
            SyscallUntypedSsa(_) => "SyscallUntypedSsa",
            CallUntyped(_) => "CallUntyped",
            TailcallUntyped(_) => "TailcallUntyped",
            SyscallUntyped(_) => "SyscallUntyped",
            SeparateParamList(_) => "SeparateParamList",
            SharedParamSlot(_) => "SharedParamSlot",
            Neg(_) => "Neg",
            Not(_) => "Not",
            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",
            VarField(_) => "VarField",
            AddressOfField(_) => "AddressOfField",
            VarSsa(_) => "VarSsa",
            VarAliased(_) => "VarAliased",
            VarSsaField(_) => "VarSsaField",
            VarAliasedField(_) => "VarAliasedField",
            Trap(_) => "Trap",
        }
    }

    pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> {
        use MediumLevelILLiftedInstructionKind::*;
        use MediumLevelILLiftedOperand as Operand;
        match &self.kind {
            Nop | Noret | Bp | Undef | Unimpl => vec![],
            If(op) => vec![
                ("condition", Operand::Expr(*op.condition.clone())),
                ("dest_true", Operand::Int(op.dest_true)),
                ("dest_false", Operand::Int(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::Int(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::VarList(op.output.clone())),
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            Syscall(op) => vec![
                ("output", Operand::VarList(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())),
            ],
            CallSsa(op) | TailcallSsa(op) => vec![
                ("output", Operand::VarSsaList(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::VarSsaList(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::VarSsaList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            SyscallUntypedSsa(op) => vec![
                ("output", Operand::VarSsaList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("stack", Operand::Expr(*op.stack.clone())),
            ],
            CallUntyped(op) | TailcallUntyped(op) => vec![
                ("output", Operand::VarList(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::VarList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("stack", Operand::Expr(*op.stack.clone())),
            ],
            Neg(op) | Not(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))],
            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)),
            ],
            Trap(op) => vec![("vector", Operand::Int(op.vector))],
        }
    }
}