diff options
Diffstat (limited to 'rust/src/medium_level_il/lift.rs')
| -rw-r--r-- | rust/src/medium_level_il/lift.rs | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/rust/src/medium_level_il/lift.rs b/rust/src/medium_level_il/lift.rs new file mode 100644 index 00000000..d6cceb18 --- /dev/null +++ b/rust/src/medium_level_il/lift.rs @@ -0,0 +1,510 @@ +use std::collections::BTreeMap; + +use super::operation::*; +use super::{MediumLevelILFunction, MediumLevelInstructionIndex}; +use crate::architecture::CoreIntrinsic; +use crate::rc::Ref; +use crate::variable::{ConstantData, SSAVariable, Variable}; + +#[derive(Clone)] +pub enum MediumLevelILLiftedOperand { + ConstantData(ConstantData), + Intrinsic(CoreIntrinsic), + Expr(MediumLevelILLiftedInstruction), + ExprList(Vec<MediumLevelILLiftedInstruction>), + Float(f64), + Int(u64), + IntList(Vec<u64>), + TargetMap(BTreeMap<u64, MediumLevelInstructionIndex>), + Var(Variable), + VarList(Vec<Variable>), + VarSsa(SSAVariable), + VarSsaList(Vec<SSAVariable>), + InstructionIndex(MediumLevelInstructionIndex), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct MediumLevelILLiftedInstruction { + pub function: Ref<MediumLevelILFunction>, + pub address: u64, + pub index: MediumLevelInstructionIndex, + pub size: usize, + pub kind: MediumLevelILLiftedInstructionKind, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum MediumLevelILLiftedInstructionKind { + Nop, + Noret, + Bp, + Undef, + Unimpl, + If(LiftedIf), + FloatConst(FloatConst), + Const(Constant), + ConstPtr(Constant), + Import(Constant), + ExternPtr(ExternPtr), + ConstData(LiftedConstData), + Jump(LiftedJump), + RetHint(LiftedJump), + StoreSsa(LiftedStoreSsa), + StoreStructSsa(LiftedStoreStructSsa), + StoreStruct(LiftedStoreStruct), + Store(LiftedStore), + JumpTo(LiftedJumpTo), + Goto(Goto), + FreeVarSlot(FreeVarSlot), + SetVarField(LiftedSetVarField), + SetVar(LiftedSetVar), + FreeVarSlotSsa(FreeVarSlotSsa), + SetVarSsaField(LiftedSetVarSsaField), + SetVarAliasedField(LiftedSetVarSsaField), + SetVarAliased(LiftedSetVarAliased), + SetVarSsa(LiftedSetVarSsa), + VarPhi(LiftedVarPhi), + MemPhi(LiftedMemPhi), + VarSplit(VarSplit), + SetVarSplit(LiftedSetVarSplit), + VarSplitSsa(VarSplitSsa), + SetVarSplitSsa(LiftedSetVarSplitSsa), + 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), + FcmpE(LiftedBinaryOp), + FcmpNe(LiftedBinaryOp), + FcmpLt(LiftedBinaryOp), + FcmpLe(LiftedBinaryOp), + FcmpGe(LiftedBinaryOp), + FcmpGt(LiftedBinaryOp), + FcmpO(LiftedBinaryOp), + FcmpUo(LiftedBinaryOp), + Fadd(LiftedBinaryOp), + Fsub(LiftedBinaryOp), + Fmul(LiftedBinaryOp), + Fdiv(LiftedBinaryOp), + Adc(LiftedBinaryOpCarry), + Sbb(LiftedBinaryOpCarry), + Rlc(LiftedBinaryOpCarry), + Rrc(LiftedBinaryOpCarry), + Call(LiftedCall), + Tailcall(LiftedCall), + Intrinsic(LiftedIntrinsic), + Syscall(LiftedSyscallCall), + IntrinsicSsa(LiftedIntrinsicSsa), + CallSsa(LiftedCallSsa), + TailcallSsa(LiftedCallSsa), + CallUntypedSsa(LiftedCallUntypedSsa), + TailcallUntypedSsa(LiftedCallUntypedSsa), + SyscallSsa(LiftedSyscallSsa), + SyscallUntypedSsa(LiftedSyscallUntypedSsa), + CallUntyped(LiftedCallUntyped), + TailcallUntyped(LiftedCallUntyped), + SyscallUntyped(LiftedSyscallUntyped), + SeparateParamList(LiftedSeparateParamList), + SharedParamSlot(LiftedSharedParamSlot), + 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), + Load(LiftedUnaryOp), + LoadStruct(LiftedLoadStruct), + LoadStructSsa(LiftedLoadStructSsa), + LoadSsa(LiftedLoadSsa), + Ret(LiftedRet), + Var(Var), + AddressOf(Var), + VarField(Field), + AddressOfField(Field), + VarSsa(VarSsa), + VarAliased(VarSsa), + VarSsaField(VarSsaField), + VarAliasedField(VarSsaField), + Trap(Trap), +} + +impl MediumLevelILLiftedInstruction { + pub fn name(&self) -> &'static str { + use MediumLevelILLiftedInstructionKind::*; + match self.kind { + Nop => "Nop", + Noret => "Noret", + Bp => "Bp", + Undef => "Undef", + Unimpl => "Unimpl", + If(_) => "If", + FloatConst(_) => "FloatConst", + Const(_) => "Const", + ConstPtr(_) => "ConstPtr", + Import(_) => "Import", + ExternPtr(_) => "ExternPtr", + ConstData(_) => "ConstData", + Jump(_) => "Jump", + RetHint(_) => "RetHint", + StoreSsa(_) => "StoreSsa", + StoreStructSsa(_) => "StoreStructSsa", + StoreStruct(_) => "StoreStruct", + Store(_) => "Store", + JumpTo(_) => "JumpTo", + Goto(_) => "Goto", + FreeVarSlot(_) => "FreeVarSlot", + SetVarField(_) => "SetVarField", + SetVar(_) => "SetVar", + FreeVarSlotSsa(_) => "FreeVarSlotSsa", + SetVarSsaField(_) => "SetVarSsaField", + SetVarAliasedField(_) => "SetVarAliasedField", + SetVarAliased(_) => "SetVarAliased", + SetVarSsa(_) => "SetVarSsa", + VarPhi(_) => "VarPhi", + MemPhi(_) => "MemPhi", + VarSplit(_) => "VarSplit", + SetVarSplit(_) => "SetVarSplit", + VarSplitSsa(_) => "VarSplitSsa", + SetVarSplitSsa(_) => "SetVarSplitSsa", + 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", + FcmpE(_) => "FcmpE", + FcmpNe(_) => "FcmpNe", + FcmpLt(_) => "FcmpLt", + FcmpLe(_) => "FcmpLe", + FcmpGe(_) => "FcmpGe", + FcmpGt(_) => "FcmpGt", + FcmpO(_) => "FcmpO", + FcmpUo(_) => "FcmpUo", + Fadd(_) => "Fadd", + Fsub(_) => "Fsub", + Fmul(_) => "Fmul", + Fdiv(_) => "Fdiv", + Adc(_) => "Adc", + Sbb(_) => "Sbb", + Rlc(_) => "Rlc", + Rrc(_) => "Rrc", + Call(_) => "Call", + Tailcall(_) => "Tailcall", + Syscall(_) => "Syscall", + Intrinsic(_) => "Intrinsic", + IntrinsicSsa(_) => "IntrinsicSsa", + CallSsa(_) => "CallSsa", + TailcallSsa(_) => "TailcallSsa", + CallUntypedSsa(_) => "CallUntypedSsa", + TailcallUntypedSsa(_) => "TailcallUntypedSsa", + SyscallSsa(_) => "SyscallSsa", + SyscallUntypedSsa(_) => "SyscallUntypedSsa", + CallUntyped(_) => "CallUntyped", + TailcallUntyped(_) => "TailcallUntyped", + SyscallUntyped(_) => "SyscallUntyped", + SeparateParamList(_) => "SeparateParamList", + SharedParamSlot(_) => "SharedParamSlot", + 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", + Load(_) => "Load", + LoadStruct(_) => "LoadStruct", + LoadStructSsa(_) => "LoadStructSsa", + LoadSsa(_) => "LoadSsa", + Ret(_) => "Ret", + Var(_) => "Var", + AddressOf(_) => "AddressOf", + VarField(_) => "VarField", + AddressOfField(_) => "AddressOfField", + VarSsa(_) => "VarSsa", + VarAliased(_) => "VarAliased", + VarSsaField(_) => "VarSsaField", + VarAliasedField(_) => "VarAliasedField", + Trap(_) => "Trap", + } + } + + pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> { + use MediumLevelILLiftedInstructionKind::*; + use MediumLevelILLiftedOperand as Operand; + match &self.kind { + Nop | Noret | Bp | Undef | Unimpl => vec![], + If(op) => vec![ + ("condition", Operand::Expr(*op.condition.clone())), + ("dest_true", Operand::InstructionIndex(op.dest_true)), + ("dest_false", Operand::InstructionIndex(op.dest_false)), + ], + FloatConst(op) => vec![("constant", Operand::Float(op.constant))], + Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))], + ExternPtr(op) => vec![ + ("constant", Operand::Int(op.constant)), + ("offset", Operand::Int(op.offset)), + ], + ConstData(op) => vec![( + "constant_data", + Operand::ConstantData(op.constant_data.clone()), + )], + Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))], + StoreSsa(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ("src", Operand::Expr(*op.src.clone())), + ], + StoreStructSsa(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("offset", Operand::Int(op.offset)), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ("src", Operand::Expr(*op.src.clone())), + ], + StoreStruct(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("offset", Operand::Int(op.offset)), + ("src", Operand::Expr(*op.src.clone())), + ], + Store(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("src", Operand::Expr(*op.src.clone())), + ], + JumpTo(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("targets", Operand::TargetMap(op.targets.clone())), + ], + Goto(op) => vec![("dest", Operand::InstructionIndex(op.dest))], + FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))], + SetVarField(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("offset", Operand::Int(op.offset)), + ("src", Operand::Expr(*op.src.clone())), + ], + SetVar(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("src", Operand::Expr(*op.src.clone())), + ], + FreeVarSlotSsa(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("prev", Operand::VarSsa(op.prev)), + ], + SetVarSsaField(op) | SetVarAliasedField(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("prev", Operand::VarSsa(op.prev)), + ("offset", Operand::Int(op.offset)), + ("src", Operand::Expr(*op.src.clone())), + ], + SetVarAliased(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("prev", Operand::VarSsa(op.prev)), + ("src", Operand::Expr(*op.src.clone())), + ], + SetVarSsa(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())), + ], + MemPhi(op) => vec![ + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::IntList(op.src_memory.clone())), + ], + VarSplit(op) => vec![ + ("high", Operand::Var(op.high)), + ("low", Operand::Var(op.low)), + ], + SetVarSplit(op) => vec![ + ("high", Operand::Var(op.high)), + ("low", Operand::Var(op.low)), + ("src", Operand::Expr(*op.src.clone())), + ], + VarSplitSsa(op) => vec![ + ("high", Operand::VarSsa(op.high)), + ("low", Operand::VarSsa(op.low)), + ], + SetVarSplitSsa(op) => vec![ + ("high", Operand::VarSsa(op.high)), + ("low", Operand::VarSsa(op.low)), + ("src", Operand::Expr(*op.src.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) | FcmpE(op) + | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op) + | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![ + ("left", Operand::Expr(*op.left.clone())), + ("right", Operand::Expr(*op.right.clone())), + ], + 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())), + ], + Call(op) | Tailcall(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ], + Syscall(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ], + Intrinsic(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("intrinsic", Operand::Intrinsic(op.intrinsic)), + ("params", Operand::ExprList(op.params.clone())), + ], + IntrinsicSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("intrinsic", Operand::Intrinsic(op.intrinsic)), + ("params", Operand::ExprList(op.params.clone())), + ], + CallSsa(op) | TailcallSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + SyscallSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + SyscallUntypedSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + CallUntyped(op) | TailcallUntyped(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + SyscallUntyped(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + 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) | Load(op) => { + vec![("src", Operand::Expr(*op.src.clone()))] + } + LoadStruct(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("offset", Operand::Int(op.offset)), + ], + LoadStructSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("offset", Operand::Int(op.offset)), + ("src_memory", Operand::Int(op.src_memory)), + ], + LoadSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))], + SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))], + SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))], + Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))], + VarField(op) | AddressOfField(op) => vec![ + ("src", Operand::Var(op.src)), + ("offset", Operand::Int(op.offset)), + ], + VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))], + VarSsaField(op) | VarAliasedField(op) => vec![ + ("src", Operand::VarSsa(op.src)), + ("offset", Operand::Int(op.offset)), + ], + Trap(op) => vec![("vector", Operand::Int(op.vector))], + } + } +} |
