Procedure.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #pragma once
  2. #include "BasicBlock.h"
  3. #include "locident.h"
  4. #include "state.h"
  5. #include "icode.h"
  6. #include "StackFrame.h"
  7. #include "CallConvention.h"
  8. #include <QtCore/QString>
  9. #include <bitset>
  10. #include <map>
  11. class QIODevice;
  12. class QTextStream;
  13. /* PROCEDURE NODE */
  14. struct CALL_GRAPH;
  15. struct Expr;
  16. struct Disassembler;
  17. struct Function;
  18. struct CALL_GRAPH;
  19. struct PROG;
  20. struct Function;
  21. /* Procedure FLAGS */
  22. enum PROC_FLAGS
  23. {
  24. PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */
  25. PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
  26. PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
  27. PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
  28. // CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
  29. // CALL_C =0x00004000, /* Proc uses C calling convention */
  30. // CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
  31. PROC_NEAR =0x00010000, /* Proc exits with near return */
  32. PROC_FAR =0x00020000, /* Proc exits with far return */
  33. GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
  34. SI_REGVAR =0x00200000, /* SI is used as a stack variable */
  35. DI_REGVAR =0x00400000, /* DI is used as a stack variable */
  36. PROC_IS_FUNC=0x00800000, /* Proc is a function */
  37. REG_ARGS =0x01000000, /* Proc has registers as arguments */
  38. // PROC_VARARG =0x02000000, /* Proc has variable arguments */
  39. PROC_OUTPUT =0x04000000, /* C for this proc has been output */
  40. PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
  41. PROC_ISLIB =0x10000000, /* Proc is a library function */
  42. PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
  43. PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
  44. //#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
  45. };
  46. struct FunctionType
  47. {
  48. bool m_vararg=false;
  49. bool isVarArg() const {return m_vararg;}
  50. };
  51. struct Assignment
  52. {
  53. Expr *lhs;
  54. Expr *rhs;
  55. };
  56. struct JumpTable
  57. {
  58. uint32_t start;
  59. uint32_t finish;
  60. bool valid() {return start<finish;}
  61. size_t size() { return (finish-start)/2;}
  62. size_t entrySize() { return 2;}
  63. void pruneEntries(uint16_t cs);
  64. };
  65. class FunctionCfg
  66. {
  67. std::list<BB*> m_listBB; /* Ptr. to BB list/CFG */
  68. public:
  69. typedef std::list<BB*>::iterator iterator;
  70. iterator begin() {
  71. return m_listBB.begin();
  72. }
  73. iterator end() {
  74. return m_listBB.end();
  75. }
  76. BB * &front() { return m_listBB.front();}
  77. void nodeSplitting()
  78. {
  79. /* Converts the irreducible graph G into an equivalent reducible one, by
  80. * means of node splitting. */
  81. fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
  82. }
  83. void push_back(BB *v) { m_listBB.push_back(v);}
  84. };
  85. struct Function
  86. {
  87. typedef std::list<BB *> BasicBlockListType;
  88. // BasicBlock iterators...
  89. typedef BasicBlockListType::iterator iterator;
  90. typedef BasicBlockListType::const_iterator const_iterator;
  91. protected:
  92. BasicBlockListType BasicBlocks; ///< The basic blocks
  93. Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
  94. hasCase(false),liveAnal(0)
  95. {
  96. type = new FunctionType;
  97. callingConv(CConv::eUnknown);
  98. }
  99. public:
  100. FunctionType * type;
  101. CConv * m_call_conv;
  102. uint32_t procEntry; /* label number */
  103. QString name; /* Meaningful name for this proc */
  104. STATE state; /* Entry state */
  105. int depth; /* Depth at which we found it - for printing */
  106. uint32_t flg; /* Combination of Icode & Proc flags */
  107. int16_t cbParam; /* Probable no. of bytes of parameters */
  108. STKFRAME args; /* Array of arguments */
  109. LOCAL_ID localId; /* Local identifiers */
  110. ID retVal; /* Return value - identifier */
  111. /* Icodes and control flow graph */
  112. CIcodeRec Icode; /* Object with ICODE records */
  113. FunctionCfg m_actual_cfg;
  114. std::vector<BB*> m_dfsLast;
  115. std::map<int,BB*> m_ip_to_bb;
  116. // * (reverse postorder) order */
  117. size_t numBBs; /* Number of BBs in the graph cfg */
  118. bool hasCase; /* Procedure has a case node */
  119. /* For interprocedural live analysis */
  120. LivenessSet liveIn; /* Registers used before defined */
  121. LivenessSet liveOut; /* Registers that may be used in successors */
  122. bool liveAnal; /* Procedure has been analysed already */
  123. virtual ~Function() {
  124. delete type;
  125. }
  126. public:
  127. static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const QString &nm="",void */*module*/=0)
  128. {
  129. Function *r=new Function(ty);
  130. r->name = nm;
  131. return r;
  132. }
  133. FunctionType *getFunctionType() const {
  134. return type;
  135. }
  136. CConv *callingConv() const { return m_call_conv;}
  137. void callingConv(CConv::Type v);
  138. // bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
  139. bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
  140. bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
  141. void compoundCond();
  142. void writeProcComments();
  143. void lowLevelAnalysis();
  144. void bindIcodeOff();
  145. void dataFlow(LivenessSet &liveOut);
  146. void compressCFG();
  147. void highLevelGen();
  148. void structure(derSeq *derivedG);
  149. derSeq *checkReducibility();
  150. void createCFG();
  151. void markImpure();
  152. void findImmedDom();
  153. void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
  154. void process_operands(ICODE &pIcode, STATE *pstate);
  155. bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
  156. bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
  157. void freeCFG();
  158. void codeGen(QIODevice & fs);
  159. void mergeFallThrough(BB *pBB);
  160. void structIfs();
  161. void structLoops(derSeq *derivedG);
  162. void buildCFG(Disassembler &ds);
  163. void controlFlowAnalysis();
  164. void newRegArg(iICODE picode, iICODE ticode);
  165. void writeProcComments(QTextStream & ostr);
  166. void displayCFG();
  167. void displayStats();
  168. void processHliCall(Expr *exp, iICODE picode);
  169. void preprocessReturnDU(LivenessSet &_liveOut);
  170. Expr * adjustActArgType(Expr *_exp, hlType forType);
  171. QString writeCall(Function *tproc, STKFRAME &args, int *numLoc);
  172. void processDosInt(STATE *pstate, PROG &prog, bool done);
  173. ICODE *translate_DIV(LLInst *ll, ICODE &_Icode);
  174. ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode);
  175. protected:
  176. void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
  177. bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
  178. bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b);
  179. bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
  180. bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
  181. bool Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
  182. bool Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
  183. void replaceInEdge(BB* where, BB* which, BB* with);
  184. void processExpPush(int &numHlIcodes, iICODE picode);
  185. // TODO: replace those with friend visitor ?
  186. void propLongReg(int loc_ident_idx, const ID &pLocId);
  187. void propLongStk(int i, const ID &pLocId);
  188. void propLongGlb(int i, const ID &pLocId);
  189. void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong);
  190. int findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE iter);
  191. int findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg);
  192. void structCases();
  193. void findExps();
  194. void genDU1();
  195. void elimCondCodes();
  196. void liveRegAnalysis(LivenessSet &in_liveOut);
  197. void findIdioms();
  198. void propLong();
  199. void genLiveKtes();
  200. bool findDerivedSeq(derSeq &derivedGi);
  201. bool nextOrderGraph(derSeq &derivedGi);
  202. void addOutEdgesForConditionalJump(BB* pBB, int next_ip, LLInst *ll);
  203. private:
  204. bool decodeIndirectJMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
  205. bool decodeIndirectJMP2(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
  206. };
  207. typedef std::list<Function> FunctionListType;
  208. typedef FunctionListType lFunction;
  209. typedef lFunction::iterator ilFunction;