Skip to main content

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