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_MINS => Op::MinSigned(BinaryOp {
231                left: HighLevelExpressionIndex::from(op.operands[0]),
232                right: HighLevelExpressionIndex::from(op.operands[1]),
233            }),
234            HLIL_MAXS => Op::MaxSigned(BinaryOp {
235                left: HighLevelExpressionIndex::from(op.operands[0]),
236                right: HighLevelExpressionIndex::from(op.operands[1]),
237            }),
238            HLIL_MINU => Op::MinUnsigned(BinaryOp {
239                left: HighLevelExpressionIndex::from(op.operands[0]),
240                right: HighLevelExpressionIndex::from(op.operands[1]),
241            }),
242            HLIL_MAXU => Op::MaxUnsigned(BinaryOp {
243                left: HighLevelExpressionIndex::from(op.operands[0]),
244                right: HighLevelExpressionIndex::from(op.operands[1]),
245            }),
246            HLIL_CMP_E => Op::CmpE(BinaryOp {
247                left: HighLevelExpressionIndex::from(op.operands[0]),
248                right: HighLevelExpressionIndex::from(op.operands[1]),
249            }),
250            HLIL_CMP_NE => Op::CmpNe(BinaryOp {
251                left: HighLevelExpressionIndex::from(op.operands[0]),
252                right: HighLevelExpressionIndex::from(op.operands[1]),
253            }),
254            HLIL_CMP_SLT => Op::CmpSlt(BinaryOp {
255                left: HighLevelExpressionIndex::from(op.operands[0]),
256                right: HighLevelExpressionIndex::from(op.operands[1]),
257            }),
258            HLIL_CMP_ULT => Op::CmpUlt(BinaryOp {
259                left: HighLevelExpressionIndex::from(op.operands[0]),
260                right: HighLevelExpressionIndex::from(op.operands[1]),
261            }),
262            HLIL_CMP_SLE => Op::CmpSle(BinaryOp {
263                left: HighLevelExpressionIndex::from(op.operands[0]),
264                right: HighLevelExpressionIndex::from(op.operands[1]),
265            }),
266            HLIL_CMP_ULE => Op::CmpUle(BinaryOp {
267                left: HighLevelExpressionIndex::from(op.operands[0]),
268                right: HighLevelExpressionIndex::from(op.operands[1]),
269            }),
270            HLIL_CMP_SGE => Op::CmpSge(BinaryOp {
271                left: HighLevelExpressionIndex::from(op.operands[0]),
272                right: HighLevelExpressionIndex::from(op.operands[1]),
273            }),
274            HLIL_CMP_UGE => Op::CmpUge(BinaryOp {
275                left: HighLevelExpressionIndex::from(op.operands[0]),
276                right: HighLevelExpressionIndex::from(op.operands[1]),
277            }),
278            HLIL_CMP_SGT => Op::CmpSgt(BinaryOp {
279                left: HighLevelExpressionIndex::from(op.operands[0]),
280                right: HighLevelExpressionIndex::from(op.operands[1]),
281            }),
282            HLIL_CMP_UGT => Op::CmpUgt(BinaryOp {
283                left: HighLevelExpressionIndex::from(op.operands[0]),
284                right: HighLevelExpressionIndex::from(op.operands[1]),
285            }),
286            HLIL_TEST_BIT => Op::TestBit(BinaryOp {
287                left: HighLevelExpressionIndex::from(op.operands[0]),
288                right: HighLevelExpressionIndex::from(op.operands[1]),
289            }),
290            HLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp {
291                left: HighLevelExpressionIndex::from(op.operands[0]),
292                right: HighLevelExpressionIndex::from(op.operands[1]),
293            }),
294            HLIL_FADD => Op::Fadd(BinaryOp {
295                left: HighLevelExpressionIndex::from(op.operands[0]),
296                right: HighLevelExpressionIndex::from(op.operands[1]),
297            }),
298            HLIL_FSUB => Op::Fsub(BinaryOp {
299                left: HighLevelExpressionIndex::from(op.operands[0]),
300                right: HighLevelExpressionIndex::from(op.operands[1]),
301            }),
302            HLIL_FMUL => Op::Fmul(BinaryOp {
303                left: HighLevelExpressionIndex::from(op.operands[0]),
304                right: HighLevelExpressionIndex::from(op.operands[1]),
305            }),
306            HLIL_FDIV => Op::Fdiv(BinaryOp {
307                left: HighLevelExpressionIndex::from(op.operands[0]),
308                right: HighLevelExpressionIndex::from(op.operands[1]),
309            }),
310            HLIL_FCMP_E => Op::FcmpE(BinaryOp {
311                left: HighLevelExpressionIndex::from(op.operands[0]),
312                right: HighLevelExpressionIndex::from(op.operands[1]),
313            }),
314            HLIL_FCMP_NE => Op::FcmpNe(BinaryOp {
315                left: HighLevelExpressionIndex::from(op.operands[0]),
316                right: HighLevelExpressionIndex::from(op.operands[1]),
317            }),
318            HLIL_FCMP_LT => Op::FcmpLt(BinaryOp {
319                left: HighLevelExpressionIndex::from(op.operands[0]),
320                right: HighLevelExpressionIndex::from(op.operands[1]),
321            }),
322            HLIL_FCMP_LE => Op::FcmpLe(BinaryOp {
323                left: HighLevelExpressionIndex::from(op.operands[0]),
324                right: HighLevelExpressionIndex::from(op.operands[1]),
325            }),
326            HLIL_FCMP_GE => Op::FcmpGe(BinaryOp {
327                left: HighLevelExpressionIndex::from(op.operands[0]),
328                right: HighLevelExpressionIndex::from(op.operands[1]),
329            }),
330            HLIL_FCMP_GT => Op::FcmpGt(BinaryOp {
331                left: HighLevelExpressionIndex::from(op.operands[0]),
332                right: HighLevelExpressionIndex::from(op.operands[1]),
333            }),
334            HLIL_FCMP_O => Op::FcmpO(BinaryOp {
335                left: HighLevelExpressionIndex::from(op.operands[0]),
336                right: HighLevelExpressionIndex::from(op.operands[1]),
337            }),
338            HLIL_FCMP_UO => Op::FcmpUo(BinaryOp {
339                left: HighLevelExpressionIndex::from(op.operands[0]),
340                right: HighLevelExpressionIndex::from(op.operands[1]),
341            }),
342            HLIL_ARRAY_INDEX => Op::ArrayIndex(ArrayIndex {
343                src: HighLevelExpressionIndex::from(op.operands[0]),
344                index: HighLevelExpressionIndex::from(op.operands[1]),
345            }),
346            HLIL_ARRAY_INDEX_SSA => Op::ArrayIndexSsa(ArrayIndexSsa {
347                src: HighLevelExpressionIndex::from(op.operands[0]),
348                src_memory: op.operands[1],
349                index: HighLevelExpressionIndex::from(op.operands[2]),
350            }),
351            HLIL_ASSIGN => Op::Assign(Assign {
352                dest: HighLevelExpressionIndex::from(op.operands[0]),
353                src: HighLevelExpressionIndex::from(op.operands[1]),
354            }),
355            HLIL_ASSIGN_MEM_SSA => Op::AssignMemSsa(AssignMemSsa {
356                dest: HighLevelExpressionIndex::from(op.operands[0]),
357                dest_memory: op.operands[1],
358                src: HighLevelExpressionIndex::from(op.operands[2]),
359                src_memory: op.operands[3],
360            }),
361            HLIL_ASSIGN_UNPACK => Op::AssignUnpack(AssignUnpack {
362                num_dests: op.operands[0] as usize,
363                first_dest: op.operands[1] as usize,
364                src: HighLevelExpressionIndex::from(op.operands[2]),
365            }),
366            HLIL_ASSIGN_UNPACK_MEM_SSA => Op::AssignUnpackMemSsa(AssignUnpackMemSsa {
367                num_dests: op.operands[0] as usize,
368                first_dest: op.operands[1] as usize,
369                dest_memory: op.operands[2],
370                src: HighLevelExpressionIndex::from(op.operands[3]),
371                src_memory: op.operands[4],
372            }),
373            HLIL_BLOCK => Op::Block(Block {
374                num_params: op.operands[0] as usize,
375                first_param: op.operands[1] as usize,
376            }),
377            HLIL_CALL => Op::Call(Call {
378                dest: HighLevelExpressionIndex::from(op.operands[0]),
379                num_params: op.operands[1] as usize,
380                first_param: op.operands[2] as usize,
381            }),
382            HLIL_TAILCALL => Op::Tailcall(Call {
383                dest: HighLevelExpressionIndex::from(op.operands[0]),
384                num_params: op.operands[1] as usize,
385                first_param: op.operands[2] as usize,
386            }),
387            HLIL_CALL_SSA => Op::CallSsa(CallSsa {
388                dest: HighLevelExpressionIndex::from(op.operands[0]),
389                num_params: op.operands[1] as usize,
390                first_param: op.operands[2] as usize,
391                dest_memory: op.operands[3],
392                src_memory: op.operands[4],
393            }),
394            HLIL_CASE => Op::Case(Case {
395                num_values: op.operands[0] as usize,
396                first_value: op.operands[1] as usize,
397                body: HighLevelExpressionIndex::from(op.operands[2]),
398            }),
399            HLIL_CONST => Op::Const(Const {
400                constant: op.operands[0],
401            }),
402            HLIL_CONST_PTR => Op::ConstPtr(Const {
403                constant: op.operands[0],
404            }),
405            HLIL_IMPORT => Op::Import(Const {
406                constant: op.operands[0],
407            }),
408            HLIL_CONST_DATA => Op::ConstData(ConstData {
409                constant_data_kind: op.operands[0] as u32,
410                constant_data_value: op.operands[1] as i64,
411                size: op.size,
412            }),
413            HLIL_DEREF => Op::Deref(UnaryOp {
414                src: HighLevelExpressionIndex::from(op.operands[0]),
415            }),
416            HLIL_ADDRESS_OF => Op::AddressOf(UnaryOp {
417                src: HighLevelExpressionIndex::from(op.operands[0]),
418            }),
419            HLIL_PASS_BY_REF => Op::PassByRef(UnaryOp {
420                src: HighLevelExpressionIndex::from(op.operands[0]),
421            }),
422            HLIL_RETURN_BY_REF => Op::ReturnByRef(UnaryOp {
423                src: HighLevelExpressionIndex::from(op.operands[0]),
424            }),
425            HLIL_NEG => Op::Neg(UnaryOp {
426                src: HighLevelExpressionIndex::from(op.operands[0]),
427            }),
428            HLIL_NOT => Op::Not(UnaryOp {
429                src: HighLevelExpressionIndex::from(op.operands[0]),
430            }),
431            HLIL_BSWAP => Op::Bswap(UnaryOp {
432                src: HighLevelExpressionIndex::from(op.operands[0]),
433            }),
434            HLIL_POPCNT => Op::Popcnt(UnaryOp {
435                src: HighLevelExpressionIndex::from(op.operands[0]),
436            }),
437            HLIL_CLZ => Op::Clz(UnaryOp {
438                src: HighLevelExpressionIndex::from(op.operands[0]),
439            }),
440            HLIL_CTZ => Op::Ctz(UnaryOp {
441                src: HighLevelExpressionIndex::from(op.operands[0]),
442            }),
443            HLIL_RBIT => Op::Rbit(UnaryOp {
444                src: HighLevelExpressionIndex::from(op.operands[0]),
445            }),
446            HLIL_CLS => Op::Cls(UnaryOp {
447                src: HighLevelExpressionIndex::from(op.operands[0]),
448            }),
449            HLIL_ABS => Op::Abs(UnaryOp {
450                src: HighLevelExpressionIndex::from(op.operands[0]),
451            }),
452            HLIL_SX => Op::Sx(UnaryOp {
453                src: HighLevelExpressionIndex::from(op.operands[0]),
454            }),
455            HLIL_ZX => Op::Zx(UnaryOp {
456                src: HighLevelExpressionIndex::from(op.operands[0]),
457            }),
458            HLIL_LOW_PART => Op::LowPart(UnaryOp {
459                src: HighLevelExpressionIndex::from(op.operands[0]),
460            }),
461            HLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp {
462                src: HighLevelExpressionIndex::from(op.operands[0]),
463            }),
464            HLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp {
465                src: HighLevelExpressionIndex::from(op.operands[0]),
466            }),
467            HLIL_FSQRT => Op::Fsqrt(UnaryOp {
468                src: HighLevelExpressionIndex::from(op.operands[0]),
469            }),
470            HLIL_FNEG => Op::Fneg(UnaryOp {
471                src: HighLevelExpressionIndex::from(op.operands[0]),
472            }),
473            HLIL_FABS => Op::Fabs(UnaryOp {
474                src: HighLevelExpressionIndex::from(op.operands[0]),
475            }),
476            HLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp {
477                src: HighLevelExpressionIndex::from(op.operands[0]),
478            }),
479            HLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp {
480                src: HighLevelExpressionIndex::from(op.operands[0]),
481            }),
482            HLIL_FLOAT_CONV => Op::FloatConv(UnaryOp {
483                src: HighLevelExpressionIndex::from(op.operands[0]),
484            }),
485            HLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp {
486                src: HighLevelExpressionIndex::from(op.operands[0]),
487            }),
488            HLIL_FLOOR => Op::Floor(UnaryOp {
489                src: HighLevelExpressionIndex::from(op.operands[0]),
490            }),
491            HLIL_CEIL => Op::Ceil(UnaryOp {
492                src: HighLevelExpressionIndex::from(op.operands[0]),
493            }),
494            HLIL_FTRUNC => Op::Ftrunc(UnaryOp {
495                src: HighLevelExpressionIndex::from(op.operands[0]),
496            }),
497            HLIL_DEREF_FIELD_SSA => Op::DerefFieldSsa(DerefFieldSsa {
498                src: HighLevelExpressionIndex::from(op.operands[0]),
499                src_memory: op.operands[1],
500                offset: op.operands[2],
501                member_index: get_member_index(op.operands[3]),
502            }),
503            HLIL_DEREF_SSA => Op::DerefSsa(DerefSsa {
504                src: HighLevelExpressionIndex::from(op.operands[0]),
505                src_memory: op.operands[1],
506            }),
507            HLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr {
508                constant: op.operands[0],
509                offset: op.operands[1],
510            }),
511            HLIL_FLOAT_CONST => Op::FloatConst(FloatConst {
512                constant: get_float(op.operands[0], op.size),
513            }),
514            HLIL_FOR => Op::For(ForLoop {
515                init: HighLevelExpressionIndex::from(op.operands[0]),
516                condition: HighLevelExpressionIndex::from(op.operands[1]),
517                update: HighLevelExpressionIndex::from(op.operands[2]),
518                body: HighLevelExpressionIndex::from(op.operands[3]),
519            }),
520            HLIL_FOR_SSA => Op::ForSsa(ForLoopSsa {
521                init: HighLevelExpressionIndex::from(op.operands[0]),
522                condition_phi: HighLevelExpressionIndex::from(op.operands[1]),
523                condition: HighLevelExpressionIndex::from(op.operands[2]),
524                update: HighLevelExpressionIndex::from(op.operands[3]),
525                body: HighLevelExpressionIndex::from(op.operands[4]),
526            }),
527            HLIL_GOTO => Op::Goto(Label {
528                target: op.operands[0],
529            }),
530            HLIL_LABEL => Op::Label(Label {
531                target: op.operands[0],
532            }),
533            HLIL_IF => Op::If(If {
534                condition: HighLevelExpressionIndex::from(op.operands[0]),
535                cond_true: HighLevelExpressionIndex::from(op.operands[1]),
536                cond_false: HighLevelExpressionIndex::from(op.operands[2]),
537            }),
538            HLIL_INTRINSIC => Op::Intrinsic(Intrinsic {
539                intrinsic: op.operands[0] as u32,
540                num_params: op.operands[1] as usize,
541                first_param: op.operands[2] as usize,
542            }),
543            HLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa {
544                intrinsic: op.operands[0] as u32,
545                num_params: op.operands[1] as usize,
546                first_param: op.operands[2] as usize,
547                dest_memory: op.operands[3],
548                src_memory: op.operands[4],
549            }),
550            HLIL_JUMP => Op::Jump(Jump {
551                dest: HighLevelExpressionIndex::from(op.operands[0]),
552            }),
553            HLIL_MEM_PHI => Op::MemPhi(MemPhi {
554                dest: op.operands[0],
555                num_srcs: op.operands[1] as usize,
556                first_src: op.operands[2] as usize,
557            }),
558            HLIL_RET => Op::Ret(Ret {
559                num_srcs: op.operands[0] as usize,
560                first_src: op.operands[1] as usize,
561            }),
562            HLIL_SPLIT => Op::Split(Split {
563                high: HighLevelExpressionIndex::from(op.operands[0]),
564                low: HighLevelExpressionIndex::from(op.operands[1]),
565            }),
566            HLIL_STRUCT_FIELD => Op::StructField(StructField {
567                src: HighLevelExpressionIndex::from(op.operands[0]),
568                offset: op.operands[1],
569                member_index: get_member_index(op.operands[2]),
570            }),
571            HLIL_DEREF_FIELD => Op::DerefField(StructField {
572                src: HighLevelExpressionIndex::from(op.operands[0]),
573                offset: op.operands[1],
574                member_index: get_member_index(op.operands[2]),
575            }),
576            HLIL_SWITCH => Op::Switch(Switch {
577                condition: HighLevelExpressionIndex::from(op.operands[0]),
578                default: HighLevelExpressionIndex::from(op.operands[1]),
579                num_cases: op.operands[2] as usize,
580                first_case: op.operands[3] as usize,
581            }),
582            HLIL_SYSCALL => Op::Syscall(Syscall {
583                num_params: op.operands[0] as usize,
584                first_param: op.operands[1] as usize,
585            }),
586            HLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa {
587                num_params: op.operands[0] as usize,
588                first_param: op.operands[1] as usize,
589                dest_memory: op.operands[2],
590                src_memory: op.operands[3],
591            }),
592            HLIL_TRAP => Op::Trap(Trap {
593                vector: op.operands[0],
594            }),
595            HLIL_VAR_DECLARE => Op::VarDeclare(Var {
596                var: get_var(op.operands[0]),
597            }),
598            HLIL_VAR => Op::Var(Var {
599                var: get_var(op.operands[0]),
600            }),
601            HLIL_VAR_INIT => Op::VarInit(VarInit {
602                dest: get_var(op.operands[0]),
603                src: HighLevelExpressionIndex::from(op.operands[1]),
604            }),
605            HLIL_VAR_INIT_SSA => Op::VarInitSsa(VarInitSsa {
606                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
607                src: HighLevelExpressionIndex::from(op.operands[2]),
608            }),
609            HLIL_VAR_PHI => Op::VarPhi(VarPhi {
610                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
611                num_srcs: op.operands[2] as usize,
612                first_src: op.operands[3] as usize,
613            }),
614            HLIL_VAR_SSA => Op::VarSsa(VarSsa {
615                var: get_var_ssa((op.operands[0], op.operands[1] as usize)),
616            }),
617            HLIL_VAR_SSA_PARTIAL => Op::VarSsaPartial(VarSsaPartial {
618                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
619                prev: get_var_ssa((op.operands[0], op.operands[2] as usize)),
620            }),
621            HLIL_WHILE => Op::While(While {
622                condition: HighLevelExpressionIndex::from(op.operands[0]),
623                body: HighLevelExpressionIndex::from(op.operands[1]),
624            }),
625            HLIL_DO_WHILE => Op::DoWhile(While {
626                body: HighLevelExpressionIndex::from(op.operands[0]),
627                condition: HighLevelExpressionIndex::from(op.operands[1]),
628            }),
629            HLIL_WHILE_SSA => Op::WhileSsa(WhileSsa {
630                condition_phi: HighLevelExpressionIndex::from(op.operands[0]),
631                condition: HighLevelExpressionIndex::from(op.operands[1]),
632                body: HighLevelExpressionIndex::from(op.operands[2]),
633            }),
634            HLIL_DO_WHILE_SSA => Op::DoWhileSsa(WhileSsa {
635                condition_phi: HighLevelExpressionIndex::from(op.operands[0]),
636                condition: HighLevelExpressionIndex::from(op.operands[1]),
637                body: HighLevelExpressionIndex::from(op.operands[2]),
638            }),
639        };
640        Self {
641            function,
642            address: op.address,
643            instr_index,
644            expr_index,
645            size: op.size,
646            kind,
647        }
648    }
649
650    fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
651        let mut count = 0;
652        let raw_list_ptr = unsafe {
653            BNHighLevelILGetOperandList(
654                self.function.handle,
655                self.expr_index.0,
656                operand_idx,
657                &mut count,
658            )
659        };
660        assert!(!raw_list_ptr.is_null());
661        let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
662        unsafe { BNHighLevelILFreeOperandList(raw_list_ptr) };
663        list
664    }
665
666    fn get_ssa_var_list(&self, operand_idx: usize) -> Vec<SSAVariable> {
667        self.get_operand_list(operand_idx)
668            .chunks(2)
669            .map(|chunk| (Variable::from_identifier(chunk[0]), chunk[1] as usize))
670            .map(|(var, version)| SSAVariable::new(var, version))
671            .collect()
672    }
673
674    fn get_expr_list(&self, operand_idx: usize) -> Vec<HighLevelILInstruction> {
675        self.get_operand_list(operand_idx)
676            .into_iter()
677            .map(|val| HighLevelExpressionIndex(val as usize))
678            .filter_map(|idx| self.function.instruction_from_expr_index(idx))
679            .collect()
680    }
681
682    pub fn lift(&self) -> HighLevelILLiftedInstruction {
683        use HighLevelILInstructionKind::*;
684        use HighLevelILLiftedInstructionKind as Lifted;
685        let kind = match self.kind {
686            Nop => Lifted::Nop,
687            Break => Lifted::Break,
688            Continue => Lifted::Continue,
689            Noret => Lifted::Noret,
690            Unreachable => Lifted::Unreachable,
691            Bp => Lifted::Bp,
692            Undef => Lifted::Undef,
693            Unimpl => Lifted::Unimpl,
694
695            Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)),
696            Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)),
697            Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)),
698            Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)),
699
700            Add(op) => Lifted::Add(self.lift_binary_op(op)),
701            Sub(op) => Lifted::Sub(self.lift_binary_op(op)),
702            And(op) => Lifted::And(self.lift_binary_op(op)),
703            Or(op) => Lifted::Or(self.lift_binary_op(op)),
704            Xor(op) => Lifted::Xor(self.lift_binary_op(op)),
705            Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)),
706            Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)),
707            Asr(op) => Lifted::Asr(self.lift_binary_op(op)),
708            Rol(op) => Lifted::Rol(self.lift_binary_op(op)),
709            Ror(op) => Lifted::Ror(self.lift_binary_op(op)),
710            Mul(op) => Lifted::Mul(self.lift_binary_op(op)),
711            MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)),
712            MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)),
713            Divu(op) => Lifted::Divu(self.lift_binary_op(op)),
714            DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)),
715            Divs(op) => Lifted::Divs(self.lift_binary_op(op)),
716            DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)),
717            Modu(op) => Lifted::Modu(self.lift_binary_op(op)),
718            ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)),
719            Mods(op) => Lifted::Mods(self.lift_binary_op(op)),
720            ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)),
721            MinSigned(op) => Lifted::MinSigned(self.lift_binary_op(op)),
722            MaxSigned(op) => Lifted::MaxSigned(self.lift_binary_op(op)),
723            MinUnsigned(op) => Lifted::MinUnsigned(self.lift_binary_op(op)),
724            MaxUnsigned(op) => Lifted::MaxUnsigned(self.lift_binary_op(op)),
725            CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)),
726            CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)),
727            CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)),
728            CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)),
729            CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)),
730            CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)),
731            CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)),
732            CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)),
733            CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)),
734            CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)),
735            TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)),
736            AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)),
737            Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)),
738            Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)),
739            Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)),
740            Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)),
741            FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)),
742            FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)),
743            FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)),
744            FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)),
745            FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)),
746            FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)),
747            FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)),
748            FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)),
749
750            ArrayIndex(op) => Lifted::ArrayIndex(LiftedArrayIndex {
751                src: self.lift_operand(op.src),
752                index: self.lift_operand(op.index),
753            }),
754            ArrayIndexSsa(op) => Lifted::ArrayIndexSsa(LiftedArrayIndexSsa {
755                src: self.lift_operand(op.src),
756                src_memory: op.src_memory,
757                index: self.lift_operand(op.index),
758            }),
759            Assign(op) => Lifted::Assign(LiftedAssign {
760                dest: self.lift_operand(op.dest),
761                src: self.lift_operand(op.src),
762            }),
763            AssignUnpack(op) => Lifted::AssignUnpack(LiftedAssignUnpack {
764                dest: self
765                    .get_expr_list(0)
766                    .iter()
767                    .map(|expr| expr.lift())
768                    .collect(),
769                src: self.lift_operand(op.src),
770            }),
771            AssignMemSsa(op) => Lifted::AssignMemSsa(LiftedAssignMemSsa {
772                dest: self.lift_operand(op.dest),
773                dest_memory: op.dest_memory,
774                src: self.lift_operand(op.src),
775                src_memory: op.src_memory,
776            }),
777            AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(LiftedAssignUnpackMemSsa {
778                dest: self
779                    .get_expr_list(0)
780                    .iter()
781                    .map(|expr| expr.lift())
782                    .collect(),
783                dest_memory: op.dest_memory,
784                src: self.lift_operand(op.src),
785                src_memory: op.src_memory,
786            }),
787            Block(_op) => Lifted::Block(LiftedBlock {
788                body: self
789                    .get_expr_list(0)
790                    .iter()
791                    .map(|expr| expr.lift())
792                    .collect(),
793            }),
794
795            Call(op) => Lifted::Call(self.lift_call(op)),
796            Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
797            CallSsa(op) => Lifted::CallSsa(LiftedCallSsa {
798                dest: self.lift_operand(op.dest),
799                params: self
800                    .get_expr_list(1)
801                    .iter()
802                    .map(|expr| expr.lift())
803                    .collect(),
804                dest_memory: op.dest_memory,
805                src_memory: op.src_memory,
806            }),
807
808            Case(op) => Lifted::Case(LiftedCase {
809                values: self
810                    .get_expr_list(0)
811                    .iter()
812                    .map(|expr| expr.lift())
813                    .collect(),
814                body: self.lift_operand(op.body),
815            }),
816            Const(op) => Lifted::Const(op),
817            ConstPtr(op) => Lifted::ConstPtr(op),
818            Import(op) => Lifted::Import(op),
819            ConstData(op) => Lifted::ConstData(LiftedConstData {
820                constant_data: ConstantData::new(
821                    self.function.function(),
822                    RegisterValue {
823                        // TODO: Replace with a From<u32> for RegisterValueType.
824                        // TODO: We might also want to change the type of `op.constant_data_kind`
825                        // TODO: To RegisterValueType and do the conversion when creating instruction.
826                        state: unsafe {
827                            std::mem::transmute::<u32, BNRegisterValueType>(op.constant_data_kind)
828                        },
829                        value: op.constant_data_value,
830                        offset: 0,
831                        size: op.size,
832                    },
833                ),
834            }),
835
836            Deref(op) => Lifted::Deref(self.lift_unary_op(op)),
837            AddressOf(op) => Lifted::AddressOf(self.lift_unary_op(op)),
838            PassByRef(op) => Lifted::PassByRef(self.lift_unary_op(op)),
839            ReturnByRef(op) => Lifted::ReturnByRef(self.lift_unary_op(op)),
840            Neg(op) => Lifted::Neg(self.lift_unary_op(op)),
841            Not(op) => Lifted::Not(self.lift_unary_op(op)),
842            Bswap(op) => Lifted::Bswap(self.lift_unary_op(op)),
843            Popcnt(op) => Lifted::Popcnt(self.lift_unary_op(op)),
844            Clz(op) => Lifted::Clz(self.lift_unary_op(op)),
845            Ctz(op) => Lifted::Ctz(self.lift_unary_op(op)),
846            Rbit(op) => Lifted::Rbit(self.lift_unary_op(op)),
847            Cls(op) => Lifted::Cls(self.lift_unary_op(op)),
848            Abs(op) => Lifted::Abs(self.lift_unary_op(op)),
849            Sx(op) => Lifted::Sx(self.lift_unary_op(op)),
850            Zx(op) => Lifted::Zx(self.lift_unary_op(op)),
851            LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)),
852            BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)),
853            UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)),
854            Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)),
855            Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)),
856            Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)),
857            FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)),
858            IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)),
859            FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)),
860            RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)),
861            Floor(op) => Lifted::Floor(self.lift_unary_op(op)),
862            Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)),
863            Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)),
864
865            DerefFieldSsa(op) => Lifted::DerefFieldSsa(LiftedDerefFieldSsa {
866                src: self.lift_operand(op.src),
867                src_memory: op.src_memory,
868                offset: op.offset,
869                member_index: op.member_index,
870            }),
871            DerefSsa(op) => Lifted::DerefSsa(LiftedDerefSsa {
872                src: self.lift_operand(op.src),
873                src_memory: op.src_memory,
874            }),
875            ExternPtr(op) => Lifted::ExternPtr(op),
876            FloatConst(op) => Lifted::FloatConst(op),
877            For(op) => Lifted::For(LiftedForLoop {
878                init: self.lift_operand(op.init),
879                condition: self.lift_operand(op.condition),
880                update: self.lift_operand(op.update),
881                body: self.lift_operand(op.body),
882            }),
883            Goto(op) => Lifted::Goto(self.lift_label(op)),
884            Label(op) => Lifted::Label(self.lift_label(op)),
885            ForSsa(op) => Lifted::ForSsa(LiftedForLoopSsa {
886                init: self.lift_operand(op.init),
887                condition_phi: self.lift_operand(op.condition_phi),
888                condition: self.lift_operand(op.condition),
889                update: self.lift_operand(op.update),
890                body: self.lift_operand(op.body),
891            }),
892            If(op) => Lifted::If(LiftedIf {
893                condition: self.lift_operand(op.condition),
894                cond_true: self.lift_operand(op.cond_true),
895                cond_false: self.lift_operand(op.cond_false),
896            }),
897            Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic {
898                intrinsic: CoreIntrinsic::new(
899                    self.function.function().arch(),
900                    IntrinsicId(op.intrinsic),
901                )
902                .expect("Invalid intrinsic"),
903                params: self
904                    .get_expr_list(1)
905                    .iter()
906                    .map(|expr| expr.lift())
907                    .collect(),
908            }),
909            IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
910                intrinsic: CoreIntrinsic::new(
911                    self.function.function().arch(),
912                    IntrinsicId(op.intrinsic),
913                )
914                .expect("Invalid intrinsic"),
915                params: self
916                    .get_expr_list(1)
917                    .iter()
918                    .map(|expr| expr.lift())
919                    .collect(),
920                dest_memory: op.dest_memory,
921                src_memory: op.src_memory,
922            }),
923            Jump(op) => Lifted::Jump(LiftedJump {
924                dest: self.lift_operand(op.dest),
925            }),
926            MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
927                dest: op.dest,
928                src: self.get_operand_list(1),
929            }),
930            Ret(_op) => Lifted::Ret(LiftedRet {
931                src: self
932                    .get_expr_list(0)
933                    .iter()
934                    .map(|expr| expr.lift())
935                    .collect(),
936            }),
937            Split(op) => Lifted::Split(LiftedSplit {
938                high: self.lift_operand(op.high),
939                low: self.lift_operand(op.low),
940            }),
941            StructField(op) => Lifted::StructField(self.lift_struct_field(op)),
942            DerefField(op) => Lifted::DerefField(self.lift_struct_field(op)),
943            Switch(op) => Lifted::Switch(LiftedSwitch {
944                condition: self.lift_operand(op.condition),
945                default: self.lift_operand(op.default),
946                cases: self
947                    .get_expr_list(2)
948                    .iter()
949                    .map(|expr| expr.lift())
950                    .collect(),
951            }),
952            Syscall(_op) => Lifted::Syscall(LiftedSyscall {
953                params: self
954                    .get_expr_list(0)
955                    .iter()
956                    .map(|expr| expr.lift())
957                    .collect(),
958            }),
959            SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa {
960                params: self
961                    .get_expr_list(0)
962                    .iter()
963                    .map(|expr| expr.lift())
964                    .collect(),
965                dest_memory: op.dest_memory,
966                src_memory: op.src_memory,
967            }),
968            Trap(op) => Lifted::Trap(op),
969            VarDeclare(op) => Lifted::VarDeclare(op),
970            Var(op) => Lifted::Var(op),
971            VarInit(op) => Lifted::VarInit(LiftedVarInit {
972                dest: op.dest,
973                src: self.lift_operand(op.src),
974            }),
975            VarInitSsa(op) => Lifted::VarInitSsa(LiftedVarInitSsa {
976                dest: op.dest,
977                src: self.lift_operand(op.src),
978            }),
979            VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
980                dest: op.dest,
981                src: self.get_ssa_var_list(2),
982            }),
983            VarSsa(op) => Lifted::VarSsa(op),
984            VarSsaPartial(op) => Lifted::VarSsaPartial(op),
985
986            While(op) => Lifted::While(self.lift_while(op)),
987            DoWhile(op) => Lifted::DoWhile(self.lift_while(op)),
988
989            WhileSsa(op) => Lifted::WhileSsa(self.lift_while_ssa(op)),
990            DoWhileSsa(op) => Lifted::DoWhileSsa(self.lift_while_ssa(op)),
991        };
992        HighLevelILLiftedInstruction {
993            function: self.function.clone(),
994            address: self.address,
995            instr_index: self.instr_index,
996            expr_index: self.expr_index,
997            size: self.size,
998            kind,
999        }
1000    }
1001
1002    /// HLIL text lines
1003    pub fn lines(&self) -> Array<DisassemblyTextLine> {
1004        let mut count = 0;
1005        let lines = unsafe {
1006            BNGetHighLevelILExprText(
1007                self.function.handle,
1008                self.expr_index.0,
1009                self.function.full_ast,
1010                &mut count,
1011                core::ptr::null_mut(),
1012            )
1013        };
1014        unsafe { Array::new(lines, count, ()) }
1015    }
1016
1017    /// Type of expression
1018    pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> {
1019        let result = unsafe { BNGetHighLevelILExprType(self.function.handle, self.expr_index.0) };
1020        (!result.type_.is_null()).then(|| {
1021            Conf::new(
1022                unsafe { Type::ref_from_raw(result.type_) },
1023                result.confidence,
1024            )
1025        })
1026    }
1027
1028    /// Version of active memory contents in SSA form for this instruction
1029    pub fn ssa_memory_version(&self) -> usize {
1030        unsafe {
1031            BNGetHighLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.expr_index.0)
1032        }
1033    }
1034
1035    pub fn ssa_variable_version(&self, variable: Variable) -> SSAVariable {
1036        let version = unsafe {
1037            BNGetHighLevelILSSAVarVersionAtILInstruction(
1038                self.function.handle,
1039                &variable.into(),
1040                self.expr_index.0,
1041            )
1042        };
1043        SSAVariable::new(variable, version)
1044    }
1045
1046    fn lift_operand(
1047        &self,
1048        expr_idx: HighLevelExpressionIndex,
1049    ) -> Box<HighLevelILLiftedInstruction> {
1050        let operand_instr = self.function.instruction_from_expr_index(expr_idx).unwrap();
1051        Box::new(operand_instr.lift())
1052    }
1053
1054    fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp {
1055        LiftedBinaryOp {
1056            left: self.lift_operand(op.left),
1057            right: self.lift_operand(op.right),
1058        }
1059    }
1060
1061    fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry {
1062        LiftedBinaryOpCarry {
1063            left: self.lift_operand(op.left),
1064            right: self.lift_operand(op.right),
1065            carry: self.lift_operand(op.carry),
1066        }
1067    }
1068
1069    fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp {
1070        LiftedUnaryOp {
1071            src: self.lift_operand(op.src),
1072        }
1073    }
1074
1075    fn lift_label(&self, op: Label) -> LiftedLabel {
1076        LiftedLabel {
1077            target: GotoLabel {
1078                function: self.function.function(),
1079                target: op.target,
1080            },
1081        }
1082    }
1083
1084    fn lift_call(&self, op: Call) -> LiftedCall {
1085        LiftedCall {
1086            dest: self.lift_operand(op.dest),
1087            params: self
1088                .get_expr_list(1)
1089                .iter()
1090                .map(|expr| expr.lift())
1091                .collect(),
1092        }
1093    }
1094
1095    fn lift_while(&self, op: While) -> LiftedWhile {
1096        LiftedWhile {
1097            condition: self.lift_operand(op.condition),
1098            body: self.lift_operand(op.body),
1099        }
1100    }
1101
1102    fn lift_while_ssa(&self, op: WhileSsa) -> LiftedWhileSsa {
1103        LiftedWhileSsa {
1104            condition_phi: self.lift_operand(op.condition_phi),
1105            condition: self.lift_operand(op.condition),
1106            body: self.lift_operand(op.body),
1107        }
1108    }
1109
1110    fn lift_struct_field(&self, op: StructField) -> LiftedStructField {
1111        LiftedStructField {
1112            src: self.lift_operand(op.src),
1113            offset: op.offset,
1114            member_index: op.member_index,
1115        }
1116    }
1117}
1118
1119impl CoreArrayProvider for HighLevelILInstruction {
1120    type Raw = usize;
1121    type Context = Ref<HighLevelILFunction>;
1122    type Wrapped<'a> = Self;
1123}
1124
1125unsafe impl CoreArrayProviderInner for HighLevelILInstruction {
1126    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
1127        unsafe { BNFreeILInstructionList(raw) }
1128    }
1129
1130    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
1131        context
1132            .instruction_from_expr_index(HighLevelExpressionIndex(*raw))
1133            .unwrap()
1134    }
1135}
1136
1137impl Debug for HighLevelILInstruction {
1138    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
1139        // TODO: Actual debug impl please!
1140        write!(
1141            f,
1142            "<{} at 0x{:08}>",
1143            core::any::type_name::<Self>(),
1144            self.address,
1145        )
1146    }
1147}
1148
1149#[derive(Debug, Copy, Clone)]
1150pub enum HighLevelILInstructionKind {
1151    Nop,
1152    Break,
1153    Continue,
1154    Noret,
1155    Unreachable,
1156    Bp,
1157    Undef,
1158    Unimpl,
1159    Adc(BinaryOpCarry),
1160    Sbb(BinaryOpCarry),
1161    Rlc(BinaryOpCarry),
1162    Rrc(BinaryOpCarry),
1163    Add(BinaryOp),
1164    Sub(BinaryOp),
1165    And(BinaryOp),
1166    Or(BinaryOp),
1167    Xor(BinaryOp),
1168    Lsl(BinaryOp),
1169    Lsr(BinaryOp),
1170    Asr(BinaryOp),
1171    Rol(BinaryOp),
1172    Ror(BinaryOp),
1173    Mul(BinaryOp),
1174    MuluDp(BinaryOp),
1175    MulsDp(BinaryOp),
1176    Divu(BinaryOp),
1177    DivuDp(BinaryOp),
1178    Divs(BinaryOp),
1179    DivsDp(BinaryOp),
1180    Modu(BinaryOp),
1181    ModuDp(BinaryOp),
1182    Mods(BinaryOp),
1183    ModsDp(BinaryOp),
1184    MinSigned(BinaryOp),
1185    MaxSigned(BinaryOp),
1186    MinUnsigned(BinaryOp),
1187    MaxUnsigned(BinaryOp),
1188    CmpE(BinaryOp),
1189    CmpNe(BinaryOp),
1190    CmpSlt(BinaryOp),
1191    CmpUlt(BinaryOp),
1192    CmpSle(BinaryOp),
1193    CmpUle(BinaryOp),
1194    CmpSge(BinaryOp),
1195    CmpUge(BinaryOp),
1196    CmpSgt(BinaryOp),
1197    CmpUgt(BinaryOp),
1198    TestBit(BinaryOp),
1199    AddOverflow(BinaryOp),
1200    Fadd(BinaryOp),
1201    Fsub(BinaryOp),
1202    Fmul(BinaryOp),
1203    Fdiv(BinaryOp),
1204    FcmpE(BinaryOp),
1205    FcmpNe(BinaryOp),
1206    FcmpLt(BinaryOp),
1207    FcmpLe(BinaryOp),
1208    FcmpGe(BinaryOp),
1209    FcmpGt(BinaryOp),
1210    FcmpO(BinaryOp),
1211    FcmpUo(BinaryOp),
1212    ArrayIndex(ArrayIndex),
1213    ArrayIndexSsa(ArrayIndexSsa),
1214    Assign(Assign),
1215    AssignMemSsa(AssignMemSsa),
1216    AssignUnpack(AssignUnpack),
1217    AssignUnpackMemSsa(AssignUnpackMemSsa),
1218    Block(Block),
1219    Call(Call),
1220    Tailcall(Call),
1221    CallSsa(CallSsa),
1222    Case(Case),
1223    Const(Const),
1224    ConstPtr(Const),
1225    Import(Const),
1226    ConstData(ConstData),
1227    Deref(UnaryOp),
1228    AddressOf(UnaryOp),
1229    PassByRef(UnaryOp),
1230    ReturnByRef(UnaryOp),
1231    Neg(UnaryOp),
1232    Not(UnaryOp),
1233    Bswap(UnaryOp),
1234    Popcnt(UnaryOp),
1235    Clz(UnaryOp),
1236    Ctz(UnaryOp),
1237    Rbit(UnaryOp),
1238    Cls(UnaryOp),
1239    Abs(UnaryOp),
1240    Sx(UnaryOp),
1241    Zx(UnaryOp),
1242    LowPart(UnaryOp),
1243    BoolToInt(UnaryOp),
1244    UnimplMem(UnaryOp),
1245    Fsqrt(UnaryOp),
1246    Fneg(UnaryOp),
1247    Fabs(UnaryOp),
1248    FloatToInt(UnaryOp),
1249    IntToFloat(UnaryOp),
1250    FloatConv(UnaryOp),
1251    RoundToInt(UnaryOp),
1252    Floor(UnaryOp),
1253    Ceil(UnaryOp),
1254    Ftrunc(UnaryOp),
1255    DerefFieldSsa(DerefFieldSsa),
1256    DerefSsa(DerefSsa),
1257    ExternPtr(ExternPtr),
1258    FloatConst(FloatConst),
1259    For(ForLoop),
1260    ForSsa(ForLoopSsa),
1261    Goto(Label),
1262    Label(Label),
1263    If(If),
1264    Intrinsic(Intrinsic),
1265    IntrinsicSsa(IntrinsicSsa),
1266    Jump(Jump),
1267    MemPhi(MemPhi),
1268    Ret(Ret),
1269    Split(Split),
1270    StructField(StructField),
1271    DerefField(StructField),
1272    Switch(Switch),
1273    Syscall(Syscall),
1274    SyscallSsa(SyscallSsa),
1275    Trap(Trap),
1276    VarDeclare(Var),
1277    Var(Var),
1278    VarInit(VarInit),
1279    VarInitSsa(VarInitSsa),
1280    VarPhi(VarPhi),
1281    VarSsa(VarSsa),
1282    VarSsaPartial(VarSsaPartial),
1283    While(While),
1284    DoWhile(While),
1285    WhileSsa(WhileSsa),
1286    DoWhileSsa(WhileSsa),
1287}
1288
1289fn get_float(value: u64, size: usize) -> f64 {
1290    match size {
1291        4 => f32::from_bits(value as u32) as f64,
1292        8 => f64::from_bits(value),
1293        // TODO how to handle this value?
1294        size => todo!("float size {}", size),
1295    }
1296}
1297
1298fn get_var(id: u64) -> Variable {
1299    Variable::from_identifier(id)
1300}
1301
1302fn get_member_index(idx: u64) -> Option<usize> {
1303    (idx as i64 > 0).then_some(idx as usize)
1304}
1305
1306fn get_var_ssa(input: (u64, usize)) -> SSAVariable {
1307    SSAVariable::new(get_var(input.0), input.1)
1308}