use super::operation::*;
use super::HighLevelILFunction;
use crate::architecture::CoreIntrinsic;
use crate::rc::Ref;
use crate::types::{ConstantData, SSAVariable, Variable};
#[derive(Clone)]
pub enum HighLevelILLiftedOperand {
ConstantData(ConstantData),
Expr(HighLevelILLiftedInstruction),
ExprList(Vec<HighLevelILLiftedInstruction>),
Float(f64),
Int(u64),
IntList(Vec<u64>),
Intrinsic(CoreIntrinsic),
Label(GotoLabel),
MemberIndex(Option<usize>),
Var(Variable),
VarSsa(SSAVariable),
VarSsaList(Vec<SSAVariable>),
}
#[derive(Clone, Debug, PartialEq)]
pub struct HighLevelILLiftedInstruction {
pub function: Ref<HighLevelILFunction>,
pub address: u64,
pub index: usize,
pub size: usize,
pub kind: HighLevelILLiftedInstructionKind,
}
#[derive(Clone, Debug, PartialEq)]
pub enum HighLevelILLiftedInstructionKind {
Nop,
Break,
Continue,
Noret,
Unreachable,
Bp,
Undef,
Unimpl,
Adc(LiftedBinaryOpCarry),
Sbb(LiftedBinaryOpCarry),
Rlc(LiftedBinaryOpCarry),
Rrc(LiftedBinaryOpCarry),
Add(LiftedBinaryOp),
Sub(LiftedBinaryOp),
And(LiftedBinaryOp),
Or(LiftedBinaryOp),
Xor(LiftedBinaryOp),
Lsl(LiftedBinaryOp),
Lsr(LiftedBinaryOp),
Asr(LiftedBinaryOp),
Rol(LiftedBinaryOp),
Ror(LiftedBinaryOp),
Mul(LiftedBinaryOp),
MuluDp(LiftedBinaryOp),
MulsDp(LiftedBinaryOp),
Divu(LiftedBinaryOp),
DivuDp(LiftedBinaryOp),
Divs(LiftedBinaryOp),
DivsDp(LiftedBinaryOp),
Modu(LiftedBinaryOp),
ModuDp(LiftedBinaryOp),
Mods(LiftedBinaryOp),
ModsDp(LiftedBinaryOp),
CmpE(LiftedBinaryOp),
CmpNe(LiftedBinaryOp),
CmpSlt(LiftedBinaryOp),
CmpUlt(LiftedBinaryOp),
CmpSle(LiftedBinaryOp),
CmpUle(LiftedBinaryOp),
CmpSge(LiftedBinaryOp),
CmpUge(LiftedBinaryOp),
CmpSgt(LiftedBinaryOp),
CmpUgt(LiftedBinaryOp),
TestBit(LiftedBinaryOp),
AddOverflow(LiftedBinaryOp),
Fadd(LiftedBinaryOp),
Fsub(LiftedBinaryOp),
Fmul(LiftedBinaryOp),
Fdiv(LiftedBinaryOp),
FcmpE(LiftedBinaryOp),
FcmpNe(LiftedBinaryOp),
FcmpLt(LiftedBinaryOp),
FcmpLe(LiftedBinaryOp),
FcmpGe(LiftedBinaryOp),
FcmpGt(LiftedBinaryOp),
FcmpO(LiftedBinaryOp),
FcmpUo(LiftedBinaryOp),
ArrayIndex(LiftedArrayIndex),
ArrayIndexSsa(LiftedArrayIndexSsa),
Assign(LiftedAssign),
AssignMemSsa(LiftedAssignMemSsa),
AssignUnpack(LiftedAssignUnpack),
AssignUnpackMemSsa(LiftedAssignUnpackMemSsa),
Block(LiftedBlock),
Call(LiftedCall),
Tailcall(LiftedCall),
CallSsa(LiftedCallSsa),
Case(LiftedCase),
Const(Const),
ConstPtr(Const),
Import(Const),
ConstData(LiftedConstData),
Deref(LiftedUnaryOp),
AddressOf(LiftedUnaryOp),
Neg(LiftedUnaryOp),
Not(LiftedUnaryOp),
Sx(LiftedUnaryOp),
Zx(LiftedUnaryOp),
LowPart(LiftedUnaryOp),
BoolToInt(LiftedUnaryOp),
UnimplMem(LiftedUnaryOp),
Fsqrt(LiftedUnaryOp),
Fneg(LiftedUnaryOp),
Fabs(LiftedUnaryOp),
FloatToInt(LiftedUnaryOp),
IntToFloat(LiftedUnaryOp),
FloatConv(LiftedUnaryOp),
RoundToInt(LiftedUnaryOp),
Floor(LiftedUnaryOp),
Ceil(LiftedUnaryOp),
Ftrunc(LiftedUnaryOp),
DerefFieldSsa(LiftedDerefFieldSsa),
DerefSsa(LiftedDerefSsa),
ExternPtr(ExternPtr),
FloatConst(FloatConst),
For(LiftedForLoop),
ForSsa(LiftedForLoopSsa),
Goto(LiftedLabel),
Label(LiftedLabel),
If(LiftedIf),
Intrinsic(LiftedIntrinsic),
IntrinsicSsa(LiftedIntrinsicSsa),
Jump(LiftedJump),
MemPhi(LiftedMemPhi),
Ret(LiftedRet),
Split(LiftedSplit),
StructField(LiftedStructField),
DerefField(LiftedStructField),
Switch(LiftedSwitch),
Syscall(LiftedSyscall),
SyscallSsa(LiftedSyscallSsa),
Trap(Trap),
VarDeclare(Var),
Var(Var),
VarInit(LiftedVarInit),
VarInitSsa(LiftedVarInitSsa),
VarPhi(LiftedVarPhi),
VarSsa(VarSsa),
While(LiftedWhile),
DoWhile(LiftedWhile),
WhileSsa(LiftedWhileSsa),
DoWhileSsa(LiftedWhileSsa),
}
impl HighLevelILLiftedInstruction {
pub fn name(&self) -> &'static str {
use HighLevelILLiftedInstructionKind::*;
match self.kind {
Nop => "Nop",
Break => "Break",
Continue => "Continue",
Noret => "Noret",
Unreachable => "Unreachable",
Bp => "Bp",
Undef => "Undef",
Unimpl => "Unimpl",
Adc(_) => "Adc",
Sbb(_) => "Sbb",
Rlc(_) => "Rlc",
Rrc(_) => "Rrc",
Add(_) => "Add",
Sub(_) => "Sub",
And(_) => "And",
Or(_) => "Or",
Xor(_) => "Xor",
Lsl(_) => "Lsl",
Lsr(_) => "Lsr",
Asr(_) => "Asr",
Rol(_) => "Rol",
Ror(_) => "Ror",
Mul(_) => "Mul",
MuluDp(_) => "MuluDp",
MulsDp(_) => "MulsDp",
Divu(_) => "Divu",
DivuDp(_) => "DivuDp",
Divs(_) => "Divs",
DivsDp(_) => "DivsDp",
Modu(_) => "Modu",
ModuDp(_) => "ModuDp",
Mods(_) => "Mods",
ModsDp(_) => "ModsDp",
CmpE(_) => "CmpE",
CmpNe(_) => "CmpNe",
CmpSlt(_) => "CmpSlt",
CmpUlt(_) => "CmpUlt",
CmpSle(_) => "CmpSle",
CmpUle(_) => "CmpUle",
CmpSge(_) => "CmpSge",
CmpUge(_) => "CmpUge",
CmpSgt(_) => "CmpSgt",
CmpUgt(_) => "CmpUgt",
TestBit(_) => "TestBit",
AddOverflow(_) => "AddOverflow",
Fadd(_) => "Fadd",
Fsub(_) => "Fsub",
Fmul(_) => "Fmul",
Fdiv(_) => "Fdiv",
FcmpE(_) => "FcmpE",
FcmpNe(_) => "FcmpNe",
FcmpLt(_) => "FcmpLt",
FcmpLe(_) => "FcmpLe",
FcmpGe(_) => "FcmpGe",
FcmpGt(_) => "FcmpGt",
FcmpO(_) => "FcmpO",
FcmpUo(_) => "FcmpUo",
ArrayIndex(_) => "ArrayIndex",
ArrayIndexSsa(_) => "ArrayIndexSsa",
Assign(_) => "Assign",
AssignMemSsa(_) => "AssignMemSsa",
AssignUnpack(_) => "AssignUnpack",
AssignUnpackMemSsa(_) => "AssignUnpackMemSsa",
Block(_) => "Block",
Call(_) => "Call",
Tailcall(_) => "Tailcall",
CallSsa(_) => "CallSsa",
Case(_) => "Case",
Const(_) => "Const",
ConstPtr(_) => "ConstPtr",
Import(_) => "Import",
ConstData(_) => "ConstData",
Deref(_) => "Deref",
AddressOf(_) => "AddressOf",
Neg(_) => "Neg",
Not(_) => "Not",
Sx(_) => "Sx",
Zx(_) => "Zx",
LowPart(_) => "LowPart",
BoolToInt(_) => "BoolToInt",
UnimplMem(_) => "UnimplMem",
Fsqrt(_) => "Fsqrt",
Fneg(_) => "Fneg",
Fabs(_) => "Fabs",
FloatToInt(_) => "FloatToInt",
IntToFloat(_) => "IntToFloat",
FloatConv(_) => "FloatConv",
RoundToInt(_) => "RoundToInt",
Floor(_) => "Floor",
Ceil(_) => "Ceil",
Ftrunc(_) => "Ftrunc",
DerefFieldSsa(_) => "DerefFieldSsa",
DerefSsa(_) => "DerefSsa",
ExternPtr(_) => "ExternPtr",
FloatConst(_) => "FloatConst",
For(_) => "For",
ForSsa(_) => "ForSsa",
Goto(_) => "Goto",
Label(_) => "Label",
If(_) => "If",
Intrinsic(_) => "Intrinsic",
IntrinsicSsa(_) => "IntrinsicSsa",
Jump(_) => "Jump",
MemPhi(_) => "MemPhi",
Ret(_) => "Ret",
Split(_) => "Split",
StructField(_) => "StructField",
DerefField(_) => "DerefField",
Switch(_) => "Switch",
Syscall(_) => "Syscall",
SyscallSsa(_) => "SyscallSsa",
Trap(_) => "Trap",
VarDeclare(_) => "VarDeclare",
Var(_) => "Var",
VarInit(_) => "VarInit",
VarInitSsa(_) => "VarInitSsa",
VarPhi(_) => "VarPhi",
VarSsa(_) => "VarSsa",
While(_) => "While",
DoWhile(_) => "DoWhile",
WhileSsa(_) => "WhileSsa",
DoWhileSsa(_) => "DoWhileSsa",
}
}
pub fn operands(&self) -> Vec<(&'static str, HighLevelILLiftedOperand)> {
use HighLevelILLiftedInstructionKind::*;
use HighLevelILLiftedOperand as Operand;
match &self.kind {
Nop | Break | Continue | Noret | Unreachable | Bp | Undef | Unimpl => vec![],
Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![
("left", Operand::Expr(*op.left.clone())),
("right", Operand::Expr(*op.right.clone())),
("carry", Operand::Expr(*op.carry.clone())),
],
Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
| Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
| Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
| CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
| CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | Fadd(op)
| Fsub(op) | Fmul(op) | Fdiv(op) | FcmpE(op) | FcmpNe(op) | FcmpLt(op) | FcmpLe(op)
| FcmpGe(op) | FcmpGt(op) | FcmpO(op) | FcmpUo(op) => vec![
("left", Operand::Expr(*op.left.clone())),
("right", Operand::Expr(*op.right.clone())),
],
ArrayIndex(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("index", Operand::Expr(*op.index.clone())),
],
ArrayIndexSsa(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("src_memory", Operand::Int(op.src_memory)),
("index", Operand::Expr(*op.index.clone())),
],
Assign(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("src", Operand::Expr(*op.src.clone())),
],
AssignMemSsa(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("dest_memory", Operand::Int(op.dest_memory)),
("src", Operand::Expr(*op.src.clone())),
("src_memory", Operand::Int(op.src_memory)),
],
AssignUnpack(op) => vec![
("dest", Operand::ExprList(op.dest.clone())),
("src", Operand::Expr(*op.src.clone())),
],
AssignUnpackMemSsa(op) => vec![
("dest", Operand::ExprList(op.dest.clone())),
("dest_memory", Operand::Int(op.dest_memory)),
("src", Operand::Expr(*op.src.clone())),
("src_memory", Operand::Int(op.src_memory)),
],
Block(op) => vec![("body", Operand::ExprList(op.body.clone()))],
Call(op) | Tailcall(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("params", Operand::ExprList(op.params.clone())),
],
CallSsa(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("params", Operand::ExprList(op.params.clone())),
("dest_memory", Operand::Int(op.dest_memory)),
("src_memory", Operand::Int(op.src_memory)),
],
Case(op) => vec![
("values", Operand::ExprList(op.values.clone())),
("body", Operand::Expr(*op.body.clone())),
],
Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
ConstData(op) => vec![(
"constant_data",
Operand::ConstantData(op.constant_data.clone()),
)],
Deref(op) | AddressOf(op) | Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op)
| BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op)
| IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op)
| Ftrunc(op) => vec![("src", Operand::Expr(*op.src.clone()))],
DerefFieldSsa(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("src_memory", Operand::Int(op.src_memory)),
("offset", Operand::Int(op.offset)),
("member_index", Operand::MemberIndex(op.member_index)),
],
DerefSsa(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("src_memory", Operand::Int(op.src_memory)),
],
ExternPtr(op) => vec![
("constant", Operand::Int(op.constant)),
("offset", Operand::Int(op.offset)),
],
FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
For(op) => vec![
("init", Operand::Expr(*op.init.clone())),
("condition", Operand::Expr(*op.condition.clone())),
("update", Operand::Expr(*op.update.clone())),
("body", Operand::Expr(*op.body.clone())),
],
ForSsa(op) => vec![
("init", Operand::Expr(*op.init.clone())),
("condition_phi", Operand::Expr(*op.condition_phi.clone())),
("condition", Operand::Expr(*op.condition.clone())),
("update", Operand::Expr(*op.update.clone())),
("body", Operand::Expr(*op.body.clone())),
],
Goto(op) | Label(op) => vec![("target", Operand::Label(op.target.clone()))],
If(op) => vec![
("condition", Operand::Expr(*op.condition.clone())),
("cond_true", Operand::Expr(*op.cond_true.clone())),
("cond_false", Operand::Expr(*op.cond_false.clone())),
],
Intrinsic(op) => vec![
("intrinsic", Operand::Intrinsic(op.intrinsic)),
("params", Operand::ExprList(op.params.clone())),
],
IntrinsicSsa(op) => vec![
("intrinsic", Operand::Intrinsic(op.intrinsic)),
("params", Operand::ExprList(op.params.clone())),
("dest_memory", Operand::Int(op.dest_memory)),
("src_memory", Operand::Int(op.src_memory)),
],
Jump(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
MemPhi(op) => vec![
("dest", Operand::Int(op.dest)),
("src", Operand::IntList(op.src.clone())),
],
Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
Split(op) => vec![
("high", Operand::Expr(*op.high.clone())),
("low", Operand::Expr(*op.low.clone())),
],
StructField(op) | DerefField(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("offset", Operand::Int(op.offset)),
("member_index", Operand::MemberIndex(op.member_index)),
],
Switch(op) => vec![
("condition", Operand::Expr(*op.condition.clone())),
("default", Operand::Expr(*op.default.clone())),
("cases", Operand::ExprList(op.cases.clone())),
],
Syscall(op) => vec![("params", Operand::ExprList(op.params.clone()))],
SyscallSsa(op) => vec![
("params", Operand::ExprList(op.params.clone())),
("dest_memory", Operand::Int(op.dest_memory)),
("src_memory", Operand::Int(op.src_memory)),
],
Trap(op) => vec![("vector", Operand::Int(op.vector))],
VarDeclare(op) | Var(op) => vec![("var", Operand::Var(op.var))],
VarInit(op) => vec![
("dest", Operand::Var(op.dest)),
("src", Operand::Expr(*op.src.clone())),
],
VarInitSsa(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("src", Operand::Expr(*op.src.clone())),
],
VarPhi(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("src", Operand::VarSsaList(op.src.clone())),
],
VarSsa(op) => vec![("var", Operand::VarSsa(op.var))],
While(op) | DoWhile(op) => vec![
("condition", Operand::Expr(*op.condition.clone())),
("body", Operand::Expr(*op.body.clone())),
],
WhileSsa(op) | DoWhileSsa(op) => vec![
("condition_phi", Operand::Expr(*op.condition_phi.clone())),
("condition", Operand::Expr(*op.condition.clone())),
("body", Operand::Expr(*op.body.clone())),
],
}
}
}