use super::{operation::*, HighLevelILFunction}; use crate::rc::Ref; use crate::types::{ConstantData, ILIntrinsic, SSAVariable, Variable}; #[derive(Clone)] pub enum HighLevelILLiftedOperand { ConstantData(ConstantData), Expr(HighLevelILLiftedInstruction), ExprList(Vec), Float(f64), Int(u64), IntList(Vec), Intrinsic(ILIntrinsic), Label(GotoLabel), MemberIndex(Option), Var(Variable), VarSsa(SSAVariable), VarSsaList(Vec), } #[derive(Clone, Debug, PartialEq)] pub struct HighLevelILLiftedInstruction { pub function: Ref, pub address: u64, pub kind: HighLevelILLiftedInstructionKind, } #[derive(Clone, Debug, PartialEq)] pub enum HighLevelILLiftedInstructionKind { 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(LiftedConstantData), 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), Nop, Break, Continue, Noret, Unreachable, Bp, Undef, Unimpl, 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 operands(&self) -> Vec<(&'static str, HighLevelILLiftedOperand)> { use HighLevelILLiftedInstructionKind::*; use HighLevelILLiftedOperand as Operand; match &self.kind { 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())), ], Nop | Break | Continue | Noret | Unreachable | Bp | Undef | Unimpl => vec![], 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())), ], } } }