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_STRUCT_INIT => Op::StructInit(StructInit {
577                num_fields: op.operands[0] as usize,
578                first_field: op.operands[1] as usize,
579            }),
580            HLIL_STRUCT_INIT_FIELD => Op::StructInitField(StructField {
581                offset: op.operands[0],
582                member_index: get_member_index(op.operands[1]),
583                src: HighLevelExpressionIndex::from(op.operands[2]),
584            }),
585            HLIL_SWITCH => Op::Switch(Switch {
586                condition: HighLevelExpressionIndex::from(op.operands[0]),
587                default: HighLevelExpressionIndex::from(op.operands[1]),
588                num_cases: op.operands[2] as usize,
589                first_case: op.operands[3] as usize,
590            }),
591            HLIL_SYSCALL => Op::Syscall(Syscall {
592                num_params: op.operands[0] as usize,
593                first_param: op.operands[1] as usize,
594            }),
595            HLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa {
596                num_params: op.operands[0] as usize,
597                first_param: op.operands[1] as usize,
598                dest_memory: op.operands[2],
599                src_memory: op.operands[3],
600            }),
601            HLIL_TRAP => Op::Trap(Trap {
602                vector: op.operands[0],
603            }),
604            HLIL_VAR_DECLARE => Op::VarDeclare(Var {
605                var: get_var(op.operands[0]),
606            }),
607            HLIL_VAR => Op::Var(Var {
608                var: get_var(op.operands[0]),
609            }),
610            HLIL_VAR_INIT => Op::VarInit(VarInit {
611                dest: get_var(op.operands[0]),
612                src: HighLevelExpressionIndex::from(op.operands[1]),
613            }),
614            HLIL_VAR_INIT_SSA => Op::VarInitSsa(VarInitSsa {
615                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
616                src: HighLevelExpressionIndex::from(op.operands[2]),
617            }),
618            HLIL_VAR_PHI => Op::VarPhi(VarPhi {
619                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
620                num_srcs: op.operands[2] as usize,
621                first_src: op.operands[3] as usize,
622            }),
623            HLIL_VAR_SSA => Op::VarSsa(VarSsa {
624                var: get_var_ssa((op.operands[0], op.operands[1] as usize)),
625            }),
626            HLIL_VAR_SSA_PARTIAL => Op::VarSsaPartial(VarSsaPartial {
627                dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
628                prev: get_var_ssa((op.operands[0], op.operands[2] as usize)),
629            }),
630            HLIL_WHILE => Op::While(While {
631                condition: HighLevelExpressionIndex::from(op.operands[0]),
632                body: HighLevelExpressionIndex::from(op.operands[1]),
633            }),
634            HLIL_DO_WHILE => Op::DoWhile(While {
635                body: HighLevelExpressionIndex::from(op.operands[0]),
636                condition: HighLevelExpressionIndex::from(op.operands[1]),
637            }),
638            HLIL_WHILE_SSA => Op::WhileSsa(WhileSsa {
639                condition_phi: HighLevelExpressionIndex::from(op.operands[0]),
640                condition: HighLevelExpressionIndex::from(op.operands[1]),
641                body: HighLevelExpressionIndex::from(op.operands[2]),
642            }),
643            HLIL_DO_WHILE_SSA => Op::DoWhileSsa(WhileSsa {
644                condition_phi: HighLevelExpressionIndex::from(op.operands[0]),
645                condition: HighLevelExpressionIndex::from(op.operands[1]),
646                body: HighLevelExpressionIndex::from(op.operands[2]),
647            }),
648        };
649        Self {
650            function,
651            address: op.address,
652            instr_index,
653            expr_index,
654            size: op.size,
655            kind,
656        }
657    }
658
659    fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
660        let mut count = 0;
661        let raw_list_ptr = unsafe {
662            BNHighLevelILGetOperandList(
663                self.function.handle,
664                self.expr_index.0,
665                operand_idx,
666                &mut count,
667            )
668        };
669        assert!(!raw_list_ptr.is_null());
670        let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
671        unsafe { BNHighLevelILFreeOperandList(raw_list_ptr) };
672        list
673    }
674
675    fn get_ssa_var_list(&self, operand_idx: usize) -> Vec<SSAVariable> {
676        self.get_operand_list(operand_idx)
677            .chunks(2)
678            .map(|chunk| (Variable::from_identifier(chunk[0]), chunk[1] as usize))
679            .map(|(var, version)| SSAVariable::new(var, version))
680            .collect()
681    }
682
683    fn get_expr_list(&self, operand_idx: usize) -> Vec<HighLevelILInstruction> {
684        self.get_operand_list(operand_idx)
685            .into_iter()
686            .map(|val| HighLevelExpressionIndex(val as usize))
687            .filter_map(|idx| self.function.instruction_from_expr_index(idx))
688            .collect()
689    }
690
691    pub fn lift(&self) -> HighLevelILLiftedInstruction {
692        use HighLevelILInstructionKind::*;
693        use HighLevelILLiftedInstructionKind as Lifted;
694        let kind = match self.kind {
695            Nop => Lifted::Nop,
696            Break => Lifted::Break,
697            Continue => Lifted::Continue,
698            Noret => Lifted::Noret,
699            Unreachable => Lifted::Unreachable,
700            Bp => Lifted::Bp,
701            Undef => Lifted::Undef,
702            Unimpl => Lifted::Unimpl,
703
704            Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)),
705            Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)),
706            Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)),
707            Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)),
708
709            Add(op) => Lifted::Add(self.lift_binary_op(op)),
710            Sub(op) => Lifted::Sub(self.lift_binary_op(op)),
711            And(op) => Lifted::And(self.lift_binary_op(op)),
712            Or(op) => Lifted::Or(self.lift_binary_op(op)),
713            Xor(op) => Lifted::Xor(self.lift_binary_op(op)),
714            Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)),
715            Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)),
716            Asr(op) => Lifted::Asr(self.lift_binary_op(op)),
717            Rol(op) => Lifted::Rol(self.lift_binary_op(op)),
718            Ror(op) => Lifted::Ror(self.lift_binary_op(op)),
719            Mul(op) => Lifted::Mul(self.lift_binary_op(op)),
720            MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)),
721            MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)),
722            Divu(op) => Lifted::Divu(self.lift_binary_op(op)),
723            DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)),
724            Divs(op) => Lifted::Divs(self.lift_binary_op(op)),
725            DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)),
726            Modu(op) => Lifted::Modu(self.lift_binary_op(op)),
727            ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)),
728            Mods(op) => Lifted::Mods(self.lift_binary_op(op)),
729            ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)),
730            MinSigned(op) => Lifted::MinSigned(self.lift_binary_op(op)),
731            MaxSigned(op) => Lifted::MaxSigned(self.lift_binary_op(op)),
732            MinUnsigned(op) => Lifted::MinUnsigned(self.lift_binary_op(op)),
733            MaxUnsigned(op) => Lifted::MaxUnsigned(self.lift_binary_op(op)),
734            CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)),
735            CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)),
736            CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)),
737            CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)),
738            CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)),
739            CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)),
740            CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)),
741            CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)),
742            CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)),
743            CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)),
744            TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)),
745            AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)),
746            Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)),
747            Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)),
748            Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)),
749            Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)),
750            FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)),
751            FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)),
752            FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)),
753            FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)),
754            FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)),
755            FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)),
756            FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)),
757            FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)),
758
759            ArrayIndex(op) => Lifted::ArrayIndex(LiftedArrayIndex {
760                src: self.lift_operand(op.src),
761                index: self.lift_operand(op.index),
762            }),
763            ArrayIndexSsa(op) => Lifted::ArrayIndexSsa(LiftedArrayIndexSsa {
764                src: self.lift_operand(op.src),
765                src_memory: op.src_memory,
766                index: self.lift_operand(op.index),
767            }),
768            Assign(op) => Lifted::Assign(LiftedAssign {
769                dest: self.lift_operand(op.dest),
770                src: self.lift_operand(op.src),
771            }),
772            AssignUnpack(op) => Lifted::AssignUnpack(LiftedAssignUnpack {
773                dest: self
774                    .get_expr_list(0)
775                    .iter()
776                    .map(|expr| expr.lift())
777                    .collect(),
778                src: self.lift_operand(op.src),
779            }),
780            AssignMemSsa(op) => Lifted::AssignMemSsa(LiftedAssignMemSsa {
781                dest: self.lift_operand(op.dest),
782                dest_memory: op.dest_memory,
783                src: self.lift_operand(op.src),
784                src_memory: op.src_memory,
785            }),
786            AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(LiftedAssignUnpackMemSsa {
787                dest: self
788                    .get_expr_list(0)
789                    .iter()
790                    .map(|expr| expr.lift())
791                    .collect(),
792                dest_memory: op.dest_memory,
793                src: self.lift_operand(op.src),
794                src_memory: op.src_memory,
795            }),
796            Block(_op) => Lifted::Block(LiftedBlock {
797                body: self
798                    .get_expr_list(0)
799                    .iter()
800                    .map(|expr| expr.lift())
801                    .collect(),
802            }),
803
804            Call(op) => Lifted::Call(self.lift_call(op)),
805            Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
806            CallSsa(op) => Lifted::CallSsa(LiftedCallSsa {
807                dest: self.lift_operand(op.dest),
808                params: self
809                    .get_expr_list(1)
810                    .iter()
811                    .map(|expr| expr.lift())
812                    .collect(),
813                dest_memory: op.dest_memory,
814                src_memory: op.src_memory,
815            }),
816
817            Case(op) => Lifted::Case(LiftedCase {
818                values: self
819                    .get_expr_list(0)
820                    .iter()
821                    .map(|expr| expr.lift())
822                    .collect(),
823                body: self.lift_operand(op.body),
824            }),
825            Const(op) => Lifted::Const(op),
826            ConstPtr(op) => Lifted::ConstPtr(op),
827            Import(op) => Lifted::Import(op),
828            ConstData(op) => Lifted::ConstData(LiftedConstData {
829                constant_data: ConstantData::new(
830                    self.function.function(),
831                    RegisterValue {
832                        // TODO: Replace with a From<u32> for RegisterValueType.
833                        // TODO: We might also want to change the type of `op.constant_data_kind`
834                        // TODO: To RegisterValueType and do the conversion when creating instruction.
835                        state: unsafe {
836                            std::mem::transmute::<u32, BNRegisterValueType>(op.constant_data_kind)
837                        },
838                        value: op.constant_data_value,
839                        offset: 0,
840                        size: op.size,
841                    },
842                ),
843            }),
844
845            Deref(op) => Lifted::Deref(self.lift_unary_op(op)),
846            AddressOf(op) => Lifted::AddressOf(self.lift_unary_op(op)),
847            PassByRef(op) => Lifted::PassByRef(self.lift_unary_op(op)),
848            ReturnByRef(op) => Lifted::ReturnByRef(self.lift_unary_op(op)),
849            Neg(op) => Lifted::Neg(self.lift_unary_op(op)),
850            Not(op) => Lifted::Not(self.lift_unary_op(op)),
851            Bswap(op) => Lifted::Bswap(self.lift_unary_op(op)),
852            Popcnt(op) => Lifted::Popcnt(self.lift_unary_op(op)),
853            Clz(op) => Lifted::Clz(self.lift_unary_op(op)),
854            Ctz(op) => Lifted::Ctz(self.lift_unary_op(op)),
855            Rbit(op) => Lifted::Rbit(self.lift_unary_op(op)),
856            Cls(op) => Lifted::Cls(self.lift_unary_op(op)),
857            Abs(op) => Lifted::Abs(self.lift_unary_op(op)),
858            Sx(op) => Lifted::Sx(self.lift_unary_op(op)),
859            Zx(op) => Lifted::Zx(self.lift_unary_op(op)),
860            LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)),
861            BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)),
862            UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)),
863            Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)),
864            Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)),
865            Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)),
866            FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)),
867            IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)),
868            FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)),
869            RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)),
870            Floor(op) => Lifted::Floor(self.lift_unary_op(op)),
871            Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)),
872            Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)),
873
874            DerefFieldSsa(op) => Lifted::DerefFieldSsa(LiftedDerefFieldSsa {
875                src: self.lift_operand(op.src),
876                src_memory: op.src_memory,
877                offset: op.offset,
878                member_index: op.member_index,
879            }),
880            DerefSsa(op) => Lifted::DerefSsa(LiftedDerefSsa {
881                src: self.lift_operand(op.src),
882                src_memory: op.src_memory,
883            }),
884            ExternPtr(op) => Lifted::ExternPtr(op),
885            FloatConst(op) => Lifted::FloatConst(op),
886            For(op) => Lifted::For(LiftedForLoop {
887                init: self.lift_operand(op.init),
888                condition: self.lift_operand(op.condition),
889                update: self.lift_operand(op.update),
890                body: self.lift_operand(op.body),
891            }),
892            Goto(op) => Lifted::Goto(self.lift_label(op)),
893            Label(op) => Lifted::Label(self.lift_label(op)),
894            ForSsa(op) => Lifted::ForSsa(LiftedForLoopSsa {
895                init: self.lift_operand(op.init),
896                condition_phi: self.lift_operand(op.condition_phi),
897                condition: self.lift_operand(op.condition),
898                update: self.lift_operand(op.update),
899                body: self.lift_operand(op.body),
900            }),
901            If(op) => Lifted::If(LiftedIf {
902                condition: self.lift_operand(op.condition),
903                cond_true: self.lift_operand(op.cond_true),
904                cond_false: self.lift_operand(op.cond_false),
905            }),
906            Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic {
907                intrinsic: CoreIntrinsic::new(
908                    self.function.function().arch(),
909                    IntrinsicId(op.intrinsic),
910                )
911                .expect("Invalid intrinsic"),
912                params: self
913                    .get_expr_list(1)
914                    .iter()
915                    .map(|expr| expr.lift())
916                    .collect(),
917            }),
918            IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
919                intrinsic: CoreIntrinsic::new(
920                    self.function.function().arch(),
921                    IntrinsicId(op.intrinsic),
922                )
923                .expect("Invalid intrinsic"),
924                params: self
925                    .get_expr_list(1)
926                    .iter()
927                    .map(|expr| expr.lift())
928                    .collect(),
929                dest_memory: op.dest_memory,
930                src_memory: op.src_memory,
931            }),
932            Jump(op) => Lifted::Jump(LiftedJump {
933                dest: self.lift_operand(op.dest),
934            }),
935            MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
936                dest: op.dest,
937                src: self.get_operand_list(1),
938            }),
939            Ret(_op) => Lifted::Ret(LiftedRet {
940                src: self
941                    .get_expr_list(0)
942                    .iter()
943                    .map(|expr| expr.lift())
944                    .collect(),
945            }),
946            Split(op) => Lifted::Split(LiftedSplit {
947                high: self.lift_operand(op.high),
948                low: self.lift_operand(op.low),
949            }),
950            StructField(op) => Lifted::StructField(self.lift_struct_field(op)),
951            DerefField(op) => Lifted::DerefField(self.lift_struct_field(op)),
952            StructInit(_op) => Lifted::StructInit(LiftedStructInit {
953                fields: self
954                    .get_expr_list(0)
955                    .iter()
956                    .map(|expr| expr.lift())
957                    .collect(),
958            }),
959            StructInitField(op) => Lifted::StructInitField(self.lift_struct_field(op)),
960            Switch(op) => Lifted::Switch(LiftedSwitch {
961                condition: self.lift_operand(op.condition),
962                default: self.lift_operand(op.default),
963                cases: self
964                    .get_expr_list(2)
965                    .iter()
966                    .map(|expr| expr.lift())
967                    .collect(),
968            }),
969            Syscall(_op) => Lifted::Syscall(LiftedSyscall {
970                params: self
971                    .get_expr_list(0)
972                    .iter()
973                    .map(|expr| expr.lift())
974                    .collect(),
975            }),
976            SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa {
977                params: self
978                    .get_expr_list(0)
979                    .iter()
980                    .map(|expr| expr.lift())
981                    .collect(),
982                dest_memory: op.dest_memory,
983                src_memory: op.src_memory,
984            }),
985            Trap(op) => Lifted::Trap(op),
986            VarDeclare(op) => Lifted::VarDeclare(op),
987            Var(op) => Lifted::Var(op),
988            VarInit(op) => Lifted::VarInit(LiftedVarInit {
989                dest: op.dest,
990                src: self.lift_operand(op.src),
991            }),
992            VarInitSsa(op) => Lifted::VarInitSsa(LiftedVarInitSsa {
993                dest: op.dest,
994                src: self.lift_operand(op.src),
995            }),
996            VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
997                dest: op.dest,
998                src: self.get_ssa_var_list(2),
999            }),
1000            VarSsa(op) => Lifted::VarSsa(op),
1001            VarSsaPartial(op) => Lifted::VarSsaPartial(op),
1002
1003            While(op) => Lifted::While(self.lift_while(op)),
1004            DoWhile(op) => Lifted::DoWhile(self.lift_while(op)),
1005
1006            WhileSsa(op) => Lifted::WhileSsa(self.lift_while_ssa(op)),
1007            DoWhileSsa(op) => Lifted::DoWhileSsa(self.lift_while_ssa(op)),
1008        };
1009        HighLevelILLiftedInstruction {
1010            function: self.function.clone(),
1011            address: self.address,
1012            instr_index: self.instr_index,
1013            expr_index: self.expr_index,
1014            size: self.size,
1015            kind,
1016        }
1017    }
1018
1019    /// HLIL text lines
1020    pub fn lines(&self) -> Array<DisassemblyTextLine> {
1021        let mut count = 0;
1022        let lines = unsafe {
1023            BNGetHighLevelILExprText(
1024                self.function.handle,
1025                self.expr_index.0,
1026                self.function.full_ast,
1027                &mut count,
1028                core::ptr::null_mut(),
1029            )
1030        };
1031        unsafe { Array::new(lines, count, ()) }
1032    }
1033
1034    /// Type of expression
1035    pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> {
1036        let result = unsafe { BNGetHighLevelILExprType(self.function.handle, self.expr_index.0) };
1037        (!result.type_.is_null()).then(|| {
1038            Conf::new(
1039                unsafe { Type::ref_from_raw(result.type_) },
1040                result.confidence,
1041            )
1042        })
1043    }
1044
1045    /// Version of active memory contents in SSA form for this instruction
1046    pub fn ssa_memory_version(&self) -> usize {
1047        unsafe {
1048            BNGetHighLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.expr_index.0)
1049        }
1050    }
1051
1052    pub fn ssa_variable_version(&self, variable: Variable) -> SSAVariable {
1053        let version = unsafe {
1054            BNGetHighLevelILSSAVarVersionAtILInstruction(
1055                self.function.handle,
1056                &variable.into(),
1057                self.expr_index.0,
1058            )
1059        };
1060        SSAVariable::new(variable, version)
1061    }
1062
1063    fn lift_operand(
1064        &self,
1065        expr_idx: HighLevelExpressionIndex,
1066    ) -> Box<HighLevelILLiftedInstruction> {
1067        let operand_instr = self.function.instruction_from_expr_index(expr_idx).unwrap();
1068        Box::new(operand_instr.lift())
1069    }
1070
1071    fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp {
1072        LiftedBinaryOp {
1073            left: self.lift_operand(op.left),
1074            right: self.lift_operand(op.right),
1075        }
1076    }
1077
1078    fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry {
1079        LiftedBinaryOpCarry {
1080            left: self.lift_operand(op.left),
1081            right: self.lift_operand(op.right),
1082            carry: self.lift_operand(op.carry),
1083        }
1084    }
1085
1086    fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp {
1087        LiftedUnaryOp {
1088            src: self.lift_operand(op.src),
1089        }
1090    }
1091
1092    fn lift_label(&self, op: Label) -> LiftedLabel {
1093        LiftedLabel {
1094            target: GotoLabel {
1095                function: self.function.function(),
1096                target: op.target,
1097            },
1098        }
1099    }
1100
1101    fn lift_call(&self, op: Call) -> LiftedCall {
1102        LiftedCall {
1103            dest: self.lift_operand(op.dest),
1104            params: self
1105                .get_expr_list(1)
1106                .iter()
1107                .map(|expr| expr.lift())
1108                .collect(),
1109        }
1110    }
1111
1112    fn lift_while(&self, op: While) -> LiftedWhile {
1113        LiftedWhile {
1114            condition: self.lift_operand(op.condition),
1115            body: self.lift_operand(op.body),
1116        }
1117    }
1118
1119    fn lift_while_ssa(&self, op: WhileSsa) -> LiftedWhileSsa {
1120        LiftedWhileSsa {
1121            condition_phi: self.lift_operand(op.condition_phi),
1122            condition: self.lift_operand(op.condition),
1123            body: self.lift_operand(op.body),
1124        }
1125    }
1126
1127    fn lift_struct_field(&self, op: StructField) -> LiftedStructField {
1128        LiftedStructField {
1129            src: self.lift_operand(op.src),
1130            offset: op.offset,
1131            member_index: op.member_index,
1132        }
1133    }
1134}
1135
1136impl CoreArrayProvider for HighLevelILInstruction {
1137    type Raw = usize;
1138    type Context = Ref<HighLevelILFunction>;
1139    type Wrapped<'a> = Self;
1140}
1141
1142unsafe impl CoreArrayProviderInner for HighLevelILInstruction {
1143    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
1144        unsafe { BNFreeILInstructionList(raw) }
1145    }
1146
1147    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
1148        context
1149            .instruction_from_expr_index(HighLevelExpressionIndex(*raw))
1150            .unwrap()
1151    }
1152}
1153
1154impl Debug for HighLevelILInstruction {
1155    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
1156        // TODO: Actual debug impl please!
1157        write!(
1158            f,
1159            "<{} at 0x{:08}>",
1160            core::any::type_name::<Self>(),
1161            self.address,
1162        )
1163    }
1164}
1165
1166#[derive(Debug, Copy, Clone)]
1167pub enum HighLevelILInstructionKind {
1168    Nop,
1169    Break,
1170    Continue,
1171    Noret,
1172    Unreachable,
1173    Bp,
1174    Undef,
1175    Unimpl,
1176    Adc(BinaryOpCarry),
1177    Sbb(BinaryOpCarry),
1178    Rlc(BinaryOpCarry),
1179    Rrc(BinaryOpCarry),
1180    Add(BinaryOp),
1181    Sub(BinaryOp),
1182    And(BinaryOp),
1183    Or(BinaryOp),
1184    Xor(BinaryOp),
1185    Lsl(BinaryOp),
1186    Lsr(BinaryOp),
1187    Asr(BinaryOp),
1188    Rol(BinaryOp),
1189    Ror(BinaryOp),
1190    Mul(BinaryOp),
1191    MuluDp(BinaryOp),
1192    MulsDp(BinaryOp),
1193    Divu(BinaryOp),
1194    DivuDp(BinaryOp),
1195    Divs(BinaryOp),
1196    DivsDp(BinaryOp),
1197    Modu(BinaryOp),
1198    ModuDp(BinaryOp),
1199    Mods(BinaryOp),
1200    ModsDp(BinaryOp),
1201    MinSigned(BinaryOp),
1202    MaxSigned(BinaryOp),
1203    MinUnsigned(BinaryOp),
1204    MaxUnsigned(BinaryOp),
1205    CmpE(BinaryOp),
1206    CmpNe(BinaryOp),
1207    CmpSlt(BinaryOp),
1208    CmpUlt(BinaryOp),
1209    CmpSle(BinaryOp),
1210    CmpUle(BinaryOp),
1211    CmpSge(BinaryOp),
1212    CmpUge(BinaryOp),
1213    CmpSgt(BinaryOp),
1214    CmpUgt(BinaryOp),
1215    TestBit(BinaryOp),
1216    AddOverflow(BinaryOp),
1217    Fadd(BinaryOp),
1218    Fsub(BinaryOp),
1219    Fmul(BinaryOp),
1220    Fdiv(BinaryOp),
1221    FcmpE(BinaryOp),
1222    FcmpNe(BinaryOp),
1223    FcmpLt(BinaryOp),
1224    FcmpLe(BinaryOp),
1225    FcmpGe(BinaryOp),
1226    FcmpGt(BinaryOp),
1227    FcmpO(BinaryOp),
1228    FcmpUo(BinaryOp),
1229    ArrayIndex(ArrayIndex),
1230    ArrayIndexSsa(ArrayIndexSsa),
1231    Assign(Assign),
1232    AssignMemSsa(AssignMemSsa),
1233    AssignUnpack(AssignUnpack),
1234    AssignUnpackMemSsa(AssignUnpackMemSsa),
1235    Block(Block),
1236    Call(Call),
1237    Tailcall(Call),
1238    CallSsa(CallSsa),
1239    Case(Case),
1240    Const(Const),
1241    ConstPtr(Const),
1242    Import(Const),
1243    ConstData(ConstData),
1244    Deref(UnaryOp),
1245    AddressOf(UnaryOp),
1246    PassByRef(UnaryOp),
1247    ReturnByRef(UnaryOp),
1248    Neg(UnaryOp),
1249    Not(UnaryOp),
1250    Bswap(UnaryOp),
1251    Popcnt(UnaryOp),
1252    Clz(UnaryOp),
1253    Ctz(UnaryOp),
1254    Rbit(UnaryOp),
1255    Cls(UnaryOp),
1256    Abs(UnaryOp),
1257    Sx(UnaryOp),
1258    Zx(UnaryOp),
1259    LowPart(UnaryOp),
1260    BoolToInt(UnaryOp),
1261    UnimplMem(UnaryOp),
1262    Fsqrt(UnaryOp),
1263    Fneg(UnaryOp),
1264    Fabs(UnaryOp),
1265    FloatToInt(UnaryOp),
1266    IntToFloat(UnaryOp),
1267    FloatConv(UnaryOp),
1268    RoundToInt(UnaryOp),
1269    Floor(UnaryOp),
1270    Ceil(UnaryOp),
1271    Ftrunc(UnaryOp),
1272    DerefFieldSsa(DerefFieldSsa),
1273    DerefSsa(DerefSsa),
1274    ExternPtr(ExternPtr),
1275    FloatConst(FloatConst),
1276    For(ForLoop),
1277    ForSsa(ForLoopSsa),
1278    Goto(Label),
1279    Label(Label),
1280    If(If),
1281    Intrinsic(Intrinsic),
1282    IntrinsicSsa(IntrinsicSsa),
1283    Jump(Jump),
1284    MemPhi(MemPhi),
1285    Ret(Ret),
1286    Split(Split),
1287    StructField(StructField),
1288    DerefField(StructField),
1289    StructInit(StructInit),
1290    StructInitField(StructField),
1291    Switch(Switch),
1292    Syscall(Syscall),
1293    SyscallSsa(SyscallSsa),
1294    Trap(Trap),
1295    VarDeclare(Var),
1296    Var(Var),
1297    VarInit(VarInit),
1298    VarInitSsa(VarInitSsa),
1299    VarPhi(VarPhi),
1300    VarSsa(VarSsa),
1301    VarSsaPartial(VarSsaPartial),
1302    While(While),
1303    DoWhile(While),
1304    WhileSsa(WhileSsa),
1305    DoWhileSsa(WhileSsa),
1306}
1307
1308fn get_float(value: u64, size: usize) -> f64 {
1309    match size {
1310        4 => f32::from_bits(value as u32) as f64,
1311        8 => f64::from_bits(value),
1312        // TODO how to handle this value?
1313        size => todo!("float size {}", size),
1314    }
1315}
1316
1317fn get_var(id: u64) -> Variable {
1318    Variable::from_identifier(id)
1319}
1320
1321fn get_member_index(idx: u64) -> Option<usize> {
1322    (idx as i64 > 0).then_some(idx as usize)
1323}
1324
1325fn get_var_ssa(input: (u64, usize)) -> SSAVariable {
1326    SSAVariable::new(get_var(input.0), input.1)
1327}