diff options
| author | Michael Krasnitski <michael.krasnitski@gmail.com> | 2024-02-11 15:27:22 -0500 |
|---|---|---|
| committer | Kyle Martin <krm504@nyu.edu> | 2024-03-18 17:46:37 -0400 |
| commit | 9939d850f0b8ccaf1ae048bcb5f788a6c3e606bf (patch) | |
| tree | 91b582cd51820d826efcd5312e234e56617ca7f9 /rust/src/hlil/operation.rs | |
| parent | 970fe84875e2d6eed918f5bdc9ff689ef37b05ce (diff) | |
Refactor HLIL instructions
Similar to MLIL. Also, reintroduce `LiftedJump` and `LiftedLabel` types.
Diffstat (limited to 'rust/src/hlil/operation.rs')
| -rw-r--r-- | rust/src/hlil/operation.rs | 2037 |
1 files changed, 281 insertions, 1756 deletions
diff --git a/rust/src/hlil/operation.rs b/rust/src/hlil/operation.rs index 769861e0..eeb322e3 100644 --- a/rust/src/hlil/operation.rs +++ b/rust/src/hlil/operation.rs @@ -1,201 +1,11 @@ use binaryninjacore_sys::BNFromVariableIdentifier; use binaryninjacore_sys::BNGetGotoLabelName; -use binaryninjacore_sys::BNGetHighLevelILByIndex; -use binaryninjacore_sys::BNHighLevelILInstruction; -use binaryninjacore_sys::BNHighLevelILOperation; use crate::function::Function; use crate::rc::Ref; -use crate::types::{ - ConstantData, ILIntrinsic, RegisterValue, RegisterValueType, SSAVariable, Variable, -}; +use crate::types::{ConstantData, ILIntrinsic, SSAVariable, Variable}; -use super::{HighLevelILFunction, HighLevelILInstruction, HighLevelILLiftedInstruction}; - -pub enum HighLevelILOperand { - ConstantData(ConstantData), - Expr(HighLevelILInstruction), - ExprList(OperandExprList), - Float(f64), - Int(u64), - IntList(OperandList), - Intrinsic(ILIntrinsic), - Label(GotoLabel), - MemberIndex(Option<usize>), - Var(Variable), - VarSsa(SSAVariable), - VarSsaList(OperandSSAVariableList), -} - -// Iterator for the get_list, this is better then a inline iterator because -// this also implement ExactSizeIterator, what a inline iterator does not. -pub struct OperandList { - function: Ref<HighLevelILFunction>, - remaining: usize, - next_node_idx: Option<usize>, - - current_node: core::array::IntoIter<u64, 4>, -} -impl OperandList { - fn new(function: &HighLevelILFunction, idx: usize, number: usize) -> Self { - // alternative to core::array::IntoIter::empty(); - let mut iter = [0; 4].into_iter(); - for _ in 0..4 { - let _ = iter.next(); - } - Self { - function: function.to_owned(), - remaining: number, - next_node_idx: Some(idx), - current_node: iter, - } - } - fn double(self) -> OperandDubleList { - assert_eq!(self.len() % 2, 0); - OperandDubleList(self) - } - fn map_expr(self) -> OperandExprList { - OperandExprList(self) - } - fn map_ssa_var(self) -> OperandSSAVariableList { - OperandSSAVariableList(self.double()) - } -} -impl Iterator for OperandList { - type Item = u64; - - fn next(&mut self) -> Option<Self::Item> { - // if there is an item in this node, return it - if let Some(current_node) = self.current_node.next() { - return Some(current_node); - } - - // no more items to fetch - if self.remaining == 0 { - return None; - } - - // otherwise get the next node - let next_idx = self.next_node_idx?; - let node = get_raw_operation(&self.function, next_idx); - assert_eq!(node.operation, BNHighLevelILOperation::HLIL_UNDEF); - - // each node contains at most 4, the last is reserved to next node idx - let consume = if self.remaining > 4 { - // there are more nodes after this one - self.next_node_idx = Some(node.operands[4] as usize); - self.remaining -= 4; - &node.operands[0..4] - } else { - // last part of the list, there is no next node - self.next_node_idx = None; - let nodes = &node.operands[0..self.remaining]; - self.remaining = 0; - nodes - }; - // the iter need to have a space of 4, but we may have less then that, - // solution is create a dummy elements at the start and discard it - let mut nodes = [0; 4]; - let dummy_values = 4 - consume.len(); - nodes[dummy_values..4].copy_from_slice(consume); - self.current_node = nodes.into_iter(); - for _ in 0..dummy_values { - let _ = self.current_node.next(); - } - - self.current_node.next() - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } -} -impl ExactSizeIterator for OperandList { - fn len(&self) -> usize { - self.remaining + self.current_node.len() - } -} - -// Iterator similar to OperationList, but returns two elements -pub struct OperandDubleList(OperandList); -impl Iterator for OperandDubleList { - type Item = (u64, u64); - - fn next(&mut self) -> Option<Self::Item> { - let first = self.0.next()?; - let second = self.0.next().unwrap(); - Some((first, second)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } -} -impl ExactSizeIterator for OperandDubleList { - fn len(&self) -> usize { - self.0.len() / 2 - } -} - -pub struct OperandExprList(OperandList); -impl Iterator for OperandExprList { - type Item = HighLevelILInstruction; - - fn next(&mut self) -> Option<Self::Item> { - self.0 - .next() - .map(|idx| get_instruction(&self.0.function, idx as usize)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.0.len(), Some(self.0.len())) - } -} -impl ExactSizeIterator for OperandExprList { - fn len(&self) -> usize { - self.0.len() - } -} - -pub struct OperandVariableList(OperandList); -impl Iterator for OperandVariableList { - type Item = Variable; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().map(get_var) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.0.len(), Some(self.0.len())) - } -} -impl ExactSizeIterator for OperandVariableList { - fn len(&self) -> usize { - self.0.len() - } -} - -pub struct OperandSSAVariableList(OperandDubleList); -impl Iterator for OperandSSAVariableList { - type Item = SSAVariable; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().map(|(id, version)| { - let raw = unsafe { BNFromVariableIdentifier(id) }; - let var = unsafe { Variable::from_raw(raw) }; - SSAVariable::new(var, version as usize) - }) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } -} -impl ExactSizeIterator for OperandSSAVariableList { - fn len(&self) -> usize { - self.0.len() - } -} +use super::HighLevelILLiftedInstruction; fn get_float(value: u64, size: usize) -> f64 { match size { @@ -206,22 +16,6 @@ fn get_float(value: u64, size: usize) -> f64 { } } -fn get_instruction(function: &HighLevelILFunction, idx: usize) -> HighLevelILInstruction { - function.instruction_from_idx(idx) -} - -fn get_instruction_list(function: &HighLevelILFunction, list: (usize, usize)) -> OperandExprList { - OperandList::new(function, list.1, list.0).map_expr() -} - -fn get_int_list(function: &HighLevelILFunction, list: (usize, usize)) -> OperandList { - OperandList::new(function, list.1, list.0) -} - -fn get_raw_operation(function: &HighLevelILFunction, idx: usize) -> BNHighLevelILInstruction { - unsafe { BNGetHighLevelILByIndex(function.handle, idx, function.full_ast) } -} - fn get_var(id: u64) -> Variable { unsafe { Variable::from_raw(BNFromVariableIdentifier(id)) } } @@ -236,17 +30,10 @@ fn get_var_ssa(input: (u64, usize)) -> SSAVariable { SSAVariable::new(var, input.1) } -fn get_var_ssa_list( - function: &HighLevelILFunction, - list: (usize, usize), -) -> OperandSSAVariableList { - OperandList::new(function, list.1, list.0).map_ssa_var() -} - #[derive(Clone, Debug, PartialEq, Eq)] pub struct GotoLabel { - function: Ref<Function>, - target: u64, + pub(crate) function: Ref<Function>, + pub(crate) target: u64, } impl GotoLabel { @@ -258,419 +45,157 @@ impl GotoLabel { } // ADC, SBB, RLC, RRC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct BinaryOpCarry { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - left: usize, - right: usize, - carry: usize, + pub left: usize, + pub right: usize, + pub carry: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBinaryOpCarry { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub left: Box<HighLevelILLiftedInstruction>, pub right: Box<HighLevelILLiftedInstruction>, pub carry: Box<HighLevelILLiftedInstruction>, } impl BinaryOpCarry { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - left: usize, - right: usize, - carry: usize, - ) -> Self { - Self { - function, - address, - left, - right, - carry, - } - } - pub fn left(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.left) - } - pub fn right(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.right) - } - pub fn carry(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.carry) - } - pub fn lift(&self) -> LiftedBinaryOpCarry { - LiftedBinaryOpCarry { - function: self.function.to_owned(), - address: self.address, - left: Box::new(self.left().lift()), - right: Box::new(self.right().lift()), - carry: Box::new(self.carry().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("left", Expr(self.left())), - 1usize => ("right", Expr(self.right())), - 2usize => ("carry", Expr(self.carry())), - _ => unreachable!(), - }) + pub(crate) fn new(left: usize, right: usize, carry: usize) -> Self { + Self { left, right, carry } } } + // ADD, SUB, AND, OR, XOR, LSL, LSR, ASR, ROL, ROR, MUL, MULU_DP, MULS_DP, DIVU, DIVU_DP, DIVS, DIVS_DP, MODU, MODU_DP, MODS, MODS_DP, CMP_E, CMP_NE, CMP_SLT, CMP_ULT, CMP_SLE, CMP_ULE, CMP_SGE, CMP_UGE, CMP_SGT, CMP_UGT, TEST_BIT, ADD_OVERFLOW, FADD, FSUB, FMUL, FDIV, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct BinaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - left: usize, - right: usize, + pub left: usize, + pub right: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBinaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub left: Box<HighLevelILLiftedInstruction>, pub right: Box<HighLevelILLiftedInstruction>, } impl BinaryOp { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - left: usize, - right: usize, - ) -> Self { - Self { - function, - address, - left, - right, - } - } - pub fn left(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.left) - } - pub fn right(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.right) - } - pub fn lift(&self) -> LiftedBinaryOp { - LiftedBinaryOp { - function: self.function.to_owned(), - address: self.address, - left: Box::new(self.left().lift()), - right: Box::new(self.right().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("left", Expr(self.left())), - 1usize => ("right", Expr(self.right())), - _ => unreachable!(), - }) + pub(crate) fn new(left: usize, right: usize) -> Self { + Self { left, right } } } + // ARRAY_INDEX -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ArrayIndex { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - index: usize, + pub src: usize, + pub index: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedArrayIndex { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub index: Box<HighLevelILLiftedInstruction>, } impl ArrayIndex { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - index: usize, - ) -> Self { - Self { - function, - address, - src, - index, - } - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn index(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.index) - } - pub fn lift(&self) -> LiftedArrayIndex { - LiftedArrayIndex { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - index: Box::new(self.index().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("index", Expr(self.index())), - _ => unreachable!(), - }) + pub(crate) fn new(src: usize, index: usize) -> Self { + Self { src, index } } } + // ARRAY_INDEX_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ArrayIndexSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, - index: usize, + pub src: usize, + pub src_memory: u64, + pub index: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedArrayIndexSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, pub index: Box<HighLevelILLiftedInstruction>, } impl ArrayIndexSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - index: usize, - ) -> Self { + pub(crate) fn new(src: usize, src_memory: u64, index: usize) -> Self { Self { - function, - address, src, src_memory, index, } } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn index(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.index) - } - pub fn lift(&self) -> LiftedArrayIndexSsa { - LiftedArrayIndexSsa { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - index: Box::new(self.index().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("src_memory", Int(self.src_memory())), - 2usize => ("index", Expr(self.index())), - _ => unreachable!(), - }) - } } + // ASSIGN -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Assign { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - src: usize, + pub dest: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssign { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub src: Box<HighLevelILLiftedInstruction>, } impl Assign { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: usize, - src: usize, - ) -> Self { - Self { - function, - address, - dest, - src, - } - } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedAssign { - LiftedAssign { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) + pub(crate) fn new(dest: usize, src: usize) -> Self { + Self { dest, src } } } + // ASSIGN_MEM_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct AssignMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - dest_memory: u64, - src: usize, - src_memory: u64, + pub dest: usize, + pub dest_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssignMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub dest_memory: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, } impl AssignMemSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: usize, - dest_memory: u64, - src: usize, - src_memory: u64, - ) -> Self { + pub(crate) fn new(dest: usize, dest_memory: u64, src: usize, src_memory: u64) -> Self { Self { - function, - address, dest, dest_memory, src, src_memory, } } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedAssignMemSsa { - LiftedAssignMemSsa { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - dest_memory: self.dest_memory, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("dest_memory", Int(self.dest_memory())), - 2usize => ("src", Expr(self.src())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // ASSIGN_UNPACK -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct AssignUnpack { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: (usize, usize), - src: usize, + pub first_dest: usize, + pub num_dests: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssignUnpack { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Vec<HighLevelILLiftedInstruction>, pub src: Box<HighLevelILLiftedInstruction>, } impl AssignUnpack { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (usize, usize), - src: usize, - ) -> Self { + pub(crate) fn new(num_dests: usize, first_dest: usize, src: usize) -> Self { Self { - function, - address, - dest, + num_dests, + first_dest, src, } } - pub fn dest(&self) -> OperandExprList { - get_instruction_list(&self.function, self.dest) - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedAssignUnpack { - LiftedAssignUnpack { - function: self.function.to_owned(), - address: self.address, - dest: self.dest().map(|x| x.lift()).collect(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", ExprList(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) - } } + // ASSIGN_UNPACK_MEM_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct AssignUnpackMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: (usize, usize), - dest_memory: u64, - src: usize, - src_memory: u64, + pub first_dest: usize, + pub num_dests: usize, + pub dest_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssignUnpackMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, pub src: Box<HighLevelILLiftedInstruction>, @@ -678,164 +203,74 @@ pub struct LiftedAssignUnpackMemSsa { } impl AssignUnpackMemSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (usize, usize), + num_dests: usize, + first_dest: usize, dest_memory: u64, src: usize, src_memory: u64, ) -> Self { Self { - function, - address, - dest, + num_dests, + first_dest, dest_memory, src, src_memory, } } - pub fn dest(&self) -> OperandExprList { - get_instruction_list(&self.function, self.dest) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedAssignUnpackMemSsa { - LiftedAssignUnpackMemSsa { - function: self.function.to_owned(), - address: self.address, - dest: self.dest().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("dest", ExprList(self.dest())), - 1usize => ("dest_memory", Int(self.dest_memory())), - 2usize => ("src", Expr(self.src())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // BLOCK -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Block { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - body: (usize, usize), + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBlock { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub body: Vec<HighLevelILLiftedInstruction>, } impl Block { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - body: (usize, usize), - ) -> Self { + pub(crate) fn new(num_params: usize, first_param: usize) -> Self { Self { - function, - address, - body, + num_params, + first_param, } } - pub fn body(&self) -> OperandExprList { - get_instruction_list(&self.function, self.body) - } - pub fn lift(&self) -> LiftedBlock { - LiftedBlock { - function: self.function.to_owned(), - address: self.address, - body: self.body().map(|x| x.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("body", ExprList(self.body())), - _ => unreachable!(), - }) - } } + // CALL, TAILCALL -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Call { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - params: (usize, usize), + pub dest: usize, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCall { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub params: Vec<HighLevelILLiftedInstruction>, } impl Call { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: usize, - params: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: usize, num_params: usize, first_param: usize) -> Self { Self { - function, - address, dest, - params, - } - } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn lift(&self) -> LiftedCall { - LiftedCall { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - params: self.params().map(|x| x.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("params", ExprList(self.params())), - _ => unreachable!(), - }) - } } + // CALL_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct CallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - params: (usize, usize), - dest_memory: u64, - src_memory: u64, + pub dest: usize, + pub first_param: usize, + pub num_params: usize, + pub dest_memory: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub params: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, @@ -843,496 +278,196 @@ pub struct LiftedCallSsa { } impl CallSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, dest: usize, - params: (usize, usize), + num_params: usize, + first_param: usize, dest_memory: u64, src_memory: u64, ) -> Self { Self { - function, - address, dest, - params, + num_params, + first_param, dest_memory, src_memory, } } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedCallSsa { - LiftedCallSsa { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - params: self.params().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("params", ExprList(self.params())), - 2usize => ("dest_memory", Int(self.dest_memory())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // CASE -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Case { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - values: (usize, usize), - body: usize, + pub first_value: usize, + pub num_values: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCase { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub values: Vec<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl Case { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - values: (usize, usize), - body: usize, - ) -> Self { + pub(crate) fn new(num_values: usize, first_value: usize, body: usize) -> Self { Self { - function, - address, - values, + num_values, + first_value, body, } } - pub fn values(&self) -> OperandExprList { - get_instruction_list(&self.function, self.values) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedCase { - LiftedCase { - function: self.function.to_owned(), - address: self.address, - values: self.values().map(|x| x.lift()).collect(), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("values", ExprList(self.values())), - 1usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } + // CONST, CONST_PTR, IMPORT -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Const { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant: u64, } impl Const { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, constant: u64) -> Self { - Self { - function, - address, - constant, - } - } - pub fn constant(&self) -> u64 { - self.constant - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("constant", Int(self.constant())), - _ => unreachable!(), - }) + pub(crate) fn new(constant: u64) -> Self { + Self { constant } } } + // CONST_DATA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ConstData { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - constant_data: (u32, u64, usize), + pub constant_data_kind: u32, + pub constant_data_value: i64, + pub size: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedConstantData { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant_data: ConstantData, } impl ConstData { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - constant_data: (u32, u64, usize), - ) -> Self { + pub(crate) fn new(constant_data_kind: u32, constant_data_value: i64, size: usize) -> Self { Self { - function, - address, - constant_data, + constant_data_kind, + constant_data_value, + size, } } - pub fn constant_data(&self) -> ConstantData { - let register_value = RegisterValue { - state: RegisterValueType::from_raw_value(self.constant_data.0).unwrap(), - value: self.constant_data.1 as i64, - offset: 0, - size: self.constant_data.2, - }; - ConstantData::new(self.function.get_function(), register_value) - } - pub fn lift(&self) -> LiftedConstantData { - LiftedConstantData { - function: self.function.to_owned(), - address: self.address, - constant_data: self.constant_data(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("constant_data", ConstantData(self.constant_data())), - _ => unreachable!(), - }) - } } + // DEREF, ADDRESS_OF, NEG, NOT, SX, ZX, LOW_PART, BOOL_TO_INT, UNIMPL_MEM, FSQRT, FNEG, FABS, FLOAT_TO_INT, INT_TO_FLOAT, FLOAT_CONV, ROUND_TO_INT, FLOOR, CEIL, FTRUNC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct UnaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedUnaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, } impl UnaryOp { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, src: usize) -> Self { - Self { - function, - address, - src, - } - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedUnaryOp { - LiftedUnaryOp { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) + pub(crate) fn new(src: usize) -> Self { + Self { src } } } + // DEREF_FIELD_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct DerefFieldSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, - offset: u64, - member_index: Option<usize>, + pub src: usize, + pub src_memory: u64, + pub offset: u64, + pub member_index: Option<usize>, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedDerefFieldSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, pub offset: u64, pub member_index: Option<usize>, } impl DerefFieldSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - offset: u64, - member_index: u64, - ) -> Self { + pub(crate) fn new(src: usize, src_memory: u64, offset: u64, member_index: u64) -> Self { Self { - function, - address, src, src_memory, offset, member_index: get_member_index(member_index), } } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn member_index(&self) -> Option<usize> { - self.member_index - } - pub fn lift(&self) -> LiftedDerefFieldSsa { - LiftedDerefFieldSsa { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - offset: self.offset, - member_index: self.member_index, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("src_memory", Int(self.src_memory())), - 2usize => ("offset", Int(self.offset())), - 3usize => ("member_index", MemberIndex(self.member_index())), - _ => unreachable!(), - }) - } } + // DEREF_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct DerefSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedDerefSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, } impl DerefSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - ) -> Self { - Self { - function, - address, - src, - src_memory, - } - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedDerefSsa { - LiftedDerefSsa { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) + pub(crate) fn new(src: usize, src_memory: u64) -> Self { + Self { src, src_memory } } } + // EXTERN_PTR -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ExternPtr { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant: u64, pub offset: u64, } impl ExternPtr { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - constant: u64, - offset: u64, - ) -> Self { - Self { - function, - address, - constant, - offset, - } - } - pub fn constant(&self) -> u64 { - self.constant - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("constant", Int(self.constant())), - 1usize => ("offset", Int(self.offset())), - _ => unreachable!(), - }) + pub(crate) fn new(constant: u64, offset: u64) -> Self { + Self { constant, offset } } } + // FLOAT_CONST -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct FloatConst { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant: f64, } impl FloatConst { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - constant: u64, - size: usize, - ) -> Self { + pub(crate) fn new(constant: u64, size: usize) -> Self { Self { - function, - address, constant: get_float(constant, size), } } - pub fn constant(&self) -> f64 { - self.constant - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("constant", Float(self.constant())), - _ => unreachable!(), - }) - } } + // FOR -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ForLoop { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - init: usize, - condition: usize, - update: usize, - body: usize, + pub init: usize, + pub condition: usize, + pub update: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedForLoop { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub init: Box<HighLevelILLiftedInstruction>, pub condition: Box<HighLevelILLiftedInstruction>, pub update: Box<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl ForLoop { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - init: usize, - condition: usize, - update: usize, - body: usize, - ) -> Self { + pub(crate) fn new(init: usize, condition: usize, update: usize, body: usize) -> Self { Self { - function, - address, init, condition, update, body, } } - pub fn init(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.init) - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn update(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.update) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedForLoop { - LiftedForLoop { - function: self.function.to_owned(), - address: self.address, - init: Box::new(self.init().lift()), - condition: Box::new(self.condition().lift()), - update: Box::new(self.update().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("init", Expr(self.init())), - 1usize => ("condition", Expr(self.condition())), - 2usize => ("update", Expr(self.update())), - 3usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } + // FOR_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ForLoopSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - init: usize, - condition_phi: usize, - condition: usize, - update: usize, - body: usize, + pub init: usize, + pub condition_phi: usize, + pub condition: usize, + pub update: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedForLoopSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub init: Box<HighLevelILLiftedInstruction>, pub condition_phi: Box<HighLevelILLiftedInstruction>, pub condition: Box<HighLevelILLiftedInstruction>, @@ -1341,8 +476,6 @@ pub struct LiftedForLoopSsa { } impl ForLoopSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, init: usize, condition_phi: usize, condition: usize, @@ -1350,8 +483,6 @@ impl ForLoopSsa { body: usize, ) -> Self { Self { - function, - address, init, condition_phi, condition, @@ -1359,200 +490,78 @@ impl ForLoopSsa { body, } } - pub fn init(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.init) - } - pub fn condition_phi(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition_phi) - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn update(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.update) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedForLoopSsa { - LiftedForLoopSsa { - function: self.function.to_owned(), - address: self.address, - init: Box::new(self.init().lift()), - condition_phi: Box::new(self.condition_phi().lift()), - condition: Box::new(self.condition().lift()), - update: Box::new(self.update().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..5usize).map(move |i| match i { - 0usize => ("init", Expr(self.init())), - 1usize => ("condition_phi", Expr(self.condition_phi())), - 2usize => ("condition", Expr(self.condition())), - 3usize => ("update", Expr(self.update())), - 4usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } + // GOTO, LABEL -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone)] pub struct Label { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub target: u64, } +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedLabel { + pub target: GotoLabel, +} impl Label { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, target: u64) -> Self { - Self { - function, - address, - target, - } - } - pub fn target(&self) -> GotoLabel { - GotoLabel { - function: self.function.get_function(), - target: self.target, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("target", Label(self.target())), - _ => unreachable!(), - }) + pub(crate) fn new(target: u64) -> Self { + Self { target } } } // IF -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct If { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition: usize, - cond_true: usize, - cond_false: usize, + pub condition: usize, + pub cond_true: usize, + pub cond_false: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIf { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition: Box<HighLevelILLiftedInstruction>, pub cond_true: Box<HighLevelILLiftedInstruction>, pub cond_false: Box<HighLevelILLiftedInstruction>, } impl If { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - condition: usize, - cond_true: usize, - cond_false: usize, - ) -> Self { + pub(crate) fn new(condition: usize, cond_true: usize, cond_false: usize) -> Self { Self { - function, - address, condition, cond_true, cond_false, } } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn cond_true(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.cond_true) - } - pub fn cond_false(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.cond_false) - } - pub fn lift(&self) -> LiftedIf { - LiftedIf { - function: self.function.to_owned(), - address: self.address, - condition: Box::new(self.condition().lift()), - cond_true: Box::new(self.cond_true().lift()), - cond_false: Box::new(self.cond_false().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("condition", Expr(self.condition())), - 1usize => ("cond_true", Expr(self.cond_true())), - 2usize => ("cond_false", Expr(self.cond_false())), - _ => unreachable!(), - }) - } } + // INTRINSIC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Intrinsic { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - intrinsic: u32, - params: (usize, usize), + pub intrinsic: u32, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIntrinsic { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub intrinsic: ILIntrinsic, pub params: Vec<HighLevelILLiftedInstruction>, } impl Intrinsic { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - intrinsic: u32, - params: (usize, usize), - ) -> Self { + pub(crate) fn new(intrinsic: u32, num_params: usize, first_param: usize) -> Self { Self { - function, - address, intrinsic, - params, - } - } - pub fn intrinsic(&self) -> ILIntrinsic { - ILIntrinsic::new(self.function.get_function().arch(), self.intrinsic) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn lift(&self) -> LiftedIntrinsic { - LiftedIntrinsic { - function: self.function.to_owned(), - address: self.address, - intrinsic: self.intrinsic(), - params: self.params().map(|x| x.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("intrinsic", Intrinsic(self.intrinsic())), - 1usize => ("params", ExprList(self.params())), - _ => unreachable!(), - }) - } } + // INTRINSIC_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct IntrinsicSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - intrinsic: u32, - params: (usize, usize), - dest_memory: u64, - src_memory: u64, + pub intrinsic: u32, + pub first_param: usize, + pub num_params: usize, + pub dest_memory: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIntrinsicSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub intrinsic: ILIntrinsic, pub params: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, @@ -1560,814 +569,330 @@ pub struct LiftedIntrinsicSsa { } impl IntrinsicSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, intrinsic: u32, - params: (usize, usize), + num_params: usize, + first_param: usize, dest_memory: u64, src_memory: u64, ) -> Self { Self { - function, - address, intrinsic, - params, + num_params, + first_param, dest_memory, src_memory, } } - pub fn intrinsic(&self) -> ILIntrinsic { - ILIntrinsic::new(self.function.get_function().arch(), self.intrinsic) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedIntrinsicSsa { - LiftedIntrinsicSsa { - function: self.function.to_owned(), - address: self.address, - intrinsic: self.intrinsic(), - params: self.params().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("intrinsic", Intrinsic(self.intrinsic())), - 1usize => ("params", ExprList(self.params())), - 2usize => ("dest_memory", Int(self.dest_memory())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // JUMP -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone)] pub struct Jump { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: usize, } +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedJump { + pub dest: Box<HighLevelILLiftedInstruction>, +} impl Jump { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, dest: usize) -> Self { - Self { - function, - address, - dest, - } - } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - _ => unreachable!(), - }) + pub(crate) fn new(dest: usize) -> Self { + Self { dest } } } + // MEM_PHI -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct MemPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: u64, - src: (usize, usize), + pub dest: u64, + pub first_src: usize, + pub num_srcs: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedMemPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: u64, pub src: Vec<u64>, } impl MemPhi { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: u64, - src: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: u64, num_srcs: usize, first_src: usize) -> Self { Self { - function, - address, dest, - src, + num_srcs, + first_src, } } - pub fn dest(&self) -> u64 { - self.dest - } - pub fn src(&self) -> OperandList { - get_int_list(&self.function, self.src) - } - pub fn lift(&self) -> LiftedMemPhi { - LiftedMemPhi { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: self.src().collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Int(self.dest())), - 1usize => ("src", IntList(self.src())), - _ => unreachable!(), - }) - } -} -// NOP, BREAK, CONTINUE, NORET, UNREACHABLE, BP, UNDEF, UNIMPL -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct NoArgs { - pub function: Ref<HighLevelILFunction>, - pub address: u64, -} -impl NoArgs { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64) -> Self { - Self { function, address } - } - // NOTE self is not required, it's present just in case data is added to - // the struct in the future - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - [].into_iter() - } } + // RET -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Ret { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: (usize, usize), + pub first_src: usize, + pub num_srcs: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedRet { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Vec<HighLevelILLiftedInstruction>, } impl Ret { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: (usize, usize), - ) -> Self { + pub(crate) fn new(num_srcs: usize, first_src: usize) -> Self { Self { - function, - address, - src, - } - } - pub fn src(&self) -> OperandExprList { - get_instruction_list(&self.function, self.src) - } - pub fn lift(&self) -> LiftedRet { - LiftedRet { - function: self.function.to_owned(), - address: self.address, - src: self.src().map(|x| x.lift()).collect(), + first_src, + num_srcs, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("src", ExprList(self.src())), - _ => unreachable!(), - }) - } } + // SPLIT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Split { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - high: usize, - low: usize, + pub high: usize, + pub low: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSplit { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub high: Box<HighLevelILLiftedInstruction>, pub low: Box<HighLevelILLiftedInstruction>, } impl Split { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - high: usize, - low: usize, - ) -> Self { - Self { - function, - address, - high, - low, - } - } - pub fn high(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.high) - } - pub fn low(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.low) - } - pub fn lift(&self) -> LiftedSplit { - LiftedSplit { - function: self.function.to_owned(), - address: self.address, - high: Box::new(self.high().lift()), - low: Box::new(self.low().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("high", Expr(self.high())), - 1usize => ("low", Expr(self.low())), - _ => unreachable!(), - }) + pub(crate) fn new(high: usize, low: usize) -> Self { + Self { high, low } } } + // STRUCT_FIELD, DEREF_FIELD -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct StructField { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - offset: u64, - member_index: Option<usize>, + pub src: usize, + pub offset: u64, + pub member_index: Option<usize>, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedStructField { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub offset: u64, pub member_index: Option<usize>, } impl StructField { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - offset: u64, - member_index: u64, - ) -> Self { + pub(crate) fn new(src: usize, offset: u64, member_index: u64) -> Self { Self { - function, - address, src, offset, member_index: get_member_index(member_index), } } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn member_index(&self) -> Option<usize> { - self.member_index - } - pub fn lift(&self) -> LiftedStructField { - LiftedStructField { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - offset: self.offset, - member_index: self.member_index, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("offset", Int(self.offset())), - 2usize => ("member_index", MemberIndex(self.member_index())), - _ => unreachable!(), - }) - } } + // SWITCH -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Switch { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition: usize, - default: usize, - cases: (usize, usize), + pub condition: usize, + pub default: usize, + pub first_case: usize, + pub num_cases: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSwitch { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition: Box<HighLevelILLiftedInstruction>, pub default: Box<HighLevelILLiftedInstruction>, pub cases: Vec<HighLevelILLiftedInstruction>, } impl Switch { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, condition: usize, default: usize, - cases: (usize, usize), + num_cases: usize, + first_case: usize, ) -> Self { Self { - function, - address, condition, default, - cases, - } - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn default(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.default) - } - pub fn cases(&self) -> OperandExprList { - get_instruction_list(&self.function, self.cases) - } - pub fn lift(&self) -> LiftedSwitch { - LiftedSwitch { - function: self.function.to_owned(), - address: self.address, - condition: Box::new(self.condition().lift()), - default: Box::new(self.default().lift()), - cases: self.cases().map(|x| x.lift()).collect(), + num_cases, + first_case, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("condition", Expr(self.condition())), - 1usize => ("default", Expr(self.default())), - 2usize => ("cases", ExprList(self.cases())), - _ => unreachable!(), - }) - } } + // SYSCALL -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Syscall { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - params: (usize, usize), + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscall { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub params: Vec<HighLevelILLiftedInstruction>, } impl Syscall { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - params: (usize, usize), - ) -> Self { + pub(crate) fn new(num_params: usize, first_param: usize) -> Self { Self { - function, - address, - params, + num_params, + first_param, } } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn lift(&self) -> LiftedSyscall { - LiftedSyscall { - function: self.function.to_owned(), - address: self.address, - params: self.params().map(|x| x.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("params", ExprList(self.params())), - _ => unreachable!(), - }) - } } + // SYSCALL_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SyscallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - params: (usize, usize), - dest_memory: u64, - src_memory: u64, + pub first_param: usize, + pub num_params: usize, + pub dest_memory: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub params: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, pub src_memory: u64, } impl SyscallSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - params: (usize, usize), + num_params: usize, + first_param: usize, dest_memory: u64, src_memory: u64, ) -> Self { Self { - function, - address, - params, + num_params, + first_param, dest_memory, src_memory, } } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedSyscallSsa { - LiftedSyscallSsa { - function: self.function.to_owned(), - address: self.address, - params: self.params().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("params", ExprList(self.params())), - 1usize => ("dest_memory", Int(self.dest_memory())), - 2usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // TRAP -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Trap { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub vector: u64, } impl Trap { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, vector: u64) -> Self { - Self { - function, - address, - vector, - } - } - pub fn vector(&self) -> u64 { - self.vector - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("vector", Int(self.vector())), - _ => unreachable!(), - }) + pub(crate) fn new(vector: u64) -> Self { + Self { vector } } } + // VAR_DECLARE, VAR -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Var { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub var: Variable, } impl Var { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, var: u64) -> Self { - Self { - function, - address, - var: get_var(var), - } - } - pub fn var(&self) -> Variable { - self.var - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("var", Var(self.var())), - _ => unreachable!(), - }) + pub(crate) fn new(var: u64) -> Self { + Self { var: get_var(var) } } } + // VAR_INIT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarInit { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: Variable, - src: usize, + pub dest: Variable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedVarInit { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Variable, pub src: Box<HighLevelILLiftedInstruction>, } impl VarInit { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: u64, - src: usize, - ) -> Self { + pub(crate) fn new(dest: u64, src: usize) -> Self { Self { - function, - address, dest: get_var(dest), src, } } - pub fn dest(&self) -> Variable { - self.dest - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedVarInit { - LiftedVarInit { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Var(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) - } } + // VAR_INIT_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarInitSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: SSAVariable, - src: usize, + pub dest: SSAVariable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedVarInitSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub src: Box<HighLevelILLiftedInstruction>, } impl VarInitSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (u64, usize), - src: usize, - ) -> Self { + pub(crate) fn new(dest: (u64, usize), src: usize) -> Self { Self { - function, - address, dest: get_var_ssa(dest), src, } } - pub fn dest(&self) -> SSAVariable { - self.dest - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedVarInitSsa { - LiftedVarInitSsa { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", VarSsa(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) - } } + // VAR_PHI -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: SSAVariable, - src: (usize, usize), + pub dest: SSAVariable, + pub first_src: usize, + pub num_srcs: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedVarPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub src: Vec<SSAVariable>, } impl VarPhi { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (u64, usize), - src: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: (u64, usize), num_srcs: usize, first_src: usize) -> Self { Self { - function, - address, dest: get_var_ssa(dest), - src, + num_srcs, + first_src, } } - pub fn dest(&self) -> SSAVariable { - self.dest - } - pub fn src(&self) -> OperandSSAVariableList { - get_var_ssa_list(&self.function, self.src) - } - pub fn lift(&self) -> LiftedVarPhi { - LiftedVarPhi { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: self.src().collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", VarSsa(self.dest())), - 1usize => ("src", VarSsaList(self.src())), - _ => unreachable!(), - }) - } } + // VAR_SSA -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub var: SSAVariable, } impl VarSsa { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, var: (u64, usize)) -> Self { + pub(crate) fn new(var: (u64, usize)) -> Self { Self { - function, - address, var: get_var_ssa(var), } } - pub fn var(&self) -> SSAVariable { - self.var - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("var", VarSsa(self.var())), - _ => unreachable!(), - }) - } } + // WHILE, DO_WHILE -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct While { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition: usize, - body: usize, + pub condition: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedWhile { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition: Box<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl While { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - condition: usize, - body: usize, - ) -> Self { - Self { - function, - address, - condition, - body, - } - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedWhile { - LiftedWhile { - function: self.function.to_owned(), - address: self.address, - condition: Box::new(self.condition().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("condition", Expr(self.condition())), - 1usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) + pub(crate) fn new(condition: usize, body: usize) -> Self { + Self { condition, body } } } + // WHILE_SSA, DO_WHILE_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct WhileSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition_phi: usize, - condition: usize, - body: usize, + pub condition_phi: usize, + pub condition: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedWhileSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition_phi: Box<HighLevelILLiftedInstruction>, pub condition: Box<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl WhileSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - condition_phi: usize, - condition: usize, - body: usize, - ) -> Self { + pub(crate) fn new(condition_phi: usize, condition: usize, body: usize) -> Self { Self { - function, - address, condition_phi, condition, body, } } - pub fn condition_phi(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition_phi) - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedWhileSsa { - LiftedWhileSsa { - function: self.function.to_owned(), - address: self.address, - condition_phi: Box::new(self.condition_phi().lift()), - condition: Box::new(self.condition().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("condition_phi", Expr(self.condition_phi())), - 1usize => ("condition", Expr(self.condition())), - 2usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } |
