binaryninja/high_level_il/
instruction.rs

1use binaryninjacore_sys::*;
2use std::fmt;
3use std::fmt::{Debug, Display, Formatter};
4
5use super::operation::*;
6use super::{HighLevelILFunction, HighLevelILLiftedInstruction, HighLevelILLiftedInstructionKind};
7use crate::architecture::{CoreIntrinsic, IntrinsicId};
8use crate::confidence::Conf;
9use crate::disassembly::DisassemblyTextLine;
10use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
11use crate::types::Type;
12use crate::variable::{ConstantData, RegisterValue, SSAVariable, Variable};
13
14#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct HighLevelInstructionIndex(pub usize);
16
17impl HighLevelInstructionIndex {
18    pub fn next(&self) -> Self {
19        Self(self.0 + 1)
20    }
21}
22
23impl From<usize> for HighLevelInstructionIndex {
24    fn from(index: usize) -> Self {
25        Self(index)
26    }
27}
28
29impl From<u64> for HighLevelInstructionIndex {
30    fn from(index: u64) -> Self {
31        Self(index as usize)
32    }
33}
34
35impl Display for HighLevelInstructionIndex {
36    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
37        f.write_fmt(format_args!("{}", self.0))
38    }
39}
40
41#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct HighLevelExpressionIndex(pub usize);
43
44impl HighLevelExpressionIndex {
45    pub fn next(&self) -> Self {
46        Self(self.0 + 1)
47    }
48}
49
50impl From<usize> for HighLevelExpressionIndex {
51    fn from(index: usize) -> Self {
52        Self(index)
53    }
54}
55
56impl From<u64> for HighLevelExpressionIndex {
57    fn from(index: u64) -> Self {
58        Self(index as usize)
59    }
60}
61
62impl Display for HighLevelExpressionIndex {
63    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64        f.write_fmt(format_args!("{}", self.0))
65    }
66}
67
68#[derive(Clone)]
69pub struct HighLevelILInstruction {
70    pub function: Ref<HighLevelILFunction>,
71    pub address: u64,
72    pub instr_index: HighLevelInstructionIndex,
73    pub expr_index: HighLevelExpressionIndex,
74    pub size: usize,
75    pub kind: HighLevelILInstructionKind,
76}
77
78impl HighLevelILInstruction {
79    pub(crate) fn from_instr_index(
80        function: Ref<HighLevelILFunction>,
81        instr_index: HighLevelInstructionIndex,
82    ) -> Self {
83        // Get the associated expression index for the top-level instruction.
84        let expr_index_raw =
85            unsafe { BNGetHighLevelILIndexForInstruction(function.handle, instr_index.0) };
86        Self::new(
87            function,
88            instr_index,
89            HighLevelExpressionIndex(expr_index_raw),
90        )
91    }
92
93    pub(crate) fn from_expr_index(
94        function: Ref<HighLevelILFunction>,
95        expr_index: HighLevelExpressionIndex,
96    ) -> Self {
97        // Get the associated top-level instruction index for the expression.
98        let instr_index_raw =
99            unsafe { BNGetHighLevelILInstructionForExpr(function.handle, expr_index.0) };
100        Self::new(
101            function,
102            HighLevelInstructionIndex(instr_index_raw),
103            expr_index,
104        )
105    }
106
107    pub(crate) fn new(
108        function: Ref<HighLevelILFunction>,
109        instr_index: HighLevelInstructionIndex,
110        expr_index: HighLevelExpressionIndex,
111    ) -> Self {
112        let op =
113            unsafe { BNGetHighLevelILByIndex(function.handle, expr_index.0, function.full_ast) };
114        use BNHighLevelILOperation::*;
115        use HighLevelILInstructionKind as Op;
116        let kind = match op.operation {
117            HLIL_NOP => Op::Nop,
118            HLIL_BREAK => Op::Break,
119            HLIL_CONTINUE => Op::Continue,
120            HLIL_NORET => Op::Noret,
121            HLIL_UNREACHABLE => Op::Unreachable,
122            HLIL_BP => Op::Bp,
123            HLIL_UNDEF => Op::Undef,
124            HLIL_FORCE_VER | HLIL_FORCE_VER_SSA | HLIL_ASSERT | HLIL_ASSERT_SSA => Op::Undef,
125            HLIL_UNIMPL => Op::Unimpl,
126            HLIL_ADC => Op::Adc(BinaryOpCarry {
127                left: HighLevelExpressionIndex::from(op.operands[0]),
128                right: HighLevelExpressionIndex::from(op.operands[1]),
129                carry: HighLevelExpressionIndex::from(op.operands[2]),
130            }),
131            HLIL_SBB => Op::Sbb(BinaryOpCarry {
132                left: HighLevelExpressionIndex::from(op.operands[0]),
133                right: HighLevelExpressionIndex::from(op.operands[1]),
134                carry: HighLevelExpressionIndex::from(op.operands[2]),
135            }),
136            HLIL_RLC => Op::Rlc(BinaryOpCarry {
137                left: HighLevelExpressionIndex::from(op.operands[0]),
138                right: HighLevelExpressionIndex::from(op.operands[1]),
139                carry: HighLevelExpressionIndex::from(op.operands[2]),
140            }),
141            HLIL_RRC => Op::Rrc(BinaryOpCarry {
142                left: HighLevelExpressionIndex::from(op.operands[0]),
143                right: HighLevelExpressionIndex::from(op.operands[1]),
144                carry: HighLevelExpressionIndex::from(op.operands[2]),
145            }),
146            HLIL_ADD => Op::Add(BinaryOp {
147                left: HighLevelExpressionIndex::from(op.operands[0]),
148                right: HighLevelExpressionIndex::from(op.operands[1]),
149            }),
150            HLIL_SUB => Op::Sub(BinaryOp {
151                left: HighLevelExpressionIndex::from(op.operands[0]),
152                right: HighLevelExpressionIndex::from(op.operands[1]),
153            }),
154            HLIL_AND => Op::And(BinaryOp {
155                left: HighLevelExpressionIndex::from(op.operands[0]),
156                right: HighLevelExpressionIndex::from(op.operands[1]),
157            }),
158            HLIL_OR => Op::Or(BinaryOp {
159                left: HighLevelExpressionIndex::from(op.operands[0]),
160                right: HighLevelExpressionIndex::from(op.operands[1]),
161            }),
162            HLIL_XOR => Op::Xor(BinaryOp {
163                left: HighLevelExpressionIndex::from(op.operands[0]),
164                right: HighLevelExpressionIndex::from(op.operands[1]),
165            }),
166            HLIL_LSL => Op::Lsl(BinaryOp {
167                left: HighLevelExpressionIndex::from(op.operands[0]),
168                right: HighLevelExpressionIndex::from(op.operands[1]),
169            }),
170            HLIL_LSR => Op::Lsr(BinaryOp {
171                left: HighLevelExpressionIndex::from(op.operands[0]),
172                right: HighLevelExpressionIndex::from(op.operands[1]),
173            }),
174            HLIL_ASR => Op::Asr(BinaryOp {
175                left: HighLevelExpressionIndex::from(op.operands[0]),
176                right: HighLevelExpressionIndex::from(op.operands[1]),
177            }),
178            HLIL_ROL => Op::Rol(BinaryOp {
179                left: HighLevelExpressionIndex::from(op.operands[0]),
180                right: HighLevelExpressionIndex::from(op.operands[1]),
181            }),
182            HLIL_ROR => Op::Ror(BinaryOp {
183                left: HighLevelExpressionIndex::from(op.operands[0]),
184                right: HighLevelExpressionIndex::from(op.operands[1]),
185            }),
186            HLIL_MUL => Op::Mul(BinaryOp {
187                left: HighLevelExpressionIndex::from(op.operands[0]),
188                right: HighLevelExpressionIndex::from(op.operands[1]),
189            }),
190            HLIL_MULU_DP => Op::MuluDp(BinaryOp {
191                left: HighLevelExpressionIndex::from(op.operands[0]),
192                right: HighLevelExpressionIndex::from(op.operands[1]),
193            }),
194            HLIL_MULS_DP => Op::MulsDp(BinaryOp {
195                left: HighLevelExpressionIndex::from(op.operands[0]),
196                right: HighLevelExpressionIndex::from(op.operands[1]),
197            }),
198            HLIL_DIVU => Op::Divu(BinaryOp {
199                left: HighLevelExpressionIndex::from(op.operands[0]),
200                right: HighLevelExpressionIndex::from(op.operands[1]),
201            }),
202            HLIL_DIVU_DP => Op::DivuDp(BinaryOp {
203                left: HighLevelExpressionIndex::from(op.operands[0]),
204                right: HighLevelExpressionIndex::from(op.operands[1]),
205            }),
206            HLIL_DIVS => Op::Divs(BinaryOp {
207                left: HighLevelExpressionIndex::from(op.operands[0]),
208                right: HighLevelExpressionIndex::from(op.operands[1]),
209            }),
210            HLIL_DIVS_DP => Op::DivsDp(BinaryOp {
211                left: HighLevelExpressionIndex::from(op.operands[0]),
212                right: HighLevelExpressionIndex::from(op.operands[1]),
213            }),
214            HLIL_MODU => Op::Modu(BinaryOp {
215                left: HighLevelExpressionIndex::from(op.operands[0]),
216                right: HighLevelExpressionIndex::from(op.operands[1]),
217            }),
218            HLIL_MODU_DP => Op::ModuDp(BinaryOp {
219                left: HighLevelExpressionIndex::from(op.operands[0]),
220                right: HighLevelExpressionIndex::from(op.operands[1]),
221            }),
222            HLIL_MODS => Op::Mods(BinaryOp {
223                left: HighLevelExpressionIndex::from(op.operands[0]),
224                right: HighLevelExpressionIndex::from(op.operands[1]),
225            }),
226            HLIL_MODS_DP => Op::ModsDp(BinaryOp {
227                left: HighLevelExpressionIndex::from(op.operands[0]),
228                right: HighLevelExpressionIndex::from(op.operands[1]),
229            }),
230            HLIL_CMP_E => Op::CmpE(BinaryOp {
231                left: HighLevelExpressionIndex::from(op.operands[0]),
232                right: HighLevelExpressionIndex::from(op.operands[1]),
233            }),
234            HLIL_CMP_NE => Op::CmpNe(BinaryOp {
235                left: HighLevelExpressionIndex::from(op.operands[0]),
236                right: HighLevelExpressionIndex::from(op.operands[1]),
237            }),
238            HLIL_CMP_SLT => Op::CmpSlt(BinaryOp {
239                left: HighLevelExpressionIndex::from(op.operands[0]),
240                right: HighLevelExpressionIndex::from(op.operands[1]),
241            }),
242            HLIL_CMP_ULT => Op::CmpUlt(BinaryOp {
243                left: HighLevelExpressionIndex::from(op.operands[0]),
244                right: HighLevelExpressionIndex::from(op.operands[1]),
245            }),
246            HLIL_CMP_SLE => Op::CmpSle(BinaryOp {
247                left: HighLevelExpressionIndex::from(op.operands[0]),
248                right: HighLevelExpressionIndex::from(op.operands[1]),
249            }),
250            HLIL_CMP_ULE => Op::CmpUle(BinaryOp {
251                left: HighLevelExpressionIndex::from(op.operands[0]),
252                right: HighLevelExpressionIndex::from(op.operands[1]),
253            }),
254            HLIL_CMP_SGE => Op::CmpSge(BinaryOp {
255                left: HighLevelExpressionIndex::from(op.operands[0]),
256                right: HighLevelExpressionIndex::from(op.operands[1]),
257            }),
258            HLIL_CMP_UGE => Op::CmpUge(BinaryOp {
259                left: HighLevelExpressionIndex::from(op.operands[0]),
260                right: HighLevelExpressionIndex::from(op.operands[1]),
261            }),
262            HLIL_CMP_SGT => Op::CmpSgt(BinaryOp {
263                left: HighLevelExpressionIndex::from(op.operands[0]),
264                right: HighLevelExpressionIndex::from(op.operands[1]),
265            }),
266            HLIL_CMP_UGT => Op::CmpUgt(BinaryOp {
267                left: HighLevelExpressionIndex::from(op.operands[0]),
268                right: HighLevelExpressionIndex::from(op.operands[1]),
269            }),
270            HLIL_TEST_BIT => Op::TestBit(BinaryOp {
271                left: HighLevelExpressionIndex::from(op.operands[0]),
272                right: HighLevelExpressionIndex::from(op.operands[1]),
273            }),
274            HLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp {
275                left: HighLevelExpressionIndex::from(op.operands[0]),
276                right: HighLevelExpressionIndex::from(op.operands[1]),
277            }),
278            HLIL_FADD => Op::Fadd(BinaryOp {
279                left: HighLevelExpressionIndex::from(op.operands[0]),
280                right: HighLevelExpressionIndex::from(op.operands[1]),
281            }),
282            HLIL_FSUB => Op::Fsub(BinaryOp {
283                left: HighLevelExpressionIndex::from(op.operands[0]),
284                right: HighLevelExpressionIndex::from(op.operands[1]),
285            }),
286            HLIL_FMUL => Op::Fmul(BinaryOp {
287                left: HighLevelExpressionIndex::from(op.operands[0]),
288                right: HighLevelExpressionIndex::from(op.operands[1]),
289            }),
290            HLIL_FDIV => Op::Fdiv(BinaryOp {
291                left: HighLevelExpressionIndex::from(op.operands[0]),
292                right: HighLevelExpressionIndex::from(op.operands[1]),
293            }),
294            HLIL_FCMP_E => Op::FcmpE(BinaryOp {
295                left: HighLevelExpressionIndex::from(op.operands[0]),
296                right: HighLevelExpressionIndex::from(op.operands[1]),
297            }),
298            HLIL_FCMP_NE => Op::FcmpNe(BinaryOp {
299                left: HighLevelExpressionIndex::from(op.operands[0]),
300                right: HighLevelExpressionIndex::from(op.operands[1]),
301            }),
302            HLIL_FCMP_LT => Op::FcmpLt(BinaryOp {
303                left: HighLevelExpressionIndex::from(op.operands[0]),
304                right: HighLevelExpressionIndex::from(op.operands[1]),
305            }),
306            HLIL_FCMP_LE => Op::FcmpLe(BinaryOp {
307                left: HighLevelExpressionIndex::from(op.operands[0]),
308                right: HighLevelExpressionIndex::from(op.operands[1]),
309            }),
310            HLIL_FCMP_GE => Op::FcmpGe(BinaryOp {
311                left: HighLevelExpressionIndex::from(op.operands[0]),
312                right: HighLevelExpressionIndex::from(op.operands[1]),
313            }),
314            HLIL_FCMP_GT => Op::FcmpGt(BinaryOp {
315                left: HighLevelExpressionIndex::from(op.operands[0]),
316                right: HighLevelExpressionIndex::from(op.operands[1]),
317            }),
318            HLIL_FCMP_O => Op::FcmpO(BinaryOp {
319                left: HighLevelExpressionIndex::from(op.operands[0]),
320                right: HighLevelExpressionIndex::from(op.operands[1]),
321            }),
322            HLIL_FCMP_UO => Op::FcmpUo(BinaryOp {
323                left: HighLevelExpressionIndex::from(op.operands[0]),
324                right: HighLevelExpressionIndex::from(op.operands[1]),
325            }),
326            HLIL_ARRAY_INDEX => Op::ArrayIndex(ArrayIndex {
327                src: HighLevelExpressionIndex::from(op.operands[0]),
328                index: HighLevelExpressionIndex::from(op.operands[1]),
329            }),
330            HLIL_ARRAY_INDEX_SSA => Op::ArrayIndexSsa(ArrayIndexSsa {
331                src: HighLevelExpressionIndex::from(op.operands[0]),
332                src_memory: op.operands[1],
333                index: HighLevelExpressionIndex::from(op.operands[2]),
334            }),
335            HLIL_ASSIGN => Op::Assign(Assign {
336                dest: HighLevelExpressionIndex::from(op.operands[0]),
337                src: HighLevelExpressionIndex::from(op.operands[1]),
338            }),
339            HLIL_ASSIGN_MEM_SSA => Op::AssignMemSsa(AssignMemSsa {
340                dest: HighLevelExpressionIndex::from(op.operands[0]),
341                dest_memory: op.operands[1],
342                src: HighLevelExpressionIndex::from(op.operands[2]),
343                src_memory: op.operands[3],
344            }),
345            HLIL_ASSIGN_UNPACK => Op::AssignUnpack(AssignUnpack {
346                num_dests: op.operands[0] as usize,
347                first_dest: op.operands[1] as usize,
348                src: HighLevelExpressionIndex::from(op.operands[2]),
349            }),
350            HLIL_ASSIGN_UNPACK_MEM_SSA => Op::AssignUnpackMemSsa(AssignUnpackMemSsa {
351                num_dests: op.operands[0] as usize,
352                first_dest: op.operands[1] as usize,
353                dest_memory: op.operands[2],
354                src: HighLevelExpressionIndex::from(op.operands[3]),
355                src_memory: op.operands[4],
356            }),
357            HLIL_BLOCK => Op::Block(Block {
358                num_params: op.operands[0] as usize,
359                first_param: op.operands[1] as usize,
360            }),
361            HLIL_CALL => Op::Call(Call {
362                dest: HighLevelExpressionIndex::from(op.operands[0]),
363                num_params: op.operands[1] as usize,
364                first_param: op.operands[2] as usize,
365            }),
366            HLIL_TAILCALL => Op::Tailcall(Call {
367                dest: HighLevelExpressionIndex::from(op.operands[0]),
368                num_params: op.operands[1] as usize,
369                first_param: op.operands[2] as usize,
370            }),
371            HLIL_CALL_SSA => Op::CallSsa(CallSsa {
372                dest: HighLevelExpressionIndex::from(op.operands[0]),
373                num_params: op.operands[1] as usize,
374                first_param: op.operands[2] as usize,
375                dest_memory: op.operands[3],
376                src_memory: op.operands[4],
377            }),
378            HLIL_CASE => Op::Case(Case {
379                num_values: op.operands[0] as usize,
380                first_value: op.operands[1] as usize,
381                body: HighLevelExpressionIndex::from(op.operands[2]),
382            }),
383            HLIL_CONST => Op::Const(Const {
384                constant: op.operands[0],
385            }),
386            HLIL_CONST_PTR => Op::ConstPtr(Const {
387                constant: op.operands[0],
388            }),
389            HLIL_IMPORT => Op::Import(Const {
390                constant: op.operands[0],
391            }),
392            HLIL_CONST_DATA => Op::ConstData(ConstData {
393                constant_data_kind: op.operands[0] as u32,
394                constant_data_value: op.operands[1] as i64,
395                size: op.size,
396            }),
397            HLIL_DEREF => Op::Deref(UnaryOp {
398                src: HighLevelExpressionIndex::from(op.operands[0]),
399            }),
400            HLIL_ADDRESS_OF => Op::AddressOf(UnaryOp {
401                src: HighLevelExpressionIndex::from(op.operands[0]),
402            }),
403            HLIL_NEG => Op::Neg(UnaryOp {
404                src: HighLevelExpressionIndex::from(op.operands[0]),
405            }),
406            HLIL_NOT => Op::Not(UnaryOp {
407                src: HighLevelExpressionIndex::from(op.operands[0]),
408            }),
409            HLIL_SX => Op::Sx(UnaryOp {
410                src: HighLevelExpressionIndex::from(op.operands[0]),
411            }),
412            HLIL_ZX => Op::Zx(UnaryOp {
413                src: HighLevelExpressionIndex::from(op.operands[0]),
414            }),
415            HLIL_LOW_PART => Op::LowPart(UnaryOp {
416                src: HighLevelExpressionIndex::from(op.operands[0]),
417            }),
418            HLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp {
419                src: HighLevelExpressionIndex::from(op.operands[0]),
420            }),
421            HLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp {
422                src: HighLevelExpressionIndex::from(op.operands[0]),
423            }),
424            HLIL_FSQRT => Op::Fsqrt(UnaryOp {
425                src: HighLevelExpressionIndex::from(op.operands[0]),
426            }),
427            HLIL_FNEG => Op::Fneg(UnaryOp {
428                src: HighLevelExpressionIndex::from(op.operands[0]),
429            }),
430            HLIL_FABS => Op::Fabs(UnaryOp {
431                src: HighLevelExpressionIndex::from(op.operands[0]),
432            }),
433            HLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp {
434                src: HighLevelExpressionIndex::from(op.operands[0]),
435            }),
436            HLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp {
437                src: HighLevelExpressionIndex::from(op.operands[0]),
438            }),
439            HLIL_FLOAT_CONV => Op::FloatConv(UnaryOp {
440                src: HighLevelExpressionIndex::from(op.operands[0]),
441            }),
442            HLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp {
443                src: HighLevelExpressionIndex::from(op.operands[0]),
444            }),
445            HLIL_FLOOR => Op::Floor(UnaryOp {
446                src: HighLevelExpressionIndex::from(op.operands[0]),
447            }),
448            HLIL_CEIL => Op::Ceil(UnaryOp {
449                src: HighLevelExpressionIndex::from(op.operands[0]),
450            }),
451            HLIL_FTRUNC => Op::Ftrunc(UnaryOp {
452                src: HighLevelExpressionIndex::from(op.operands[0]),
453            }),
454            HLIL_DEREF_FIELD_SSA => Op::DerefFieldSsa(DerefFieldSsa {
455                src: HighLevelExpressionIndex::from(op.operands[0]),
456                src_memory: op.operands[1],
457                offset: op.operands[2],
458                member_index: get_member_index(op.operands[3]),
459            }),
460            HLIL_DEREF_SSA => Op::DerefSsa(DerefSsa {
461                src: HighLevelExpressionIndex::from(op.operands[0]),
462                src_memory: op.operands[1],
463            }),
464            HLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr {
465                constant: op.operands[0],
466                offset: op.operands[1],
467            }),
468            HLIL_FLOAT_CONST => Op::FloatConst(FloatConst {
469                constant: get_float(op.operands[0], op.size),
470            }),
471            HLIL_FOR => Op::For(ForLoop {
472                init: HighLevelExpressionIndex::from(op.operands[0]),
473                condition: HighLevelExpressionIndex::from(op.operands[1]),
474                update: HighLevelExpressionIndex::from(op.operands[2]),
475                body: HighLevelExpressionIndex::from(op.operands[3]),
476            }),
477            HLIL_FOR_SSA => Op::ForSsa(ForLoopSsa {
478                init: HighLevelExpressionIndex::from(op.operands[0]),
479                condition_phi: HighLevelExpressionIndex::from(op.operands[1]),
480                condition: HighLevelExpressionIndex::from(op.operands[2]),
481                update: HighLevelExpressionIndex::from(op.operands[3]),
482                body: HighLevelExpressionIndex::from(op.operands[4]),
483            }),
484            HLIL_GOTO => Op::Goto(Label {
485                target: op.operands[0],
486            }),
487            HLIL_LABEL => Op::Label(Label {
488                target: op.operands[0],
489            }),
490            HLIL_IF => Op::If(If {
491                condition: HighLevelExpressionIndex::from(op.operands[0]),
492                cond_true: HighLevelExpressionIndex::from(op.operands[1]),
493                cond_false: HighLevelExpressionIndex::from(op.operands[2]),
494            }),
495            HLIL_INTRINSIC => Op::Intrinsic(Intrinsic {
496                intrinsic: op.operands[0] as u32,
497                num_params: op.operands[1] as usize,
498                first_param: op.operands[2] as usize,
499            }),
500            HLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa {
501                intrinsic: op.operands[0] as u32,
502                num_params: op.operands[1] as usize,
503                first_param: op.operands[2] as usize,
504                dest_memory: op.operands[3],
505                src_memory: op.operands[4],
506            }),
507            HLIL_JUMP => Op::Jump(Jump {
508                dest: HighLevelExpressionIndex::from(op.operands[0]),
509            }),
510            HLIL_MEM_PHI => Op::MemPhi(MemPhi {
511                dest: op.operands[0],
512                num_srcs: op.operands[1] as usize,
513                first_src: op.operands[2] as usize,
514            }),
515            HLIL_RET => Op::Ret(Ret {
516                num_srcs: op.operands[0] as usize,
517                first_src: op.operands[1] as usize,
518            }),
519            HLIL_SPLIT => Op::Split(Split {
520                high: HighLevelExpressionIndex::from(op.operands[0]),
521                low: HighLevelExpressionIndex::from(op.operands[1]),
522            }),
523            HLIL_STRUCT_FIELD => Op::StructField(StructField {
524                src: HighLevelExpressionIndex::from(op.operands[0]),
525                offset: op.operands[1],
526                member_index: get_member_index(op.operands[2]),
527            }),
528            HLIL_DEREF_FIELD => Op::DerefField(StructField {
529                src: HighLevelExpressionIndex::from(op.operands[0]),
530                offset: op.operands[1],
531                member_index: get_member_index(op.operands[2]),
532            }),
533            HLIL_SWITCH => Op::Switch(Switch {
534                condition: HighLevelExpressionIndex::from(op.operands[0]),
535                default: HighLevelExpressionIndex::from(op.operands[1]),
536                num_cases: op.operands[2] as usize,
537                first_case: op.operands[3] as usize,
538            }),
539            HLIL_SYSCALL => Op::Syscall(Syscall {
540                num_params: op.operands[0] as usize,
541                first_param: op.operands[1] as usize,
542            }),
543            HLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa {
544                num_params: op.operands[0] as usize,
545                first_param: op.operands[1] as usize,
546                dest_memory: op.operands[2],
547                src_memory: op.operands[3],
548            }),
549            HLIL_TRAP => Op::Trap(Trap {
550                vector: op.operands[0],
551            }),
552            HLIL_VAR_DECLARE => Op::VarDeclare(Var {
553                var: get_var(op.operands[0]),
554            }),
555            HLIL_VAR => Op::Var(Var {
556                var: get_var(op.operands[0]),
557            }),
558            HLIL_VAR_INIT => Op::VarInit(VarInit {
559                dest: get_var(op.operands[0]),
560                src: HighLevelExpressionIndex::from(op.operands[1]),
561            }),
562            HLIL_VAR_INIT_SSA => Op::VarInitSsa(VarInitSsa {
563                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
564                src: HighLevelExpressionIndex::from(op.operands[2]),
565            }),
566            HLIL_VAR_PHI => Op::VarPhi(VarPhi {
567                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
568                num_srcs: op.operands[2] as usize,
569                first_src: op.operands[3] as usize,
570            }),
571            HLIL_VAR_SSA => Op::VarSsa(VarSsa {
572                var: get_var_ssa((op.operands[0], op.operands[1] as usize)),
573            }),
574            HLIL_WHILE => Op::While(While {
575                condition: HighLevelExpressionIndex::from(op.operands[0]),
576                body: HighLevelExpressionIndex::from(op.operands[1]),
577            }),
578            HLIL_DO_WHILE => Op::DoWhile(While {
579                body: HighLevelExpressionIndex::from(op.operands[0]),
580                condition: HighLevelExpressionIndex::from(op.operands[1]),
581            }),
582            HLIL_WHILE_SSA => Op::WhileSsa(WhileSsa {
583                condition_phi: HighLevelExpressionIndex::from(op.operands[0]),
584                condition: HighLevelExpressionIndex::from(op.operands[1]),
585                body: HighLevelExpressionIndex::from(op.operands[2]),
586            }),
587            HLIL_DO_WHILE_SSA => Op::DoWhileSsa(WhileSsa {
588                condition_phi: HighLevelExpressionIndex::from(op.operands[0]),
589                condition: HighLevelExpressionIndex::from(op.operands[1]),
590                body: HighLevelExpressionIndex::from(op.operands[2]),
591            }),
592        };
593        Self {
594            function,
595            address: op.address,
596            instr_index,
597            expr_index,
598            size: op.size,
599            kind,
600        }
601    }
602
603    fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
604        let mut count = 0;
605        let raw_list_ptr = unsafe {
606            BNHighLevelILGetOperandList(
607                self.function.handle,
608                self.expr_index.0,
609                operand_idx,
610                &mut count,
611            )
612        };
613        assert!(!raw_list_ptr.is_null());
614        let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
615        unsafe { BNHighLevelILFreeOperandList(raw_list_ptr) };
616        list
617    }
618
619    fn get_ssa_var_list(&self, operand_idx: usize) -> Vec<SSAVariable> {
620        self.get_operand_list(operand_idx)
621            .chunks(2)
622            .map(|chunk| (Variable::from_identifier(chunk[0]), chunk[1] as usize))
623            .map(|(var, version)| SSAVariable::new(var, version))
624            .collect()
625    }
626
627    fn get_expr_list(&self, operand_idx: usize) -> Vec<HighLevelILInstruction> {
628        self.get_operand_list(operand_idx)
629            .into_iter()
630            .map(|val| HighLevelExpressionIndex(val as usize))
631            .filter_map(|idx| self.function.instruction_from_expr_index(idx))
632            .collect()
633    }
634
635    pub fn lift(&self) -> HighLevelILLiftedInstruction {
636        use HighLevelILInstructionKind::*;
637        use HighLevelILLiftedInstructionKind as Lifted;
638        let kind = match self.kind {
639            Nop => Lifted::Nop,
640            Break => Lifted::Break,
641            Continue => Lifted::Continue,
642            Noret => Lifted::Noret,
643            Unreachable => Lifted::Unreachable,
644            Bp => Lifted::Bp,
645            Undef => Lifted::Undef,
646            Unimpl => Lifted::Unimpl,
647
648            Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)),
649            Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)),
650            Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)),
651            Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)),
652
653            Add(op) => Lifted::Add(self.lift_binary_op(op)),
654            Sub(op) => Lifted::Sub(self.lift_binary_op(op)),
655            And(op) => Lifted::And(self.lift_binary_op(op)),
656            Or(op) => Lifted::Or(self.lift_binary_op(op)),
657            Xor(op) => Lifted::Xor(self.lift_binary_op(op)),
658            Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)),
659            Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)),
660            Asr(op) => Lifted::Asr(self.lift_binary_op(op)),
661            Rol(op) => Lifted::Rol(self.lift_binary_op(op)),
662            Ror(op) => Lifted::Ror(self.lift_binary_op(op)),
663            Mul(op) => Lifted::Mul(self.lift_binary_op(op)),
664            MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)),
665            MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)),
666            Divu(op) => Lifted::Divu(self.lift_binary_op(op)),
667            DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)),
668            Divs(op) => Lifted::Divs(self.lift_binary_op(op)),
669            DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)),
670            Modu(op) => Lifted::Modu(self.lift_binary_op(op)),
671            ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)),
672            Mods(op) => Lifted::Mods(self.lift_binary_op(op)),
673            ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)),
674            CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)),
675            CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)),
676            CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)),
677            CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)),
678            CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)),
679            CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)),
680            CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)),
681            CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)),
682            CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)),
683            CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)),
684            TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)),
685            AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)),
686            Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)),
687            Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)),
688            Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)),
689            Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)),
690            FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)),
691            FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)),
692            FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)),
693            FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)),
694            FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)),
695            FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)),
696            FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)),
697            FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)),
698
699            ArrayIndex(op) => Lifted::ArrayIndex(LiftedArrayIndex {
700                src: self.lift_operand(op.src),
701                index: self.lift_operand(op.index),
702            }),
703            ArrayIndexSsa(op) => Lifted::ArrayIndexSsa(LiftedArrayIndexSsa {
704                src: self.lift_operand(op.src),
705                src_memory: op.src_memory,
706                index: self.lift_operand(op.index),
707            }),
708            Assign(op) => Lifted::Assign(LiftedAssign {
709                dest: self.lift_operand(op.dest),
710                src: self.lift_operand(op.src),
711            }),
712            AssignUnpack(op) => Lifted::AssignUnpack(LiftedAssignUnpack {
713                dest: self
714                    .get_expr_list(0)
715                    .iter()
716                    .map(|expr| expr.lift())
717                    .collect(),
718                src: self.lift_operand(op.src),
719            }),
720            AssignMemSsa(op) => Lifted::AssignMemSsa(LiftedAssignMemSsa {
721                dest: self.lift_operand(op.dest),
722                dest_memory: op.dest_memory,
723                src: self.lift_operand(op.src),
724                src_memory: op.src_memory,
725            }),
726            AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(LiftedAssignUnpackMemSsa {
727                dest: self
728                    .get_expr_list(0)
729                    .iter()
730                    .map(|expr| expr.lift())
731                    .collect(),
732                dest_memory: op.dest_memory,
733                src: self.lift_operand(op.src),
734                src_memory: op.src_memory,
735            }),
736            Block(_op) => Lifted::Block(LiftedBlock {
737                body: self
738                    .get_expr_list(0)
739                    .iter()
740                    .map(|expr| expr.lift())
741                    .collect(),
742            }),
743
744            Call(op) => Lifted::Call(self.lift_call(op)),
745            Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
746            CallSsa(op) => Lifted::CallSsa(LiftedCallSsa {
747                dest: self.lift_operand(op.dest),
748                params: self
749                    .get_expr_list(1)
750                    .iter()
751                    .map(|expr| expr.lift())
752                    .collect(),
753                dest_memory: op.dest_memory,
754                src_memory: op.src_memory,
755            }),
756
757            Case(op) => Lifted::Case(LiftedCase {
758                values: self
759                    .get_expr_list(0)
760                    .iter()
761                    .map(|expr| expr.lift())
762                    .collect(),
763                body: self.lift_operand(op.body),
764            }),
765            Const(op) => Lifted::Const(op),
766            ConstPtr(op) => Lifted::ConstPtr(op),
767            Import(op) => Lifted::Import(op),
768            ConstData(op) => Lifted::ConstData(LiftedConstData {
769                constant_data: ConstantData::new(
770                    self.function.function(),
771                    RegisterValue {
772                        // TODO: Replace with a From<u32> for RegisterValueType.
773                        // TODO: We might also want to change the type of `op.constant_data_kind`
774                        // TODO: To RegisterValueType and do the conversion when creating instruction.
775                        state: unsafe {
776                            std::mem::transmute::<u32, BNRegisterValueType>(op.constant_data_kind)
777                        },
778                        value: op.constant_data_value,
779                        offset: 0,
780                        size: op.size,
781                    },
782                ),
783            }),
784
785            Deref(op) => Lifted::Deref(self.lift_unary_op(op)),
786            AddressOf(op) => Lifted::AddressOf(self.lift_unary_op(op)),
787            Neg(op) => Lifted::Neg(self.lift_unary_op(op)),
788            Not(op) => Lifted::Not(self.lift_unary_op(op)),
789            Sx(op) => Lifted::Sx(self.lift_unary_op(op)),
790            Zx(op) => Lifted::Zx(self.lift_unary_op(op)),
791            LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)),
792            BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)),
793            UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)),
794            Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)),
795            Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)),
796            Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)),
797            FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)),
798            IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)),
799            FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)),
800            RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)),
801            Floor(op) => Lifted::Floor(self.lift_unary_op(op)),
802            Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)),
803            Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)),
804
805            DerefFieldSsa(op) => Lifted::DerefFieldSsa(LiftedDerefFieldSsa {
806                src: self.lift_operand(op.src),
807                src_memory: op.src_memory,
808                offset: op.offset,
809                member_index: op.member_index,
810            }),
811            DerefSsa(op) => Lifted::DerefSsa(LiftedDerefSsa {
812                src: self.lift_operand(op.src),
813                src_memory: op.src_memory,
814            }),
815            ExternPtr(op) => Lifted::ExternPtr(op),
816            FloatConst(op) => Lifted::FloatConst(op),
817            For(op) => Lifted::For(LiftedForLoop {
818                init: self.lift_operand(op.init),
819                condition: self.lift_operand(op.condition),
820                update: self.lift_operand(op.update),
821                body: self.lift_operand(op.body),
822            }),
823            Goto(op) => Lifted::Goto(self.lift_label(op)),
824            Label(op) => Lifted::Label(self.lift_label(op)),
825            ForSsa(op) => Lifted::ForSsa(LiftedForLoopSsa {
826                init: self.lift_operand(op.init),
827                condition_phi: self.lift_operand(op.condition_phi),
828                condition: self.lift_operand(op.condition),
829                update: self.lift_operand(op.update),
830                body: self.lift_operand(op.body),
831            }),
832            If(op) => Lifted::If(LiftedIf {
833                condition: self.lift_operand(op.condition),
834                cond_true: self.lift_operand(op.cond_true),
835                cond_false: self.lift_operand(op.cond_false),
836            }),
837            Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic {
838                intrinsic: CoreIntrinsic::new(
839                    self.function.function().arch(),
840                    IntrinsicId(op.intrinsic),
841                )
842                .expect("Invalid intrinsic"),
843                params: self
844                    .get_expr_list(1)
845                    .iter()
846                    .map(|expr| expr.lift())
847                    .collect(),
848            }),
849            IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
850                intrinsic: CoreIntrinsic::new(
851                    self.function.function().arch(),
852                    IntrinsicId(op.intrinsic),
853                )
854                .expect("Invalid intrinsic"),
855                params: self
856                    .get_expr_list(1)
857                    .iter()
858                    .map(|expr| expr.lift())
859                    .collect(),
860                dest_memory: op.dest_memory,
861                src_memory: op.src_memory,
862            }),
863            Jump(op) => Lifted::Jump(LiftedJump {
864                dest: self.lift_operand(op.dest),
865            }),
866            MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
867                dest: op.dest,
868                src: self.get_operand_list(1),
869            }),
870            Ret(_op) => Lifted::Ret(LiftedRet {
871                src: self
872                    .get_expr_list(0)
873                    .iter()
874                    .map(|expr| expr.lift())
875                    .collect(),
876            }),
877            Split(op) => Lifted::Split(LiftedSplit {
878                high: self.lift_operand(op.high),
879                low: self.lift_operand(op.low),
880            }),
881            StructField(op) => Lifted::StructField(self.lift_struct_field(op)),
882            DerefField(op) => Lifted::DerefField(self.lift_struct_field(op)),
883            Switch(op) => Lifted::Switch(LiftedSwitch {
884                condition: self.lift_operand(op.condition),
885                default: self.lift_operand(op.default),
886                cases: self
887                    .get_expr_list(2)
888                    .iter()
889                    .map(|expr| expr.lift())
890                    .collect(),
891            }),
892            Syscall(_op) => Lifted::Syscall(LiftedSyscall {
893                params: self
894                    .get_expr_list(0)
895                    .iter()
896                    .map(|expr| expr.lift())
897                    .collect(),
898            }),
899            SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa {
900                params: self
901                    .get_expr_list(0)
902                    .iter()
903                    .map(|expr| expr.lift())
904                    .collect(),
905                dest_memory: op.dest_memory,
906                src_memory: op.src_memory,
907            }),
908            Trap(op) => Lifted::Trap(op),
909            VarDeclare(op) => Lifted::VarDeclare(op),
910            Var(op) => Lifted::Var(op),
911            VarInit(op) => Lifted::VarInit(LiftedVarInit {
912                dest: op.dest,
913                src: self.lift_operand(op.src),
914            }),
915            VarInitSsa(op) => Lifted::VarInitSsa(LiftedVarInitSsa {
916                dest: op.dest,
917                src: self.lift_operand(op.src),
918            }),
919            VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
920                dest: op.dest,
921                src: self.get_ssa_var_list(2),
922            }),
923            VarSsa(op) => Lifted::VarSsa(op),
924
925            While(op) => Lifted::While(self.lift_while(op)),
926            DoWhile(op) => Lifted::DoWhile(self.lift_while(op)),
927
928            WhileSsa(op) => Lifted::WhileSsa(self.lift_while_ssa(op)),
929            DoWhileSsa(op) => Lifted::DoWhileSsa(self.lift_while_ssa(op)),
930        };
931        HighLevelILLiftedInstruction {
932            function: self.function.clone(),
933            address: self.address,
934            instr_index: self.instr_index,
935            expr_index: self.expr_index,
936            size: self.size,
937            kind,
938        }
939    }
940
941    /// HLIL text lines
942    pub fn lines(&self) -> Array<DisassemblyTextLine> {
943        let mut count = 0;
944        let lines = unsafe {
945            BNGetHighLevelILExprText(
946                self.function.handle,
947                self.expr_index.0,
948                self.function.full_ast,
949                &mut count,
950                core::ptr::null_mut(),
951            )
952        };
953        unsafe { Array::new(lines, count, ()) }
954    }
955
956    /// Type of expression
957    pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> {
958        let result = unsafe { BNGetHighLevelILExprType(self.function.handle, self.expr_index.0) };
959        (!result.type_.is_null()).then(|| {
960            Conf::new(
961                unsafe { Type::ref_from_raw(result.type_) },
962                result.confidence,
963            )
964        })
965    }
966
967    /// Version of active memory contents in SSA form for this instruction
968    pub fn ssa_memory_version(&self) -> usize {
969        unsafe {
970            BNGetHighLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.expr_index.0)
971        }
972    }
973
974    pub fn ssa_variable_version(&self, variable: Variable) -> SSAVariable {
975        let version = unsafe {
976            BNGetHighLevelILSSAVarVersionAtILInstruction(
977                self.function.handle,
978                &variable.into(),
979                self.expr_index.0,
980            )
981        };
982        SSAVariable::new(variable, version)
983    }
984
985    fn lift_operand(
986        &self,
987        expr_idx: HighLevelExpressionIndex,
988    ) -> Box<HighLevelILLiftedInstruction> {
989        let operand_instr = self.function.instruction_from_expr_index(expr_idx).unwrap();
990        Box::new(operand_instr.lift())
991    }
992
993    fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp {
994        LiftedBinaryOp {
995            left: self.lift_operand(op.left),
996            right: self.lift_operand(op.right),
997        }
998    }
999
1000    fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry {
1001        LiftedBinaryOpCarry {
1002            left: self.lift_operand(op.left),
1003            right: self.lift_operand(op.right),
1004            carry: self.lift_operand(op.carry),
1005        }
1006    }
1007
1008    fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp {
1009        LiftedUnaryOp {
1010            src: self.lift_operand(op.src),
1011        }
1012    }
1013
1014    fn lift_label(&self, op: Label) -> LiftedLabel {
1015        LiftedLabel {
1016            target: GotoLabel {
1017                function: self.function.function(),
1018                target: op.target,
1019            },
1020        }
1021    }
1022
1023    fn lift_call(&self, op: Call) -> LiftedCall {
1024        LiftedCall {
1025            dest: self.lift_operand(op.dest),
1026            params: self
1027                .get_expr_list(1)
1028                .iter()
1029                .map(|expr| expr.lift())
1030                .collect(),
1031        }
1032    }
1033
1034    fn lift_while(&self, op: While) -> LiftedWhile {
1035        LiftedWhile {
1036            condition: self.lift_operand(op.condition),
1037            body: self.lift_operand(op.body),
1038        }
1039    }
1040
1041    fn lift_while_ssa(&self, op: WhileSsa) -> LiftedWhileSsa {
1042        LiftedWhileSsa {
1043            condition_phi: self.lift_operand(op.condition_phi),
1044            condition: self.lift_operand(op.condition),
1045            body: self.lift_operand(op.body),
1046        }
1047    }
1048
1049    fn lift_struct_field(&self, op: StructField) -> LiftedStructField {
1050        LiftedStructField {
1051            src: self.lift_operand(op.src),
1052            offset: op.offset,
1053            member_index: op.member_index,
1054        }
1055    }
1056}
1057
1058impl CoreArrayProvider for HighLevelILInstruction {
1059    type Raw = usize;
1060    type Context = Ref<HighLevelILFunction>;
1061    type Wrapped<'a> = Self;
1062}
1063
1064unsafe impl CoreArrayProviderInner for HighLevelILInstruction {
1065    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
1066        unsafe { BNFreeILInstructionList(raw) }
1067    }
1068
1069    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
1070        context
1071            .instruction_from_expr_index(HighLevelExpressionIndex(*raw))
1072            .unwrap()
1073    }
1074}
1075
1076impl Debug for HighLevelILInstruction {
1077    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
1078        // TODO: Actual debug impl please!
1079        write!(
1080            f,
1081            "<{} at 0x{:08}>",
1082            core::any::type_name::<Self>(),
1083            self.address,
1084        )
1085    }
1086}
1087
1088#[derive(Debug, Copy, Clone)]
1089pub enum HighLevelILInstructionKind {
1090    Nop,
1091    Break,
1092    Continue,
1093    Noret,
1094    Unreachable,
1095    Bp,
1096    Undef,
1097    Unimpl,
1098    Adc(BinaryOpCarry),
1099    Sbb(BinaryOpCarry),
1100    Rlc(BinaryOpCarry),
1101    Rrc(BinaryOpCarry),
1102    Add(BinaryOp),
1103    Sub(BinaryOp),
1104    And(BinaryOp),
1105    Or(BinaryOp),
1106    Xor(BinaryOp),
1107    Lsl(BinaryOp),
1108    Lsr(BinaryOp),
1109    Asr(BinaryOp),
1110    Rol(BinaryOp),
1111    Ror(BinaryOp),
1112    Mul(BinaryOp),
1113    MuluDp(BinaryOp),
1114    MulsDp(BinaryOp),
1115    Divu(BinaryOp),
1116    DivuDp(BinaryOp),
1117    Divs(BinaryOp),
1118    DivsDp(BinaryOp),
1119    Modu(BinaryOp),
1120    ModuDp(BinaryOp),
1121    Mods(BinaryOp),
1122    ModsDp(BinaryOp),
1123    CmpE(BinaryOp),
1124    CmpNe(BinaryOp),
1125    CmpSlt(BinaryOp),
1126    CmpUlt(BinaryOp),
1127    CmpSle(BinaryOp),
1128    CmpUle(BinaryOp),
1129    CmpSge(BinaryOp),
1130    CmpUge(BinaryOp),
1131    CmpSgt(BinaryOp),
1132    CmpUgt(BinaryOp),
1133    TestBit(BinaryOp),
1134    AddOverflow(BinaryOp),
1135    Fadd(BinaryOp),
1136    Fsub(BinaryOp),
1137    Fmul(BinaryOp),
1138    Fdiv(BinaryOp),
1139    FcmpE(BinaryOp),
1140    FcmpNe(BinaryOp),
1141    FcmpLt(BinaryOp),
1142    FcmpLe(BinaryOp),
1143    FcmpGe(BinaryOp),
1144    FcmpGt(BinaryOp),
1145    FcmpO(BinaryOp),
1146    FcmpUo(BinaryOp),
1147    ArrayIndex(ArrayIndex),
1148    ArrayIndexSsa(ArrayIndexSsa),
1149    Assign(Assign),
1150    AssignMemSsa(AssignMemSsa),
1151    AssignUnpack(AssignUnpack),
1152    AssignUnpackMemSsa(AssignUnpackMemSsa),
1153    Block(Block),
1154    Call(Call),
1155    Tailcall(Call),
1156    CallSsa(CallSsa),
1157    Case(Case),
1158    Const(Const),
1159    ConstPtr(Const),
1160    Import(Const),
1161    ConstData(ConstData),
1162    Deref(UnaryOp),
1163    AddressOf(UnaryOp),
1164    Neg(UnaryOp),
1165    Not(UnaryOp),
1166    Sx(UnaryOp),
1167    Zx(UnaryOp),
1168    LowPart(UnaryOp),
1169    BoolToInt(UnaryOp),
1170    UnimplMem(UnaryOp),
1171    Fsqrt(UnaryOp),
1172    Fneg(UnaryOp),
1173    Fabs(UnaryOp),
1174    FloatToInt(UnaryOp),
1175    IntToFloat(UnaryOp),
1176    FloatConv(UnaryOp),
1177    RoundToInt(UnaryOp),
1178    Floor(UnaryOp),
1179    Ceil(UnaryOp),
1180    Ftrunc(UnaryOp),
1181    DerefFieldSsa(DerefFieldSsa),
1182    DerefSsa(DerefSsa),
1183    ExternPtr(ExternPtr),
1184    FloatConst(FloatConst),
1185    For(ForLoop),
1186    ForSsa(ForLoopSsa),
1187    Goto(Label),
1188    Label(Label),
1189    If(If),
1190    Intrinsic(Intrinsic),
1191    IntrinsicSsa(IntrinsicSsa),
1192    Jump(Jump),
1193    MemPhi(MemPhi),
1194    Ret(Ret),
1195    Split(Split),
1196    StructField(StructField),
1197    DerefField(StructField),
1198    Switch(Switch),
1199    Syscall(Syscall),
1200    SyscallSsa(SyscallSsa),
1201    Trap(Trap),
1202    VarDeclare(Var),
1203    Var(Var),
1204    VarInit(VarInit),
1205    VarInitSsa(VarInitSsa),
1206    VarPhi(VarPhi),
1207    VarSsa(VarSsa),
1208    While(While),
1209    DoWhile(While),
1210    WhileSsa(WhileSsa),
1211    DoWhileSsa(WhileSsa),
1212}
1213
1214fn get_float(value: u64, size: usize) -> f64 {
1215    match size {
1216        4 => f32::from_bits(value as u32) as f64,
1217        8 => f64::from_bits(value),
1218        // TODO how to handle this value?
1219        size => todo!("float size {}", size),
1220    }
1221}
1222
1223fn get_var(id: u64) -> Variable {
1224    Variable::from_identifier(id)
1225}
1226
1227fn get_member_index(idx: u64) -> Option<usize> {
1228    (idx as i64 > 0).then_some(idx as usize)
1229}
1230
1231fn get_var_ssa(input: (u64, usize)) -> SSAVariable {
1232    SSAVariable::new(get_var(input.0), input.1)
1233}