Add addOutEdgesForConditionalJump to header

This commit is contained in:
nemerle 2016-04-25 10:03:30 +02:00
parent 5963f5fd4d
commit c0e9ba2fb3

View File

@ -1,261 +1,263 @@
#pragma once #pragma once
#include <llvm/ADT/ilist.h> #include <llvm/ADT/ilist.h>
//#include <llvm/ADT/ilist_node.h> //#include <llvm/ADT/ilist_node.h>
#include <bitset> #include <bitset>
#include <map> #include <map>
#include "BasicBlock.h" #include "BasicBlock.h"
#include "locident.h" #include "locident.h"
#include "state.h" #include "state.h"
#include "icode.h" #include "icode.h"
#include "StackFrame.h" #include "StackFrame.h"
#include "CallConvention.h" #include "CallConvention.h"
/* PROCEDURE NODE */ /* PROCEDURE NODE */
struct CALL_GRAPH; struct CALL_GRAPH;
struct Expr; struct Expr;
struct Disassembler; struct Disassembler;
struct Function; struct Function;
struct CALL_GRAPH; struct CALL_GRAPH;
struct PROG; struct PROG;
struct Function; struct Function;
namespace llvm namespace llvm
{ {
// Traits for intrusive list of basic blocks... // Traits for intrusive list of basic blocks...
template<> template<>
struct ilist_traits<BB> : public ilist_default_traits<BB> struct ilist_traits<BB> : public ilist_default_traits<BB>
{ {
// createSentinel is used to get hold of the node that marks the end of the // createSentinel is used to get hold of the node that marks the end of the
// list... (same trick used here as in ilist_traits<Instruction>) // list... (same trick used here as in ilist_traits<Instruction>)
BB *createSentinel() const { BB *createSentinel() const {
return static_cast<BB*>(&Sentinel); return static_cast<BB*>(&Sentinel);
} }
static void destroySentinel(BB*) {} static void destroySentinel(BB*) {}
BB *provideInitialHead() const { return createSentinel(); } BB *provideInitialHead() const { return createSentinel(); }
BB *ensureHead(BB*) const { return createSentinel(); } BB *ensureHead(BB*) const { return createSentinel(); }
static void noteHead(BB*, BB*) {} static void noteHead(BB*, BB*) {}
//static ValueSymbolTable *getSymTab(Function *ItemParent); //static ValueSymbolTable *getSymTab(Function *ItemParent);
private: private:
mutable ilist_half_node<BB> Sentinel; mutable ilist_half_node<BB> Sentinel;
}; };
} }
/* Procedure FLAGS */ /* Procedure FLAGS */
enum PROC_FLAGS enum PROC_FLAGS
{ {
PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */ PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */
PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */ PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */ PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */ PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
// CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */ // CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
// CALL_C =0x00004000, /* Proc uses C calling convention */ // CALL_C =0x00004000, /* Proc uses C calling convention */
// CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */ // CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
PROC_NEAR =0x00010000, /* Proc exits with near return */ PROC_NEAR =0x00010000, /* Proc exits with near return */
PROC_FAR =0x00020000, /* Proc exits with far return */ PROC_FAR =0x00020000, /* Proc exits with far return */
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */ GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
SI_REGVAR =0x00200000, /* SI is used as a stack variable */ SI_REGVAR =0x00200000, /* SI is used as a stack variable */
DI_REGVAR =0x00400000, /* DI is used as a stack variable */ DI_REGVAR =0x00400000, /* DI is used as a stack variable */
PROC_IS_FUNC=0x00800000, /* Proc is a function */ PROC_IS_FUNC=0x00800000, /* Proc is a function */
REG_ARGS =0x01000000, /* Proc has registers as arguments */ REG_ARGS =0x01000000, /* Proc has registers as arguments */
// PROC_VARARG =0x02000000, /* Proc has variable arguments */ // PROC_VARARG =0x02000000, /* Proc has variable arguments */
PROC_OUTPUT =0x04000000, /* C for this proc has been output */ PROC_OUTPUT =0x04000000, /* C for this proc has been output */
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */ PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
PROC_ISLIB =0x10000000, /* Proc is a library function */ PROC_ISLIB =0x10000000, /* Proc is a library function */
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */ PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */ PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */ //#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
}; };
struct FunctionType struct FunctionType
{ {
bool m_vararg=false; bool m_vararg=false;
bool isVarArg() const {return m_vararg;} bool isVarArg() const {return m_vararg;}
}; };
struct Assignment struct Assignment
{ {
Expr *lhs; Expr *lhs;
Expr *rhs; Expr *rhs;
}; };
struct JumpTable struct JumpTable
{ {
uint32_t start; uint32_t start;
uint32_t finish; uint32_t finish;
bool valid() {return start<finish;} bool valid() {return start<finish;}
size_t size() { return (finish-start)/2;} size_t size() { return (finish-start)/2;}
size_t entrySize() { return 2;} size_t entrySize() { return 2;}
void pruneEntries(uint16_t cs); void pruneEntries(uint16_t cs);
}; };
class FunctionCfg class FunctionCfg
{ {
std::list<BB*> m_listBB; /* Ptr. to BB list/CFG */ std::list<BB*> m_listBB; /* Ptr. to BB list/CFG */
public: public:
typedef std::list<BB*>::iterator iterator; typedef std::list<BB*>::iterator iterator;
iterator begin() { iterator begin() {
return m_listBB.begin(); return m_listBB.begin();
} }
iterator end() { iterator end() {
return m_listBB.end(); return m_listBB.end();
} }
BB * &front() { return m_listBB.front();} BB * &front() { return m_listBB.front();}
void nodeSplitting() void nodeSplitting()
{ {
/* Converts the irreducible graph G into an equivalent reducible one, by /* Converts the irreducible graph G into an equivalent reducible one, by
* means of node splitting. */ * means of node splitting. */
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n"); fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
} }
void push_back(BB *v) { m_listBB.push_back(v);} void push_back(BB *v) { m_listBB.push_back(v);}
}; };
struct Function : public llvm::ilist_node<Function> struct Function : public llvm::ilist_node<Function>
{ {
typedef llvm::iplist<BB> BasicBlockListType; typedef llvm::iplist<BB> BasicBlockListType;
// BasicBlock iterators... // BasicBlock iterators...
typedef BasicBlockListType::iterator iterator; typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator; typedef BasicBlockListType::const_iterator const_iterator;
protected: protected:
BasicBlockListType BasicBlocks; ///< The basic blocks BasicBlockListType BasicBlocks; ///< The basic blocks
Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0), Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
hasCase(false),liveAnal(0) hasCase(false),liveAnal(0)
{ {
type = new FunctionType; type = new FunctionType;
callingConv(CConv::UNKNOWN); callingConv(CConv::UNKNOWN);
} }
public: public:
FunctionType * type; FunctionType * type;
CConv * m_call_conv; CConv * m_call_conv;
uint32_t procEntry; /* label number */ uint32_t procEntry; /* label number */
std::string name; /* Meaningful name for this proc */ std::string name; /* Meaningful name for this proc */
STATE state; /* Entry state */ STATE state; /* Entry state */
int depth; /* Depth at which we found it - for printing */ int depth; /* Depth at which we found it - for printing */
uint32_t flg; /* Combination of Icode & Proc flags */ uint32_t flg; /* Combination of Icode & Proc flags */
int16_t cbParam; /* Probable no. of bytes of parameters */ int16_t cbParam; /* Probable no. of bytes of parameters */
STKFRAME args; /* Array of arguments */ STKFRAME args; /* Array of arguments */
LOCAL_ID localId; /* Local identifiers */ LOCAL_ID localId; /* Local identifiers */
ID retVal; /* Return value - identifier */ ID retVal; /* Return value - identifier */
/* Icodes and control flow graph */ /* Icodes and control flow graph */
CIcodeRec Icode; /* Object with ICODE records */ CIcodeRec Icode; /* Object with ICODE records */
FunctionCfg m_actual_cfg; FunctionCfg m_actual_cfg;
std::vector<BB*> m_dfsLast; std::vector<BB*> m_dfsLast;
std::map<int,BB*> m_ip_to_bb; std::map<int,BB*> m_ip_to_bb;
// * (reverse postorder) order */ // * (reverse postorder) order */
size_t numBBs; /* Number of BBs in the graph cfg */ size_t numBBs; /* Number of BBs in the graph cfg */
bool hasCase; /* Procedure has a case node */ bool hasCase; /* Procedure has a case node */
/* For interprocedural live analysis */ /* For interprocedural live analysis */
LivenessSet liveIn; /* Registers used before defined */ LivenessSet liveIn; /* Registers used before defined */
LivenessSet liveOut; /* Registers that may be used in successors */ LivenessSet liveOut; /* Registers that may be used in successors */
bool liveAnal; /* Procedure has been analysed already */ bool liveAnal; /* Procedure has been analysed already */
virtual ~Function() { virtual ~Function() {
delete type; delete type;
} }
public: public:
static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const std::string &nm="",void */*module*/=0) static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const std::string &nm="",void */*module*/=0)
{ {
Function *r=new Function(ty); Function *r=new Function(ty);
r->name = nm; r->name = nm;
return r; return r;
} }
FunctionType *getFunctionType() const { FunctionType *getFunctionType() const {
return type; return type;
} }
CConv *callingConv() const { return m_call_conv;} CConv *callingConv() const { return m_call_conv;}
void callingConv(CConv::Type v); void callingConv(CConv::Type v);
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;} // bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;} bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;} bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
void compoundCond(); void compoundCond();
void writeProcComments(); void writeProcComments();
void lowLevelAnalysis(); void lowLevelAnalysis();
void bindIcodeOff(); void bindIcodeOff();
void dataFlow(LivenessSet &liveOut); void dataFlow(LivenessSet &liveOut);
void compressCFG(); void compressCFG();
void highLevelGen(); void highLevelGen();
void structure(derSeq *derivedG); void structure(derSeq *derivedG);
derSeq *checkReducibility(); derSeq *checkReducibility();
void createCFG(); void createCFG();
void markImpure(); void markImpure();
void findImmedDom(); void findImmedDom();
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate); void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
void process_operands(ICODE &pIcode, STATE *pstate); void process_operands(ICODE &pIcode, STATE *pstate);
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph); bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate); bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
void freeCFG(); void freeCFG();
void codeGen(std::ostream &fs); void codeGen(std::ostream &fs);
void mergeFallThrough(BB *pBB); void mergeFallThrough(BB *pBB);
void structIfs(); void structIfs();
void structLoops(derSeq *derivedG); void structLoops(derSeq *derivedG);
void buildCFG(Disassembler &ds); void buildCFG(Disassembler &ds);
void controlFlowAnalysis(); void controlFlowAnalysis();
void newRegArg(iICODE picode, iICODE ticode); void newRegArg(iICODE picode, iICODE ticode);
void writeProcComments(std::ostream &ostr); void writeProcComments(std::ostream &ostr);
void displayCFG(); void displayCFG();
void displayStats(); void displayStats();
void processHliCall(Expr *exp, iICODE picode); void processHliCall(Expr *exp, iICODE picode);
void preprocessReturnDU(LivenessSet &_liveOut); void preprocessReturnDU(LivenessSet &_liveOut);
Expr * adjustActArgType(Expr *_exp, hlType forType); Expr * adjustActArgType(Expr *_exp, hlType forType);
std::string writeCall(Function *tproc, STKFRAME &args, int *numLoc); std::string writeCall(Function *tproc, STKFRAME &args, int *numLoc);
void processDosInt(STATE *pstate, PROG &prog, bool done); void processDosInt(STATE *pstate, PROG &prog, bool done);
ICODE *translate_DIV(LLInst *ll, ICODE &_Icode); ICODE *translate_DIV(LLInst *ll, ICODE &_Icode);
ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode); ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode);
protected: protected:
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table); void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate); bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b); bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b);
bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB); bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB); bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
bool Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB); bool Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
bool Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB); bool Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
void replaceInEdge(BB* where, BB* which, BB* with); void replaceInEdge(BB* where, BB* which, BB* with);
void processExpPush(int &numHlIcodes, iICODE picode); void processExpPush(int &numHlIcodes, iICODE picode);
// TODO: replace those with friend visitor ? // TODO: replace those with friend visitor ?
void propLongReg(int loc_ident_idx, const ID &pLocId); void propLongReg(int loc_ident_idx, const ID &pLocId);
void propLongStk(int i, const ID &pLocId); void propLongStk(int i, const ID &pLocId);
void propLongGlb(int i, const ID &pLocId); void propLongGlb(int i, const ID &pLocId);
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong); void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong);
int findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE iter); int findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE iter);
int findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg); int findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg);
void structCases(); void structCases();
void findExps(); void findExps();
void genDU1(); void genDU1();
void elimCondCodes(); void elimCondCodes();
void liveRegAnalysis(LivenessSet &in_liveOut); void liveRegAnalysis(LivenessSet &in_liveOut);
void findIdioms(); void findIdioms();
void propLong(); void propLong();
void genLiveKtes(); void genLiveKtes();
bool findDerivedSeq(derSeq &derivedGi); bool findDerivedSeq(derSeq &derivedGi);
bool nextOrderGraph(derSeq &derivedGi); bool nextOrderGraph(derSeq &derivedGi);
private: void addOutEdgesForConditionalJump(BB* pBB, int next_ip, LLInst *ll);
bool decodeIndirectJMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
bool decodeIndirectJMP2(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph); private:
}; bool decodeIndirectJMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
namespace llvm { bool decodeIndirectJMP2(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
template<> struct ilist_traits<typename ::Function> };
: public ilist_default_traits<typename ::Function> { namespace llvm {
template<> struct ilist_traits<typename ::Function>
// createSentinel is used to get hold of the node that marks the end of the : public ilist_default_traits<typename ::Function> {
// list... (same trick used here as in ilist_traits<Instruction>)
typename ::Function *createSentinel() const { // createSentinel is used to get hold of the node that marks the end of the
return static_cast<typename ::Function*>(&Sentinel); // list... (same trick used here as in ilist_traits<Instruction>)
} typename ::Function *createSentinel() const {
static void destroySentinel(typename ::Function*) {} return static_cast<typename ::Function*>(&Sentinel);
}
typename ::Function *provideInitialHead() const { return createSentinel(); } static void destroySentinel(typename ::Function*) {}
typename ::Function *ensureHead(::Function*) const { return createSentinel(); }
static void noteHead(typename ::Function*, typename ::Function*) {} typename ::Function *provideInitialHead() const { return createSentinel(); }
typename ::Function *ensureHead(::Function*) const { return createSentinel(); }
private: static void noteHead(typename ::Function*, typename ::Function*) {}
mutable ilist_node<typename ::Function> Sentinel;
}; private:
} mutable ilist_node<typename ::Function> Sentinel;
typedef llvm::iplist<Function> FunctionListType; };
typedef FunctionListType lFunction; }
typedef lFunction::iterator ilFunction; typedef llvm::iplist<Function> FunctionListType;
typedef FunctionListType lFunction;
typedef lFunction::iterator ilFunction;