Orignal dcc code
Only 2 differences with original release: add return type to main int disassem.cpp popPosStack() add cast to intptr_t
This commit is contained in:
parent
9cc5202ff7
commit
2a59d07ef2
@ -1,7 +1,7 @@
|
||||
PROJECT(dcc_original)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
OPTION(dcc_build_tests "Enable unit tests." OFF)
|
||||
#OPTION(dcc_build_tests "Enable unit tests." OFF)
|
||||
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS)
|
||||
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||
@ -14,25 +14,24 @@ ENDIF()
|
||||
|
||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
||||
|
||||
FIND_PACKAGE(LLVM)
|
||||
FIND_PACKAGE(Boost)
|
||||
IF(dcc_build_tests)
|
||||
FIND_PACKAGE(GMock)
|
||||
ENDIF()
|
||||
#FIND_PACKAGE(LLVM)
|
||||
#FIND_PACKAGE(Boost)
|
||||
#IF(dcc_build_tests)
|
||||
# FIND_PACKAGE(GMock)
|
||||
#ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY(3rd_party)
|
||||
#ADD_SUBDIRECTORY(3rd_party)
|
||||
|
||||
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support)
|
||||
#llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support)
|
||||
INCLUDE_DIRECTORIES(
|
||||
3rd_party/libdisasm
|
||||
# 3rd_party/libdisasm
|
||||
include
|
||||
include/idioms
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
# include/idioms
|
||||
# ${Boost_INCLUDE_DIRS}
|
||||
# ${LLVM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
src/ast.cpp
|
||||
src/backend.cpp
|
||||
src/bundle.cpp
|
||||
@ -40,75 +39,47 @@ set(dcc_SOURCES
|
||||
src/comwrite.cpp
|
||||
src/control.cpp
|
||||
src/dataflow.cpp
|
||||
src/dcc.cpp
|
||||
src/disassem.cpp
|
||||
src/error.cpp
|
||||
src/fixwild.cpp
|
||||
src/frontend.cpp
|
||||
src/graph.cpp
|
||||
src/hlicode.cpp
|
||||
src/machine_x86.cpp
|
||||
src/icode.cpp
|
||||
src/idioms.cpp
|
||||
src/idioms/idiom1.cpp
|
||||
src/idioms/arith_idioms.cpp
|
||||
src/idioms/call_idioms.cpp
|
||||
src/idioms/epilogue_idioms.cpp
|
||||
src/idioms/mov_idioms.cpp
|
||||
src/idioms/neg_idioms.cpp
|
||||
src/idioms/shift_idioms.cpp
|
||||
src/idioms/xor_idioms.cpp
|
||||
src/locident.cpp
|
||||
src/parser.cpp
|
||||
src/perfhlib.cpp
|
||||
src/procs.cpp
|
||||
src/project.cpp
|
||||
src/Procedure.cpp
|
||||
src/proplong.cpp
|
||||
src/reducible.cpp
|
||||
src/scanner.cpp
|
||||
src/symtab.cpp
|
||||
src/udm.cpp
|
||||
src/BasicBlock.cpp
|
||||
)
|
||||
set(dcc_HEADERS
|
||||
include/ast.h
|
||||
include/bundle.h
|
||||
include/BinaryImage.h
|
||||
include/dcc.h
|
||||
include/disassem.h
|
||||
include/dosdcc.h
|
||||
include/error.h
|
||||
include/graph.h
|
||||
include/hlicode.h
|
||||
include/machine_x86.h
|
||||
include/icode.h
|
||||
include/idioms/idiom.h
|
||||
include/idioms/idiom1.h
|
||||
include/idioms/arith_idioms.h
|
||||
include/idioms/call_idioms.h
|
||||
include/idioms/epilogue_idioms.h
|
||||
include/idioms/mov_idioms.h
|
||||
include/idioms/neg_idioms.h
|
||||
include/idioms/shift_idioms.h
|
||||
include/idioms/xor_idioms.h
|
||||
include/locident.h
|
||||
include/perfhlib.h
|
||||
include/project.h
|
||||
include/scanner.h
|
||||
include/state.h
|
||||
include/symtab.h
|
||||
include/types.h
|
||||
include/Procedure.h
|
||||
include/StackFrame.h
|
||||
include/BasicBlock.h
|
||||
)
|
||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
||||
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
||||
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||
TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
|
||||
if(dcc_build_tests)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
endif()
|
||||
|
||||
|
||||
#TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
|
||||
#if(dcc_build_tests)
|
||||
#ADD_SUBDIRECTORY(src)
|
||||
#endif()
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <boost/range.hpp>
|
||||
#include "icode.h"
|
||||
#include "types.h"
|
||||
#include "graph.h"
|
||||
//#include "icode.h"
|
||||
/* Basic block (BB) node definition */
|
||||
struct Function;
|
||||
class CIcodeRec;
|
||||
struct BB;
|
||||
struct LOCAL_ID;
|
||||
struct interval;
|
||||
|
||||
struct TYPEADR_TYPE
|
||||
{
|
||||
uint32_t ip; /* Out edge icode address */
|
||||
BB * BBptr; /* Out edge pointer to next BB */
|
||||
interval *intPtr; /* Out edge ptr to next interval*/
|
||||
};
|
||||
|
||||
struct BB : public llvm::ilist_node<BB>
|
||||
{
|
||||
private:
|
||||
BB(const BB&);
|
||||
BB() : nodeType(0),traversed(DFS_NONE),
|
||||
numHlIcodes(0),flg(0),
|
||||
inEdges(0),
|
||||
edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0),
|
||||
inInterval(0),correspInt(0),liveUse(0),def(0),liveIn(0),liveOut(0),
|
||||
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(0),latchNode(0),
|
||||
numBackEdges(0),loopHead(0),loopFollow(0),caseHead(0),caseTail(0),index(0)
|
||||
{
|
||||
|
||||
}
|
||||
//friend class SymbolTableListTraits<BB, Function>;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
rCODE instructions;
|
||||
|
||||
public:
|
||||
struct ValidFunctor
|
||||
{
|
||||
bool operator()(BB *p) {return p->valid();}
|
||||
};
|
||||
iICODE begin();
|
||||
iICODE end() const;
|
||||
riICODE rbegin();
|
||||
riICODE rend();
|
||||
ICODE &front();
|
||||
ICODE &back();
|
||||
size_t size();
|
||||
uint8_t nodeType; /* Type of node */
|
||||
eDFS traversed; /* last traversal id is held here traversed yet? */
|
||||
int numHlIcodes; /* No. of high-level icodes */
|
||||
uint32_t flg; /* BB flags */
|
||||
|
||||
/* In edges and out edges */
|
||||
std::vector<BB *> inEdges; // does not own held pointers
|
||||
|
||||
//int numOutEdges; /* Number of out edges */
|
||||
std::vector<TYPEADR_TYPE> edges;/* Array of ptrs. to out edges */
|
||||
|
||||
/* For interval construction */
|
||||
int beenOnH; /* #times been on header list H */
|
||||
int inEdgeCount; /* #inEdges (to find intervals) */
|
||||
BB * reachingInt; /* Reaching interval header */
|
||||
interval *inInterval; /* Node's interval */
|
||||
|
||||
/* For derived sequence construction */
|
||||
interval *correspInt; /* Corresponding interval in
|
||||
* derived graph Gi-1 */
|
||||
|
||||
/* For live register analysis
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
std::bitset<32> liveUse; /* LiveUse(b) */
|
||||
std::bitset<32> def; /* Def(b) */
|
||||
std::bitset<32> liveIn; /* LiveIn(b) */
|
||||
std::bitset<32> liveOut; /* LiveOut(b) */
|
||||
|
||||
/* For structuring analysis */
|
||||
int dfsFirstNum; /* DFS #: first visit of node */
|
||||
int dfsLastNum; /* DFS #: last visit of node */
|
||||
int immedDom; /* Immediate dominator (dfsLast
|
||||
* index) */
|
||||
int ifFollow; /* node that ends the if */
|
||||
int loopType; /* Type of loop (if any) */
|
||||
int latchNode; /* latching node of the loop */
|
||||
int numBackEdges; /* # of back edges */
|
||||
int loopHead; /* most nested loop head to which
|
||||
* thcis node belongs (dfsLast) */
|
||||
int loopFollow; /* node that follows the loop */
|
||||
int caseHead; /* most nested case to which this
|
||||
node belongs (dfsLast) */
|
||||
int caseTail; /* tail node for the case */
|
||||
|
||||
int index; /* Index, used in several ways */
|
||||
static BB * Create(void *ctx=0,const std::string &s="",Function *parent=0,BB *insertBefore=0);
|
||||
static BB * Create(int start, int ip, uint8_t nodeType, int numOutEdges, Function * parent);
|
||||
static BB * Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent);
|
||||
void writeCode(int indLevel, Function *pProc, int *numLoc, int latchNode, int ifFollow);
|
||||
void mergeFallThrough(CIcodeRec &Icode);
|
||||
void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last);
|
||||
void displayDfs();
|
||||
void display();
|
||||
/// getParent - Return the enclosing method, or null if none
|
||||
///
|
||||
const Function *getParent() const { return Parent; }
|
||||
Function *getParent() { return Parent; }
|
||||
void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc);
|
||||
BB * rmJMP(int marker, BB *pBB);
|
||||
void genDU1();
|
||||
int findBBExps(LOCAL_ID &locals, Function *f);
|
||||
bool valid() {return 0==(flg & INVALID_BB); }
|
||||
bool wasTraversedAtLevel(int l) const {return traversed==l;}
|
||||
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond);
|
||||
void addOutEdge(uint32_t ip) // TODO: fix this
|
||||
{
|
||||
edges[0].ip = ip;
|
||||
}
|
||||
void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
|
||||
private:
|
||||
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);
|
||||
void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode);
|
||||
bool isEndOfPath(int latch_node_idx) const;
|
||||
Function *Parent;
|
||||
|
||||
};
|
||||
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
struct PROG /* Loaded program image parameters */
|
||||
{
|
||||
int16_t initCS;
|
||||
int16_t initIP; /* These are initial load values */
|
||||
int16_t initSS; /* Probably not of great interest */
|
||||
uint16_t initSP;
|
||||
bool fCOM; /* Flag set if COM program (else EXE)*/
|
||||
int cReloc; /* No. of relocation table entries */
|
||||
uint32_t * relocTable; /* Ptr. to relocation table */
|
||||
uint8_t * map; /* Memory bitmap ptr */
|
||||
int cProcs; /* Number of procedures so far */
|
||||
int offMain; /* The offset of the main() proc */
|
||||
uint16_t segMain; /* The segment of the main() proc */
|
||||
bool bSigs; /* True if signatures loaded */
|
||||
int cbImage; /* Length of image in bytes */
|
||||
uint8_t * Image; /* Allocated by loader to hold entire program image */
|
||||
};
|
||||
|
||||
283
include/Enums.h
283
include/Enums.h
@ -1,283 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/* Register types */
|
||||
enum regType
|
||||
{
|
||||
BYTE_REG,
|
||||
WORD_REG
|
||||
};
|
||||
enum condId
|
||||
{
|
||||
GLOB_VAR, /* global variable */
|
||||
REGISTER, /* register */
|
||||
LOCAL_VAR, /* negative disp */
|
||||
PARAM, /* positive disp */
|
||||
GLOB_VAR_IDX, /* indexed global variable *//*** should merge w/glob-var*/
|
||||
CONSTANT, /* constant */
|
||||
STRING, /* string */
|
||||
LONG_VAR, /* long variable */
|
||||
FUNCTION, /* function */
|
||||
OTHER /* other **** tmp solution */
|
||||
};
|
||||
|
||||
enum condOp
|
||||
{
|
||||
/* For conditional expressions */
|
||||
LESS_EQUAL, /* <= */
|
||||
LESS, /* < */
|
||||
EQUAL, /* == */
|
||||
NOT_EQUAL, /* != */
|
||||
GREATER, /* > */
|
||||
GREATER_EQUAL, /* >= */
|
||||
/* For general expressions */
|
||||
AND, /* & */
|
||||
OR, /* | */
|
||||
XOR, /* ^ */
|
||||
NOT, /* ~ */ /* 1's complement */
|
||||
ADD, /* + */
|
||||
SUB, /* - */
|
||||
MUL, /* * */
|
||||
DIV, /* / */
|
||||
SHR, /* >> */
|
||||
SHL, /* << */
|
||||
MOD, /* % */
|
||||
DBL_AND, /* && */
|
||||
DBL_OR, /* || */
|
||||
DUMMY /* */
|
||||
};
|
||||
/* LOW_LEVEL operand location: source or destination */
|
||||
enum opLoc
|
||||
{
|
||||
SRC, /* Source operand */
|
||||
DST, /* Destination operand */
|
||||
LHS_OP /* Left-hand side operand (for HIGH_LEVEL) */
|
||||
};
|
||||
/* LOW_LEVEL icode flags */
|
||||
#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */
|
||||
enum eLLFlags
|
||||
{
|
||||
|
||||
B =0x0000001, /* uint8_t operands (value implicitly used) */
|
||||
I =0x0000002, /* Immed. source */
|
||||
NOT_HLL =0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP =0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED =0x0000010, /* Number is relocated segment value */
|
||||
IMPURE =0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF =0x0000040, /* Inst has uint16_t offset ie.could be address */
|
||||
TERMINATES =0x0000080, /* Instruction terminates program */
|
||||
CASE =0x0000100, /* Label as case part of switch */
|
||||
SWITCH =0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET =0x0000400, /* Jump target */
|
||||
SYNTHETIC =0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL =0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE =0x0002000, /* Hole in Icode array */
|
||||
SYM_USE =0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF =0x0008000, /* Instruction defines a symbol */
|
||||
NO_SRC =0x0010000, /* Opcode takes no source */
|
||||
NO_OPS =0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS =0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B =0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
|
||||
HLL_LABEL =0x0100000, /* Icode has a high level language label */
|
||||
IM_DST =0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC =0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST =0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
JMP_ICODE =0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP =0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK =0x4000000 /* Stack needs to be restored after CALL */
|
||||
#define ICODEMASK 0x0FF00FF /* Masks off parser flags */
|
||||
};
|
||||
/* Types of icodes */
|
||||
enum icodeType
|
||||
{
|
||||
NOT_SCANNED = 0, // not even scanned yet
|
||||
LOW_LEVEL, // low-level icode
|
||||
HIGH_LEVEL // high-level icode
|
||||
};
|
||||
|
||||
|
||||
/* LOW_LEVEL icode opcodes */
|
||||
enum llIcode
|
||||
{
|
||||
//iINVALID,
|
||||
iCBW, /* 0 */
|
||||
iAAA,
|
||||
iAAD,
|
||||
iAAM,
|
||||
iAAS,
|
||||
iADC,
|
||||
iADD,
|
||||
iAND,
|
||||
iBOUND,
|
||||
iCALL,
|
||||
iCALLF, /* 10 */
|
||||
iCLC,
|
||||
iCLD,
|
||||
iCLI,
|
||||
iCMC,
|
||||
iCMP,
|
||||
iCMPS,
|
||||
iREPNE_CMPS,
|
||||
iREPE_CMPS,
|
||||
iDAA,
|
||||
iDAS, /* 20 */
|
||||
iDEC,
|
||||
iDIV,
|
||||
iENTER,
|
||||
iESC,
|
||||
iHLT,
|
||||
iIDIV,
|
||||
iIMUL,
|
||||
iIN,
|
||||
iINC,
|
||||
iINS, /* 30 */
|
||||
iREP_INS,
|
||||
iINT,
|
||||
iIRET,
|
||||
iJB,
|
||||
iJBE,
|
||||
iJAE,
|
||||
iJA,
|
||||
iJE,
|
||||
iJNE,
|
||||
iJL, /* 40 */
|
||||
iJGE,
|
||||
iJLE,
|
||||
iJG,
|
||||
iJS,
|
||||
iJNS,
|
||||
iJO,
|
||||
iJNO,
|
||||
iJP,
|
||||
iJNP,
|
||||
iJCXZ, /* 50 */
|
||||
iJMP,
|
||||
iJMPF,
|
||||
iLAHF,
|
||||
iLDS,
|
||||
iLEA,
|
||||
iLEAVE,
|
||||
iLES,
|
||||
iLOCK,
|
||||
iLODS,
|
||||
iREP_LODS, /* 60 */
|
||||
iLOOP,
|
||||
iLOOPE,
|
||||
iLOOPNE,
|
||||
iMOV, /* 64 */
|
||||
iMOVS,
|
||||
iREP_MOVS,
|
||||
iMUL, /* 67 */
|
||||
iNEG,
|
||||
iNOT,
|
||||
iOR, /* 70 */
|
||||
iOUT,
|
||||
iOUTS,
|
||||
iREP_OUTS,
|
||||
iPOP,
|
||||
iPOPA,
|
||||
iPOPF,
|
||||
iPUSH,
|
||||
iPUSHA,
|
||||
iPUSHF,
|
||||
iRCL, /* 80 */
|
||||
iRCR,
|
||||
iROL,
|
||||
iROR,
|
||||
iRET, /* 84 */
|
||||
iRETF,
|
||||
iSAHF,
|
||||
iSAR,
|
||||
iSHL,
|
||||
iSHR,
|
||||
iSBB, /* 90 */
|
||||
iSCAS,
|
||||
iREPNE_SCAS,
|
||||
iREPE_SCAS,
|
||||
iSIGNEX,
|
||||
iSTC,
|
||||
iSTD,
|
||||
iSTI,
|
||||
iSTOS,
|
||||
iREP_STOS,
|
||||
iSUB, /* 100 */
|
||||
iTEST,
|
||||
iWAIT,
|
||||
iXCHG,
|
||||
iXLAT,
|
||||
iXOR,
|
||||
iINTO,
|
||||
iNOP,
|
||||
iREPNE,
|
||||
iREPE,
|
||||
iMOD /* 110 */
|
||||
};
|
||||
/* Conditional Expression enumeration nodes and operators */
|
||||
enum condNodeType
|
||||
{
|
||||
UNKNOWN_OP=0,
|
||||
BOOLEAN_OP, /* condOps */
|
||||
NEGATION, /* not (2's complement) */
|
||||
ADDRESSOF, /* addressOf (&) */
|
||||
DEREFERENCE, /* contents of (*) */
|
||||
IDENTIFIER, /* {register | local | param | constant | global} */
|
||||
/* The following are only available to C programs */
|
||||
POST_INC, /* ++ (post increment) */
|
||||
POST_DEC, /* -- (post decrement) */
|
||||
PRE_INC, /* ++ (pre increment) */
|
||||
PRE_DEC /* -- (pre decrement) */
|
||||
} ;
|
||||
|
||||
/* Enumeration to determine whether pIcode points to the high or low part
|
||||
* of a long number */
|
||||
enum hlFirst
|
||||
{
|
||||
HIGH_FIRST, /* High value is first */
|
||||
LOW_FIRST /* Low value is first */
|
||||
};
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
enum hlIcode
|
||||
{
|
||||
HLI_INVALID,
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
HLI_RET, /* Return from procedure */
|
||||
/* pseudo high-level icodes */
|
||||
HLI_POP, /* Pop expression */
|
||||
HLI_PUSH /* Push expression */
|
||||
} ;
|
||||
/* Type definitions used in the decompiled program */
|
||||
enum hlType
|
||||
{
|
||||
TYPE_UNKNOWN = 0, /* unknown so far */
|
||||
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
|
||||
TYPE_BYTE_UNSIGN, /* unsigned byte */
|
||||
TYPE_WORD_SIGN, /* signed word (16 bits) */
|
||||
TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */
|
||||
TYPE_LONG_SIGN, /* signed long (32 bits) */
|
||||
TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */
|
||||
TYPE_RECORD, /* record structure */
|
||||
TYPE_PTR, /* pointer (32 bit ptr) */
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE /* double precision float */
|
||||
};
|
||||
|
||||
/* Operand is defined, used or both flag */
|
||||
enum operDu
|
||||
{
|
||||
eDEF=0x10, /* Operand is defined */
|
||||
eUSE=0x100, /* Operand is used */
|
||||
USE_DEF, /* Operand is used and defined */
|
||||
NONE /* No operation is required on this operand */
|
||||
};
|
||||
|
||||
/* LOW_LEVEL icode, DU flag bits */
|
||||
enum eDuFlags
|
||||
{
|
||||
Cf=1,
|
||||
Sf=2,
|
||||
Zf=4,
|
||||
Df=8
|
||||
};
|
||||
@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#include "ast.h"
|
||||
#include "types.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
struct IDENTTYPE
|
||||
{
|
||||
condId idType;
|
||||
regType regiType; /* for REGISTER only */
|
||||
union _idNode {
|
||||
int regiIdx; /* index into localId, REGISTER */
|
||||
int globIdx; /* index into symtab for GLOB_VAR */
|
||||
int localIdx; /* idx into localId, LOCAL_VAR */
|
||||
int paramIdx; /* idx into args symtab, PARAMS */
|
||||
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
struct _kte
|
||||
{ /* for CONSTANT only */
|
||||
uint32_t kte; /* value of the constant */
|
||||
uint8_t size; /* #bytes size constant */
|
||||
} kte;
|
||||
uint32_t strIdx; /* idx into image, for STRING */
|
||||
int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/
|
||||
struct _call { /* for FUNCTION only */
|
||||
Function *proc;
|
||||
STKFRAME *args;
|
||||
} call;
|
||||
struct { /* for OTHER; tmp struct */
|
||||
eReg seg; /* segment */
|
||||
eReg regi; /* index mode */
|
||||
int16_t off; /* offset */
|
||||
} other;
|
||||
} idNode;
|
||||
};
|
||||
@ -1,199 +0,0 @@
|
||||
#pragma once
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <bitset>
|
||||
#include "BasicBlock.h"
|
||||
#include "locident.h"
|
||||
#include "state.h"
|
||||
#include "icode.h"
|
||||
#include "StackFrame.h"
|
||||
/* PROCEDURE NODE */
|
||||
struct CALL_GRAPH;
|
||||
struct COND_EXPR;
|
||||
struct Disassembler;
|
||||
struct Function;
|
||||
struct CALL_GRAPH;
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
// Traits for intrusive list of basic blocks...
|
||||
template<>
|
||||
struct ilist_traits<BB> : public ilist_default_traits<BB>
|
||||
{
|
||||
|
||||
// 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>)
|
||||
BB *createSentinel() const {
|
||||
return static_cast<BB*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(BB*) {}
|
||||
|
||||
BB *provideInitialHead() const { return createSentinel(); }
|
||||
BB *ensureHead(BB*) const { return createSentinel(); }
|
||||
static void noteHead(BB*, BB*) {}
|
||||
|
||||
//static ValueSymbolTable *getSymTab(Function *ItemParent);
|
||||
private:
|
||||
mutable ilist_half_node<BB> Sentinel;
|
||||
};
|
||||
}
|
||||
/* Procedure FLAGS */
|
||||
enum PROC_FLAGS
|
||||
{
|
||||
PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */
|
||||
PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
|
||||
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
|
||||
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
|
||||
CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
|
||||
CALL_C =0x00004000, /* Proc uses C calling convention */
|
||||
CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
|
||||
PROC_NEAR =0x00010000, /* Proc exits with near return */
|
||||
PROC_FAR =0x00020000, /* Proc exits with far return */
|
||||
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
|
||||
SI_REGVAR =0x00200000, /* SI is used as a stack variable */
|
||||
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
|
||||
PROC_IS_FUNC=0x00800000, /* Proc is a function */
|
||||
REG_ARGS =0x01000000, /* Proc has registers as arguments */
|
||||
PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
|
||||
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
|
||||
PROC_ISLIB =0x10000000, /* Proc is a library function */
|
||||
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
|
||||
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
|
||||
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
};
|
||||
|
||||
struct FunctionType
|
||||
{
|
||||
bool m_vararg;
|
||||
bool isVarArg() const {return m_vararg;}
|
||||
};
|
||||
struct Assignment
|
||||
{
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
};
|
||||
struct JumpTable
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t finish;
|
||||
bool valid() {return start<finish;}
|
||||
size_t size() { return (finish-start)/2;}
|
||||
size_t entrySize() { return 2;}
|
||||
void pruneEntries(uint16_t cs);
|
||||
};
|
||||
|
||||
struct Function : public llvm::ilist_node<Function>
|
||||
{
|
||||
typedef llvm::iplist<BB> BasicBlockListType;
|
||||
// BasicBlock iterators...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
typedef BasicBlockListType::const_iterator const_iterator;
|
||||
private:
|
||||
BasicBlockListType BasicBlocks; ///< The basic blocks
|
||||
|
||||
public:
|
||||
uint32_t procEntry; /* label number */
|
||||
std::string name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
int depth; /* Depth at which we found it - for printing */
|
||||
uint32_t flg; /* Combination of Icode & Proc flags */
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
std::list<BB*> m_cfg; /* Ptr. to BB list/CFG */
|
||||
std::vector<BB*> m_dfsLast;
|
||||
std::list<BB*> heldBBs;
|
||||
//BB * *dfsLast; /* Array of pointers to BBs in dfsLast
|
||||
// * (reverse postorder) order */
|
||||
size_t numBBs; /* Number of BBs in the graph cfg */
|
||||
bool hasCase; /* Procedure has a case node */
|
||||
|
||||
/* For interprocedural live analysis */
|
||||
std::bitset<32> liveIn; /* Registers used before defined */
|
||||
std::bitset<32> liveOut; /* Registers that may be used in successors */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
Function(void *ty=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
static Function *Create(void *ty=0,int Linkage=0,const std::string &nm="",void *module=0)
|
||||
{
|
||||
Function *r=new Function(ty);
|
||||
r->name = nm;
|
||||
return r;
|
||||
}
|
||||
bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
||||
void compoundCond();
|
||||
void writeProcComments();
|
||||
void lowLevelAnalysis();
|
||||
void bindIcodeOff();
|
||||
void dataFlow(std::bitset<32> &liveOut);
|
||||
void compressCFG();
|
||||
void highLevelGen();
|
||||
void structure(derSeq *derivedG);
|
||||
derSeq *checkReducibility();
|
||||
void createCFG();
|
||||
void markImpure();
|
||||
void findImmedDom();
|
||||
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void process_operands(ICODE &pIcode, STATE *pstate);
|
||||
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
boolT process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void freeCFG();
|
||||
void codeGen(std::ostream &fs);
|
||||
void mergeFallThrough(BB *pBB);
|
||||
void structIfs();
|
||||
void structLoops(derSeq *derivedG);
|
||||
void buildCFG(Disassembler &ds);
|
||||
void controlFlowAnalysis();
|
||||
void newRegArg(iICODE picode, iICODE ticode);
|
||||
void writeProcComments(std::ostream &ostr);
|
||||
|
||||
void displayCFG();
|
||||
void displayStats();
|
||||
void processHliCall(COND_EXPR *exp, iICODE picode);
|
||||
|
||||
void preprocessReturnDU(std::bitset<32> &_liveOut);
|
||||
protected:
|
||||
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
|
||||
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 Case_X_and_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_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
void replaceInEdge(BB* where, BB* which, BB* with);
|
||||
void processExpPush(int &numHlIcodes, iICODE picode);
|
||||
|
||||
// TODO: replace those with friend visitor ?
|
||||
void propLongReg(int loc_ident_idx, const ID &pLocId);
|
||||
void propLongStk(int i, const ID &pLocId);
|
||||
void propLongGlb(int i, const ID &pLocId);
|
||||
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong);
|
||||
|
||||
int findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE iter);
|
||||
int findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg);
|
||||
void structCases();
|
||||
void findExps();
|
||||
void genDU1();
|
||||
void elimCondCodes();
|
||||
void liveRegAnalysis(std::bitset<32> &in_liveOut);
|
||||
void findIdioms();
|
||||
void propLong();
|
||||
void genLiveKtes();
|
||||
uint8_t findDerivedSeq (derSeq &derivedGi);
|
||||
bool nextOrderGraph(derSeq &derivedGi);
|
||||
};
|
||||
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "symtab.h"
|
||||
|
||||
struct STKFRAME : public SymbolTableCommon<STKSYM>
|
||||
{
|
||||
//std::vector<STKSYM> sym;
|
||||
//STKSYM * sym; /* Symbols */
|
||||
int16_t m_minOff; /* Initial offset in stack frame*/
|
||||
int16_t maxOff; /* Maximum offset in stack frame*/
|
||||
int cb; /* Number of bytes in arguments */
|
||||
int numArgs; /* No. of arguments in the table*/
|
||||
void adjustForArgType(int numArg_, hlType actType_);
|
||||
STKFRAME() : m_minOff(0),maxOff(0),cb(0),numArgs(0)
|
||||
{
|
||||
|
||||
}
|
||||
size_t getLocVar(int off);
|
||||
public:
|
||||
void updateFrameOff(int16_t off, int size, uint16_t duFlag);
|
||||
};
|
||||
262
include/ast.h
262
include/ast.h
@ -4,12 +4,9 @@
|
||||
* Date: September 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include "Enums.h"
|
||||
#include <boost/range.hpp>
|
||||
static const int operandSize=20;
|
||||
|
||||
#define operandSize 20
|
||||
|
||||
/* The following definitions and types define the Conditional Expression
|
||||
* attributed syntax tree, as defined by the following EBNF:
|
||||
CondExp ::= CondTerm AND CondTerm | CondTerm
|
||||
@ -18,160 +15,123 @@ static const int operandSize=20;
|
||||
Identifier ::= globalVar | register | localVar | parameter | constant
|
||||
op ::= <= | < | = | != | > | >=
|
||||
*/
|
||||
|
||||
/* Conditional Expression enumeration nodes and operators */
|
||||
typedef enum {
|
||||
BOOLEAN_OP, /* condOps */
|
||||
NEGATION, /* not (2's complement) */
|
||||
ADDRESSOF, /* addressOf (&) */
|
||||
DEREFERENCE, /* contents of (*) */
|
||||
IDENTIFIER, /* {register | local | param | constant | global} */
|
||||
/* The following are only available to C programs */
|
||||
POST_INC, /* ++ (post increment) */
|
||||
POST_DEC, /* -- (post decrement) */
|
||||
PRE_INC, /* ++ (pre increment) */
|
||||
PRE_DEC, /* -- (pre decrement) */
|
||||
} condNodeType;
|
||||
|
||||
typedef enum {
|
||||
GLOB_VAR, /* global variable */
|
||||
REGISTER, /* register */
|
||||
LOCAL_VAR, /* negative disp */
|
||||
PARAM, /* positive disp */
|
||||
GLOB_VAR_IDX, /* indexed global variable *//*** should merge w/glob-var*/
|
||||
CONSTANT, /* constant */
|
||||
STRING, /* string */
|
||||
LONG_VAR, /* long variable */
|
||||
FUNCTION, /* function */
|
||||
OTHER /* other **** tmp solution */
|
||||
} condId;
|
||||
|
||||
typedef enum {
|
||||
/* For conditional expressions */
|
||||
LESS_EQUAL = 0, /* <= */
|
||||
LESS, /* < */
|
||||
EQUAL, /* == */
|
||||
NOT_EQUAL, /* != */
|
||||
GREATER, /* > */
|
||||
GREATER_EQUAL, /* >= */
|
||||
/* For general expressions */
|
||||
AND, /* & */
|
||||
OR, /* | */
|
||||
XOR, /* ^ */
|
||||
NOT, /* ~ */ /* 1's complement */
|
||||
ADD, /* + */
|
||||
SUB, /* - */
|
||||
MUL, /* * */
|
||||
DIV, /* / */
|
||||
SHR, /* >> */
|
||||
SHL, /* << */
|
||||
MOD, /* % */
|
||||
DBL_AND, /* && */
|
||||
DBL_OR, /* || */
|
||||
DUMMY, /* */
|
||||
} condOp;
|
||||
|
||||
/* High-level BOOLEAN conditions for iJB..iJNS icodes */
|
||||
static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
||||
static condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
||||
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
||||
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
||||
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct LOCAL_ID;
|
||||
struct ICODE;
|
||||
struct LLInst;
|
||||
struct ID;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
typedef boost::iterator_range<iICODE> rICODE;
|
||||
#include "IdentType.h"
|
||||
static condOp invCondOpJCond[12] = {GREATER_EQUAL, GREATER, LESS, LESS_EQUAL,
|
||||
NOT_EQUAL, EQUAL, GREATER_EQUAL, LESS,
|
||||
GREATER, LESS_EQUAL, LESS, GREATER_EQUAL};
|
||||
|
||||
|
||||
/* Register types */
|
||||
typedef enum {
|
||||
BYTE_REG, WORD_REG
|
||||
} regType;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
condId idType;
|
||||
regType regiType; /* for REGISTER only */
|
||||
union _idNode {
|
||||
Int regiIdx; /* index into localId, REGISTER */
|
||||
Int globIdx; /* index into symtab for GLOB_VAR */
|
||||
Int localIdx; /* idx into localId, LOCAL_VAR */
|
||||
Int paramIdx; /* idx into args symtab, PARAMS */
|
||||
Int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
struct _kte { /* for CONSTANT only */
|
||||
dword kte; /* value of the constant */
|
||||
byte size; /* #bytes size constant */
|
||||
} kte;
|
||||
dword strIdx; /* idx into image, for STRING */
|
||||
Int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/
|
||||
struct _call { /* for FUNCTION only */
|
||||
struct _proc *proc;
|
||||
struct _STKFRAME *args;
|
||||
} call;
|
||||
struct { /* for OTHER; tmp struct */
|
||||
byte seg; /* segment */
|
||||
byte regi; /* index mode */
|
||||
int16 off; /* offset */
|
||||
} other;
|
||||
} idNode;
|
||||
} IDENTTYPE;
|
||||
|
||||
|
||||
/* Expression data type */
|
||||
struct COND_EXPR
|
||||
{
|
||||
protected:
|
||||
struct /* for BOOLEAN_OP */
|
||||
{
|
||||
condOp op;
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
} boolExpr;
|
||||
|
||||
public:
|
||||
condNodeType m_type; /* Conditional Expression Node Type */
|
||||
typedef struct _condExpr {
|
||||
condNodeType type; /* Conditional Expression Node Type */
|
||||
union _exprNode { /* Different cond expr nodes */
|
||||
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||
struct { /* for BOOLEAN_OP */
|
||||
condOp op;
|
||||
struct _condExpr *lhs;
|
||||
struct _condExpr *rhs;
|
||||
} boolExpr;
|
||||
struct _condExpr *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||
IDENTTYPE ident; /* for IDENTIFIER */
|
||||
} expr;
|
||||
COND_EXPR *lhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.lhs;
|
||||
}
|
||||
const COND_EXPR *lhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.lhs;
|
||||
}
|
||||
COND_EXPR *rhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.rhs;
|
||||
}
|
||||
const COND_EXPR *rhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.rhs;
|
||||
}
|
||||
condOp op() const { return boolExpr.op;}
|
||||
public:
|
||||
static COND_EXPR *idRegIdx(int idx, regType reg_type);
|
||||
static COND_EXPR *idKte(uint32_t kte, uint8_t size);
|
||||
static COND_EXPR *idLoc(int off, LOCAL_ID *localId);
|
||||
static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
|
||||
static COND_EXPR *idLongIdx(int idx);
|
||||
static COND_EXPR *idOther(eReg seg, eReg regi, int16_t off);
|
||||
static COND_EXPR *idParam(int off, const STKFRAME *argSymtab);
|
||||
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr);
|
||||
static COND_EXPR *idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
static COND_EXPR *idFunc(Function *pproc, STKFRAME *args);
|
||||
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
|
||||
static COND_EXPR * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
|
||||
static COND_EXPR *boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op);
|
||||
static bool insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx);
|
||||
static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
public:
|
||||
virtual COND_EXPR *clone() const;
|
||||
void release();
|
||||
void changeBoolOp(condOp newOp);
|
||||
COND_EXPR(const COND_EXPR &other)
|
||||
{
|
||||
m_type=other.m_type;
|
||||
expr=other.expr;
|
||||
boolExpr=other.boolExpr;
|
||||
}
|
||||
COND_EXPR(condNodeType t=UNKNOWN_OP) : m_type(t)
|
||||
{
|
||||
memset(&expr,0,sizeof(_exprNode));
|
||||
memset(&boolExpr,0,sizeof(boolExpr));
|
||||
} COND_EXPR;
|
||||
|
||||
}
|
||||
virtual ~COND_EXPR() {}
|
||||
public:
|
||||
virtual COND_EXPR *inverse() const; // return new COND_EXPR that is invarse of this
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
|
||||
virtual hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct BinaryOperator : public COND_EXPR
|
||||
{
|
||||
condOp m_op;
|
||||
COND_EXPR *m_lhs;
|
||||
COND_EXPR *m_rhs;
|
||||
BinaryOperator(condOp o)
|
||||
{
|
||||
m_op = o;
|
||||
m_lhs=m_rhs=nullptr;
|
||||
}
|
||||
static BinaryOperator *Create(condOp o,COND_EXPR *l,COND_EXPR *r);
|
||||
static BinaryOperator *CreateAdd(COND_EXPR *l,COND_EXPR *r);
|
||||
virtual COND_EXPR *inverse();
|
||||
virtual COND_EXPR *clone();
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym);
|
||||
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
|
||||
/* Sequence of conditional expression data type */
|
||||
/*** NOTE: not used at present ****/
|
||||
typedef struct _condExpSeq {
|
||||
COND_EXPR *expr;
|
||||
struct _condExpSeq *next;
|
||||
} SEQ_COND_EXPR;
|
||||
|
||||
COND_EXPR *lhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_lhs;
|
||||
}
|
||||
const COND_EXPR *lhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_lhs;
|
||||
}
|
||||
COND_EXPR *rhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_rhs;
|
||||
}
|
||||
const COND_EXPR *rhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_rhs;
|
||||
}
|
||||
condOp op() const { return m_op;}
|
||||
/* Changes the boolean conditional operator at the root of this expression */
|
||||
void op(condOp o) { m_op=o;}
|
||||
};
|
||||
struct UnaryOperator : public COND_EXPR
|
||||
{
|
||||
condOp op;
|
||||
COND_EXPR *unaryExp;
|
||||
virtual COND_EXPR *inverse();
|
||||
virtual COND_EXPR *clone();
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
static UnaryOperator *Create(condNodeType t, COND_EXPR *sub_expr)
|
||||
{
|
||||
UnaryOperator *newExp = new UnaryOperator();
|
||||
newExp->m_type=t;
|
||||
newExp->unaryExp = sub_expr;
|
||||
return (newExp);
|
||||
}
|
||||
};
|
||||
|
||||
struct GlobalVariable : public COND_EXPR
|
||||
{
|
||||
static COND_EXPR *Create(int16_t segValue, int16_t off);
|
||||
};
|
||||
struct Constant : public COND_EXPR
|
||||
{};
|
||||
|
||||
@ -4,39 +4,28 @@
|
||||
* Purpose: Module to handle the bundle type (array of pointers to strings).
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
struct strTable : std::vector<std::string>
|
||||
{
|
||||
/* Returns the next available index into the table */
|
||||
size_t nextIdx() {return size();}
|
||||
public:
|
||||
void addLabelBundle(int idx, int label);
|
||||
};
|
||||
|
||||
struct bundle
|
||||
{
|
||||
public:
|
||||
void appendCode(const char *format, ...);
|
||||
void appendCode(const std::string &s);
|
||||
void appendDecl(const char *format, ...);
|
||||
void appendDecl(const std::string &);
|
||||
void init()
|
||||
{
|
||||
decl.clear();
|
||||
code.clear();
|
||||
}
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
Int numLines; /* Number of lines in the table */
|
||||
Int allocLines; /* Number of lines allocated in the table */
|
||||
char **str; /* Table of strings */
|
||||
} strTable;
|
||||
|
||||
|
||||
typedef struct {
|
||||
strTable decl; /* Declarations */
|
||||
strTable code; /* C code */
|
||||
int current_indent;
|
||||
};
|
||||
} bundle;
|
||||
|
||||
|
||||
#define lineSize 360 /* 3 lines in the mean time */
|
||||
|
||||
//void newBundle (bundle *procCode);
|
||||
void writeBundle (std::ostream &ios, bundle procCode);
|
||||
void newBundle (bundle *procCode);
|
||||
void appendStrTab (strTable *strTab, char *format, ...);
|
||||
Int nextBundleIdx (strTable *strTab);
|
||||
void addLabelBundle (strTable *strTab, Int idx, Int label);
|
||||
void writeBundle (FILE *fp, bundle procCode);
|
||||
void freeBundle (bundle *procCode);
|
||||
|
||||
|
||||
353
include/dcc.h
353
include/dcc.h
@ -2,15 +2,8 @@
|
||||
* dcc project general header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
//TODO: Remove boolT
|
||||
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "icode.h"
|
||||
@ -18,31 +11,134 @@
|
||||
#include "error.h"
|
||||
#include "graph.h"
|
||||
#include "bundle.h"
|
||||
#include "Procedure.h"
|
||||
#include "BasicBlock.h"
|
||||
struct Project;
|
||||
|
||||
|
||||
/* SYMBOL TABLE */
|
||||
typedef struct {
|
||||
char name[10]; /* New name for this variable */
|
||||
dword label; /* physical address (20 bit) */
|
||||
Int size; /* maximum size */
|
||||
flags32 flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
hlType type; /* probable type */
|
||||
word duVal; /* DEF, USE, VAL */
|
||||
} SYM;
|
||||
typedef SYM *PSYM;
|
||||
|
||||
typedef struct {
|
||||
Int csym; /* No. of symbols in table */
|
||||
Int alloc; /* Allocation */
|
||||
PSYM sym; /* Symbols */
|
||||
} SYMTAB;
|
||||
typedef SYMTAB *PSYMTAB;
|
||||
|
||||
|
||||
/* STACK FRAME */
|
||||
typedef struct {
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16 off; /* Immediate off from BP (+:args, -:params) */
|
||||
byte regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
Int size; /* Size */
|
||||
hlType type; /* Probable type */
|
||||
word duVal; /* DEF, USE, VAL */
|
||||
boolT hasMacro; /* This type needs a macro */
|
||||
char macro[10]; /* Macro name */
|
||||
char name[10]; /* Name for this symbol/argument */
|
||||
boolT invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
} STKSYM;
|
||||
typedef STKSYM *PSTKSYM;
|
||||
|
||||
typedef struct _STKFRAME {
|
||||
Int csym; /* No. of symbols in table */
|
||||
Int alloc; /* Allocation */
|
||||
PSTKSYM sym; /* Symbols */
|
||||
int16 minOff; /* Initial offset in stack frame*/
|
||||
int16 maxOff; /* Maximum offset in stack frame*/
|
||||
Int cb; /* Number of bytes in arguments */
|
||||
Int numArgs; /* No. of arguments in the table*/
|
||||
} STKFRAME;
|
||||
typedef STKFRAME *PSTKFRAME;
|
||||
|
||||
/* PROCEDURE NODE */
|
||||
typedef struct _proc {
|
||||
dword procEntry; /* label number */
|
||||
char name[SYMLEN]; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
Int depth; /* Depth at which we found it - for printing */
|
||||
flags32 flg; /* Combination of Icode & Proc flags */
|
||||
int16 cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
PBB cfg; /* Ptr. to BB list/CFG */
|
||||
PBB *dfsLast; /* Array of pointers to BBs in dfsLast
|
||||
* (reverse postorder) order */
|
||||
Int numBBs; /* Number of BBs in the graph cfg */
|
||||
boolT hasCase; /* Procedure has a case node */
|
||||
|
||||
/* For interprocedural live analysis */
|
||||
dword liveIn; /* Registers used before defined */
|
||||
dword liveOut; /* Registers that may be used in successors */
|
||||
boolT liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
/* Double-linked list */
|
||||
struct _proc *next;
|
||||
struct _proc *prev;
|
||||
} PROCEDURE;
|
||||
typedef PROCEDURE *PPROC;
|
||||
|
||||
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
ilFunction proc; /* Pointer to procedure in pProcList */
|
||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
||||
public:
|
||||
void write();
|
||||
CALL_GRAPH() : outEdges(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
void writeNodeCallGraph(int indIdx);
|
||||
bool insertCallGraph(ilFunction caller, ilFunction callee);
|
||||
bool insertCallGraph(Function *caller, ilFunction callee);
|
||||
void insertArc(ilFunction newProc);
|
||||
};
|
||||
//#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||
//extern std::list<Function> pProcList;
|
||||
//extern FunctionListType pProcList;
|
||||
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
typedef struct _callGraph {
|
||||
PPROC proc; /* Pointer to procedure in pProcList */
|
||||
Int numOutEdges; /* # of out edges (ie. # procs invoked) */
|
||||
Int numAlloc; /* # of out edges allocated */
|
||||
struct _callGraph **outEdges; /* array of out edges */
|
||||
} CALL_GRAPH;
|
||||
typedef CALL_GRAPH *PCALL_GRAPH;
|
||||
#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||
|
||||
extern PPROC pProcList; /* Pointer to the head of the procedure list */
|
||||
extern PPROC pLastProc; /* Pointer to last node of the proc list */
|
||||
extern PCALL_GRAPH callGraph; /* Pointer to the head of the call graph */
|
||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
|
||||
/* Procedure FLAGS */
|
||||
#define PROC_BADINST 0x000100 /* Proc contains invalid or 386 instruction */
|
||||
#define PROC_IJMP 0x000200 /* Proc incomplete due to indirect jmp */
|
||||
#define PROC_ICALL 0x000400 /* Proc incomplete due to indirect call */
|
||||
#define PROC_HLL 0x001000 /* Proc is likely to be from a HLL */
|
||||
#define CALL_PASCAL 0x002000 /* Proc uses Pascal calling convention */
|
||||
#define CALL_C 0x004000 /* Proc uses C calling convention */
|
||||
#define CALL_UNKNOWN 0x008000 /* Proc uses unknown calling convention */
|
||||
#define PROC_NEAR 0x010000 /* Proc exits with near return */
|
||||
#define PROC_FAR 0x020000 /* Proc exits with far return */
|
||||
#define GRAPH_IRRED 0x100000 /* Proc generates an irreducible graph */
|
||||
#define SI_REGVAR 0x200000 /* SI is used as a stack variable */
|
||||
#define DI_REGVAR 0x400000 /* DI is used as a stack variable */
|
||||
#define PROC_IS_FUNC 0x800000 /* Proc is a function */
|
||||
#define REG_ARGS 0x1000000 /* Proc has registers as arguments */
|
||||
#define PROC_VARARG 0x2000000 /* Proc has variable arguments */
|
||||
#define PROC_OUTPUT 0x4000000 /* C for this proc has been output */
|
||||
#define PROC_RUNTIME 0x8000000 /* Proc is part of the runtime support */
|
||||
#define PROC_ISLIB 0x10000000 /* Proc is a library function */
|
||||
#define PROC_ASM 0x20000000 /* Proc is an intrinsic assembler routine */
|
||||
#define PROC_IS_HLL 0x40000000 /* Proc has HLL prolog code */
|
||||
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
|
||||
/* duVal FLAGS */
|
||||
#define DEF 0x0010 /* Variable was first defined than used */
|
||||
#define USE 0x0100 /* Variable was first used than defined */
|
||||
#define VAL 0x1000 /* Variable has an initial value. 2 cases:
|
||||
* 1. When variable is used first (ie. global)
|
||||
* 2. When a value is moved into the variable
|
||||
* for the first time. */
|
||||
#define USEVAL 0x1100 /* Use and Val */
|
||||
|
||||
|
||||
/**** Global variables ****/
|
||||
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
@ -60,90 +156,169 @@ typedef struct { /* Command line option flags */
|
||||
} OPTION;
|
||||
|
||||
extern OPTION option; /* Command line options */
|
||||
extern SYMTAB symtab; /* Global symbol table */
|
||||
|
||||
#include "BinaryImage.h"
|
||||
extern std::bitset<32> duReg[30]; /* def/use bits for registers */
|
||||
typedef struct { /* Loaded program image parameters */
|
||||
int16 initCS;
|
||||
int16 initIP; /* These are initial load values */
|
||||
int16 initSS; /* Probably not of great interest */
|
||||
int16 initSP;
|
||||
boolT fCOM; /* Flag set if COM program (else EXE)*/
|
||||
Int cReloc; /* No. of relocation table entries */
|
||||
dword *relocTable; /* Ptr. to relocation table */
|
||||
byte *map; /* Memory bitmap ptr */
|
||||
Int cProcs; /* Number of procedures so far */
|
||||
Int offMain; /* The offset of the main() proc */
|
||||
word segMain; /* The segment of the main() proc */
|
||||
boolT bSigs; /* True if signatures loaded */
|
||||
Int cbImage; /* Length of image in bytes */
|
||||
byte *Image; /* Allocated by loader to hold entire
|
||||
* program image */
|
||||
} PROG;
|
||||
|
||||
//extern uint32_t duReg[30]; /* def/use bits for registers */
|
||||
extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */
|
||||
extern PROG prog; /* Loaded program image parameters */
|
||||
extern char condExp[200]; /* Conditional expression buffer */
|
||||
extern char callBuf[100]; /* Function call buffer */
|
||||
extern dword duReg[30]; /* def/use bits for registers */
|
||||
extern dword maskDuReg[30]; /* masks off du bits for regs */
|
||||
|
||||
/* Registers used by icode instructions */
|
||||
static char *allRegs[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
|
||||
"si", "di", "es", "cs", "ss", "ds",
|
||||
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
|
||||
"tmp"};
|
||||
|
||||
/* Memory map states */
|
||||
enum eAreaType
|
||||
{
|
||||
BM_UNKNOWN = 0, /* Unscanned memory */
|
||||
BM_DATA = 1, /* Data */
|
||||
BM_CODE = 2, /* Code */
|
||||
BM_IMPURE = 3 /* Used as Data and Code*/
|
||||
};
|
||||
#define BM_UNKNOWN 0 /* Unscanned memory */
|
||||
#define BM_DATA 1 /* Data */
|
||||
#define BM_CODE 2 /* Code */
|
||||
#define BM_IMPURE 3 /* Used as Data and Code*/
|
||||
|
||||
/* Intermediate instructions statistics */
|
||||
struct STATS
|
||||
{
|
||||
int numBBbef; /* number of basic blocks initially */
|
||||
int numBBaft; /* number of basic blocks at the end */
|
||||
int nOrder; /* n-th order */
|
||||
int numLLIcode; /* number of low-level Icode instructions */
|
||||
int numHLIcode; /* number of high-level Icode instructions */
|
||||
int totalLL; /* total number of low-level Icode insts */
|
||||
int totalHL; /* total number of high-level Icod insts */
|
||||
};
|
||||
typedef struct {
|
||||
Int numBBbef; /* number of basic blocks initially */
|
||||
Int numBBaft; /* number of basic blocks at the end */
|
||||
Int nOrder; /* n-th order */
|
||||
Int numLLIcode; /* number of low-level Icode instructions */
|
||||
Int numHLIcode; /* number of high-level Icode instructions */
|
||||
Int totalLL; /* total number of low-level Icode insts */
|
||||
Int totalHL; /* total number of high-level Icod insts */
|
||||
} STATS;
|
||||
|
||||
extern STATS stats; /* Icode statistics */
|
||||
|
||||
|
||||
/**** Global function prototypes ****/
|
||||
class DccFrontend
|
||||
{
|
||||
void LoadImage(Project &proj);
|
||||
void parse(Project &proj);
|
||||
std::string m_fname;
|
||||
public:
|
||||
DccFrontend(const std::string &fname) : m_fname(fname)
|
||||
{
|
||||
}
|
||||
bool FrontEnd(); /* frontend.c */
|
||||
};
|
||||
|
||||
void FrontEnd(char *filename, PCALL_GRAPH *); /* frontend.c */
|
||||
void *allocMem(Int cb); /* frontend.c */
|
||||
void *reallocVar(void *p, Int newsize); /* frontend.c */
|
||||
void udm(void); /* udm.c */
|
||||
void freeCFG(BB * cfg); /* graph.c */
|
||||
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
|
||||
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
|
||||
char *cChar(uint8_t c); /* backend.c */
|
||||
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
|
||||
void parse (CALL_GRAPH * *); /* parser.c */
|
||||
|
||||
int strSize (uint8_t *, char); /* parser.c */
|
||||
//void disassem(int pass, Function * pProc); /* disassem.c */
|
||||
void interactDis(Function * initProc, int initIC); /* disassem.c */
|
||||
bool JmpInst(llIcode opcode); /* idioms.c */
|
||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
|
||||
|
||||
PBB createCFG(PPROC pProc); /* graph.c */
|
||||
void compressCFG(PPROC pProc); /* graph.c */
|
||||
void freeCFG(PBB cfg); /* graph.c */
|
||||
PBB newBB(PBB, Int, Int, byte, Int, PPROC); /* graph.c */
|
||||
void BackEnd(char *filename, PCALL_GRAPH); /* backend.c */
|
||||
char *cChar(byte c); /* backend.c */
|
||||
Int scan(dword ip, PICODE p); /* scanner.c */
|
||||
void parse (PCALL_GRAPH *); /* parser.c */
|
||||
boolT labelSrch(PICODE pIc, Int n, dword tg, Int *pIdx); /* parser.c */
|
||||
void setState(PSTATE state, word reg, int16 value); /* parser.c */
|
||||
Int strSize (byte *, char); /* parser.c */
|
||||
void disassem(Int pass, PPROC pProc); /* disassem.c */
|
||||
void interactDis(PPROC initProc, Int initIC); /* disassem.c */
|
||||
void bindIcodeOff (PPROC); /* idioms.c */
|
||||
void lowLevelAnalysis (PPROC pProc); /* idioms.c */
|
||||
void propLong (PPROC pproc); /* proplong.c */
|
||||
boolT JmpInst(llIcode opcode); /* idioms.c */
|
||||
void checkReducibility(PPROC pProc, derSeq **derG); /* reducible.c */
|
||||
queue *appendQueue(queue **Q, BB *node); /* reducible.c */
|
||||
void freeDerivedSeq(derSeq *derivedG); /* reducible.c */
|
||||
void displayDerivedSeq(derSeq *derG); /* reducible.c */
|
||||
void structure(PPROC pProc, derSeq *derG); /* control.c */
|
||||
void compoundCond (PPROC); /* control.c */
|
||||
void dataFlow(PPROC pProc, dword liveOut); /* dataflow.c */
|
||||
void writeIntComment (PICODE icode, char *s); /* comwrite.c */
|
||||
void writeProcComments (PPROC pProc, strTable *sTab); /* comwrite.c */
|
||||
void checkStartup(PSTATE pState); /* chklib.c */
|
||||
void SetupLibCheck(void); /* chklib.c */
|
||||
void CleanupLibCheck(void); /* chklib.c */
|
||||
bool LibCheck(Function &p); /* chklib.c */
|
||||
boolT LibCheck(PPROC p); /* chklib.c */
|
||||
|
||||
/* Exported functions from procs.c */
|
||||
boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction);
|
||||
void adjustActArgType (COND_EXPR *, hlType, Function *);
|
||||
boolT insertCallGraph (PCALL_GRAPH, PPROC, PPROC);
|
||||
void writeCallGraph (PCALL_GRAPH);
|
||||
void newRegArg (PPROC, PICODE, PICODE);
|
||||
boolT newStkArg (PICODE, COND_EXPR *, llIcode, PPROC);
|
||||
void allocStkArgs (PICODE, Int);
|
||||
void placeStkArg (PICODE, COND_EXPR *, Int);
|
||||
void adjustActArgType (COND_EXPR *, hlType, PPROC);
|
||||
void adjustForArgType (PSTKFRAME, Int, hlType);
|
||||
|
||||
/* Exported functions from ast.c */
|
||||
std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, int *);
|
||||
int hlTypeSize (const COND_EXPR *, Function *);
|
||||
//hlType expType (const COND_EXPR *, Function *);
|
||||
|
||||
COND_EXPR *boolCondExp (COND_EXPR *lhs, COND_EXPR *rhs, condOp op);
|
||||
COND_EXPR *unaryCondExp (condNodeType, COND_EXPR *exp);
|
||||
COND_EXPR *idCondExpGlob (int16 segValue, int16 off);
|
||||
COND_EXPR *idCondExpReg (byte regi, flags32 flg, LOCAL_ID *);
|
||||
COND_EXPR *idCondExpRegIdx (Int idx, regType);
|
||||
COND_EXPR *idCondExpLoc (Int off, LOCAL_ID *);
|
||||
COND_EXPR *idCondExpParam (Int off, PSTKFRAME argSymtab);
|
||||
COND_EXPR *idCondExpKte (dword kte, byte);
|
||||
COND_EXPR *idCondExpLong (LOCAL_ID *, opLoc, PICODE, hlFirst, Int idx, operDu,
|
||||
Int);
|
||||
COND_EXPR *idCondExpLongIdx (Int);
|
||||
COND_EXPR *idCondExpFunc (PPROC, PSTKFRAME);
|
||||
COND_EXPR *idCondExpOther (byte seg, byte regi, int16 off);
|
||||
COND_EXPR *idCondExpID (ID *, LOCAL_ID *, Int);
|
||||
COND_EXPR *idCondExp (PICODE, opLoc, PPROC, Int i, PICODE duIcode, operDu);
|
||||
COND_EXPR *copyCondExp (COND_EXPR *);
|
||||
void removeRegFromLong (byte, LOCAL_ID *, COND_EXPR *);
|
||||
char *walkCondExpr (COND_EXPR *exp, PPROC pProc, Int *);
|
||||
condId idType (PICODE pIcode, opLoc sd);
|
||||
Int hlTypeSize (COND_EXPR *, PPROC);
|
||||
hlType expType (COND_EXPR *, PPROC);
|
||||
void setRegDU (PICODE, byte regi, operDu);
|
||||
void copyDU (PICODE, PICODE, operDu, operDu);
|
||||
void changeBoolCondExpOp (COND_EXPR *, condOp);
|
||||
boolT insertSubTreeReg (COND_EXPR *, COND_EXPR **, byte, LOCAL_ID *);
|
||||
boolT insertSubTreeLongReg (COND_EXPR *, COND_EXPR **, Int);
|
||||
void freeCondExpr (COND_EXPR *exp);
|
||||
COND_EXPR *concatExps (SEQ_COND_EXPR *, COND_EXPR *, condNodeType);
|
||||
void initExpStk();
|
||||
void pushExpStk (COND_EXPR *);
|
||||
COND_EXPR *popExpStk();
|
||||
Int numElemExpStk();
|
||||
boolT emptyExpStk();
|
||||
|
||||
/* Exported functions from hlicode.c */
|
||||
std::string writeCall (Function *, STKFRAME &, Function *, int *);
|
||||
char *writeJcond (const HLTYPE &, Function *, int *);
|
||||
char *writeJcondInv (HLTYPE, Function *, int *);
|
||||
|
||||
void newAsgnHlIcode (PICODE, COND_EXPR *, COND_EXPR *);
|
||||
void newCallHlIcode (PICODE);
|
||||
void newUnaryHlIcode (PICODE, hlIcode, COND_EXPR *);
|
||||
void newJCondHlIcode (PICODE, COND_EXPR *);
|
||||
void invalidateIcode (PICODE);
|
||||
boolT removeDefRegi (byte, PICODE, Int, LOCAL_ID *);
|
||||
void highLevelGen (PPROC);
|
||||
char *writeCall (PPROC, PSTKFRAME, PPROC, Int *);
|
||||
char *write1HlIcode (HLTYPE, PPROC, Int *);
|
||||
char *writeJcond (HLTYPE, PPROC, Int *);
|
||||
char *writeJcondInv (HLTYPE, PPROC, Int *);
|
||||
Int power2 (Int);
|
||||
void writeDU (PICODE, Int);
|
||||
void inverseCondOp (COND_EXPR **);
|
||||
|
||||
/* Exported funcions from locident.c */
|
||||
boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
|
||||
boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
|
||||
eReg otherLongRegi(eReg, int, LOCAL_ID *);
|
||||
Int newByteWordRegId (LOCAL_ID *, hlType t, byte regi);
|
||||
Int newByteWordStkId (LOCAL_ID *, hlType t, Int off, byte regOff);
|
||||
Int newIntIdxId (LOCAL_ID *, int16 seg, int16 off, byte regi, Int, hlType);
|
||||
Int newLongRegId (LOCAL_ID *, hlType t, byte regH, byte regL, Int idx);
|
||||
Int newLongStkId (LOCAL_ID *, hlType t, Int offH, Int offL);
|
||||
Int newLongId (LOCAL_ID *, opLoc sd, PICODE, hlFirst, Int idx, operDu, Int);
|
||||
boolT checkLongEq (LONG_STKID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **,
|
||||
COND_EXPR **, Int);
|
||||
boolT checkLongRegEq (LONGID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **,
|
||||
COND_EXPR **, Int);
|
||||
byte otherLongRegi (byte, Int, LOCAL_ID *);
|
||||
void insertIdx (IDX_ARRAY *, Int);
|
||||
void propLongId (LOCAL_ID *, byte, byte, char *);
|
||||
|
||||
|
||||
extern const char *indentStr(int level);
|
||||
|
||||
@ -2,32 +2,7 @@
|
||||
* dcc project disassembler header
|
||||
* (C) Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "bundle.h"
|
||||
struct LLInst;
|
||||
struct Disassembler
|
||||
{
|
||||
protected:
|
||||
int pass;
|
||||
int g_lab;
|
||||
//bundle &cCode;
|
||||
std::ofstream m_fp;
|
||||
std::vector<std::string> m_decls;
|
||||
std::vector<std::string> m_code;
|
||||
|
||||
public:
|
||||
Disassembler(int _p) : pass(_p)
|
||||
{
|
||||
g_lab=0;
|
||||
}
|
||||
public:
|
||||
void disassem(Function *ppProc);
|
||||
void disassem(Function *ppProc, int i);
|
||||
void dis1Line(LLInst &inst, int loc_ip, int pass);
|
||||
};
|
||||
/* Definitions for extended keys (first key is zero) */
|
||||
|
||||
#define EXT 0x100 /* "Extended" flag */
|
||||
|
||||
@ -5,34 +5,34 @@
|
||||
**************************************************************************/
|
||||
|
||||
/* Type definitions for intel 80x86 architecture */
|
||||
typedef unsigned int uint16_t; /* 16 bits */
|
||||
typedef unsigned char uint8_t; /* 8 bits */
|
||||
typedef unsigned int Word; /* 16 bits */
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
typedef union {
|
||||
unsigned long dW;
|
||||
uint16_t wL, wH; /* 2 words */
|
||||
Word wL, wH; /* 2 words */
|
||||
} Dword; /* 32 bits */
|
||||
|
||||
/* Structure to access high and low bits of a uint8_t or uint16_t variable */
|
||||
/* Structure to access high and low bits of a Byte or Word variable */
|
||||
typedef struct {
|
||||
/* low uint8_t */
|
||||
uint16_t lowBitWord : 1;
|
||||
uint16_t filler1 : 6;
|
||||
uint16_t highBitByte : 1;
|
||||
/* high uint8_t */
|
||||
uint16_t lowBitByte : 1;
|
||||
uint16_t filler2 : 6;
|
||||
uint16_t highBitWord : 1;
|
||||
/* low byte */
|
||||
Word lowBitWord : 1;
|
||||
Word filler1 : 6;
|
||||
Word highBitByte : 1;
|
||||
/* high byte */
|
||||
Word lowBitByte : 1;
|
||||
Word filler2 : 6;
|
||||
Word highBitWord : 1;
|
||||
} wordBits;
|
||||
|
||||
/* Low and high bits of a uint8_t or uint16_t variable */
|
||||
/* Low and high bits of a Byte or Word variable */
|
||||
#define lowBit(a) ((wordBits)(a).lowBitWord)
|
||||
#define highBitByte(a) ((wordBits)(a).highBitByte)
|
||||
#define lowBitByte(a) ((wordBits)(a).lowBitByte)
|
||||
#define highBit(a) (sizeof(a) == sizeof(uint16_t) ? \
|
||||
#define highBit(a) (sizeof(a) == sizeof(Word) ? \
|
||||
((wordBits)(a).highBitWord):\
|
||||
((wordBits)(a).highBitByte))
|
||||
|
||||
/* uint16_t register variables */
|
||||
/* Word register variables */
|
||||
#define ax regs.x.ax
|
||||
#define bx regs.x.bx
|
||||
#define cx regs.x.cx
|
||||
@ -52,7 +52,7 @@ typedef struct {
|
||||
#define carry regs.x.cflags
|
||||
#define overF regs.x.flags /***** check *****/
|
||||
|
||||
/* uint8_t register variables */
|
||||
/* Byte register variables */
|
||||
#define ah regs.h.ah
|
||||
#define al regs.h.al
|
||||
#define bh regs.h.bh
|
||||
@ -64,8 +64,8 @@ typedef struct {
|
||||
|
||||
|
||||
/* High and low words of a Dword */
|
||||
#define highWord(w) (*((uint16_t*)&(w) + 1))
|
||||
#define lowWord(w) ((uint16_t)(w))
|
||||
#define highWord(w) (*((Word*)&(w) + 1))
|
||||
#define lowWord(w) ((Word)(w))
|
||||
|
||||
#define MAXByte 0xFF
|
||||
#define MAXWord 0xFFFF
|
||||
@ -74,4 +74,7 @@ typedef struct {
|
||||
#define MAXSignWord 0x7FFF
|
||||
#define MINSignWord 0x8001
|
||||
|
||||
/* Booleans */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
|
||||
@ -2,35 +2,32 @@
|
||||
* Error codes
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
|
||||
/* These definitions refer to errorMessage in error.c */
|
||||
enum eErrorId
|
||||
{
|
||||
NO_ERR =0,
|
||||
USAGE,
|
||||
INVALID_ARG,
|
||||
INVALID_OPCODE,
|
||||
INVALID_386OP,
|
||||
FUNNY_SEGOVR,
|
||||
FUNNY_REP,
|
||||
CANNOT_OPEN,
|
||||
CANNOT_READ,
|
||||
MALLOC_FAILED,
|
||||
NEWEXE_FORMAT,
|
||||
|
||||
NO_BB,
|
||||
INVALID_SYNTHETIC_BB,
|
||||
INVALID_INT_BB,
|
||||
IP_OUT_OF_RANGE,
|
||||
DEF_NOT_FOUND,
|
||||
JX_NOT_DEF,
|
||||
NOT_DEF_USE,
|
||||
REPEAT_FAIL,
|
||||
WHILE_FAIL
|
||||
};
|
||||
#define USAGE 0
|
||||
#define INVALID_ARG 1
|
||||
#define INVALID_OPCODE 2
|
||||
#define INVALID_386OP 3
|
||||
#define FUNNY_SEGOVR 4
|
||||
#define FUNNY_REP 5
|
||||
#define CANNOT_OPEN 6
|
||||
#define CANNOT_READ 7
|
||||
#define MALLOC_FAILED 8
|
||||
#define NEWEXE_FORMAT 9
|
||||
|
||||
#define NO_BB 10
|
||||
#define INVALID_SYNTHETIC_BB 11
|
||||
#define INVALID_INT_BB 12
|
||||
#define IP_OUT_OF_RANGE 13
|
||||
#define DEF_NOT_FOUND 14
|
||||
#define JX_NOT_DEF 15
|
||||
#define NOT_DEF_USE 16
|
||||
#define REPEAT_FAIL 17
|
||||
#define WHILE_FAIL 18
|
||||
|
||||
|
||||
void fatalError(eErrorId errId, ...);
|
||||
void reportError(eErrorId errId, ...);
|
||||
void fatalError(Int errId, ...);
|
||||
void reportError(Int errId, ...);
|
||||
|
||||
|
||||
171
include/graph.h
171
include/graph.h
@ -2,49 +2,37 @@
|
||||
* CFG, BB and interval related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
struct Function;
|
||||
|
||||
|
||||
/* Types of basic block nodes */
|
||||
/* Real basic blocks: type defined according to their out-edges */
|
||||
enum eBBKind
|
||||
{
|
||||
ONE_BRANCH = 0, /* unconditional branch */
|
||||
TWO_BRANCH = 1, /* conditional branch */
|
||||
MULTI_BRANCH=2, /* case branch */
|
||||
FALL_NODE=3, /* fall through */
|
||||
RETURN_NODE=4, /* procedure/program return */
|
||||
CALL_NODE=5, /* procedure call */
|
||||
LOOP_NODE=6, /* loop instruction */
|
||||
REP_NODE=7, /* repeat instruction */
|
||||
INTERVAL_NODE=8, /* contains interval list */
|
||||
#define ONE_BRANCH 0 /* unconditional branch */
|
||||
#define TWO_BRANCH 1 /* conditional branch */
|
||||
#define MULTI_BRANCH 2 /* case branch */
|
||||
#define FALL_NODE 3 /* fall through */
|
||||
#define RETURN_NODE 4 /* procedure/program return */
|
||||
#define CALL_NODE 5 /* procedure call */
|
||||
#define LOOP_NODE 6 /* loop instruction */
|
||||
#define REP_NODE 7 /* repeat instruction */
|
||||
#define INTERVAL_NODE 8 /* contains interval list */
|
||||
|
||||
TERMINATE_NODE=11, /* Exit to DOS */
|
||||
NOWHERE_NODE=12 /* No outedges going anywhere */
|
||||
};
|
||||
#define TERMINATE_NODE 11 /* Exit to DOS */
|
||||
#define NOWHERE_NODE 12 /* No outedges going anywhere */
|
||||
|
||||
|
||||
/* Depth-first traversal constants */
|
||||
enum eDFS
|
||||
{
|
||||
DFS_NONE,
|
||||
DFS_DISP=1, /* Display graph pass */
|
||||
DFS_MERGE=2, /* Merge nodes pass */
|
||||
DFS_NUM=3, /* DFS numbering pass */
|
||||
DFS_CASE=4, /* Case pass */
|
||||
DFS_ALPHA=5, /* Alpha code generation*/
|
||||
DFS_JMP=9 /* rmJMP pass - must be largest flag */
|
||||
};
|
||||
#define DFS_DISP 1 /* Display graph pass */
|
||||
#define DFS_MERGE 2 /* Merge nodes pass */
|
||||
#define DFS_NUM 3 /* DFS numbering pass */
|
||||
#define DFS_CASE 4 /* Case pass */
|
||||
#define DFS_ALPHA 5 /* Alpha code generation*/
|
||||
#define DFS_JMP 9 /* rmJMP pass - must be largest flag */
|
||||
|
||||
/* Control flow analysis constants */
|
||||
enum eNodeHeaderType
|
||||
{
|
||||
NO_TYPE=0, /* node is not a loop header*/
|
||||
WHILE_TYPE=1, /* node is a while header */
|
||||
REPEAT_TYPE=2, /* node is a repeat header */
|
||||
ENDLESS_TYPE=3 /* endless loop header */
|
||||
};
|
||||
#define NO_TYPE 0 /* node is not a loop header*/
|
||||
#define WHILE_TYPE 1 /* node is a while header */
|
||||
#define REPEAT_TYPE 2 /* node is a repeat header */
|
||||
#define ENDLESS_TYPE 3 /* endless loop header */
|
||||
|
||||
/* Uninitialized values for certain fields */
|
||||
#define NO_NODE MAX /* node has no associated node */
|
||||
@ -58,44 +46,87 @@ enum eNodeHeaderType
|
||||
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
||||
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
|
||||
|
||||
struct BB;
|
||||
/* Interval structure */
|
||||
typedef std::list<BB *> queue;
|
||||
|
||||
struct interval
|
||||
/* Interval structure */
|
||||
typedef struct _queueNode {
|
||||
struct _BB *node; /* Ptr to basic block */
|
||||
struct _queueNode *next;
|
||||
} queue;
|
||||
|
||||
typedef struct _intNode {
|
||||
byte numInt; /* # of the interval */
|
||||
byte numOutEdges; /* Number of out edges */
|
||||
queue *nodes; /* Nodes of the interval*/
|
||||
queue *currNode; /* Current node */
|
||||
struct _intNode *next; /* Next interval */
|
||||
} interval;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t numInt; /* # of the interval */
|
||||
uint8_t numOutEdges; /* Number of out edges */
|
||||
queue nodes; /* Nodes of the interval*/
|
||||
queue::iterator currNode; /* Current node */
|
||||
interval *next; /* Next interval */
|
||||
BB *firstOfInt();
|
||||
interval()
|
||||
{
|
||||
numInt=numOutEdges=0;
|
||||
currNode=nodes.end();
|
||||
next=0;
|
||||
}
|
||||
};
|
||||
dword ip; /* Out edge icode address */
|
||||
struct _BB *BBptr; /* Out edge pointer to next BB */
|
||||
interval *intPtr; /* Out edge ptr to next interval*/
|
||||
} TYPEADR_TYPE;
|
||||
|
||||
/* Basic block (BB) node definition */
|
||||
typedef struct _BB {
|
||||
byte nodeType; /* Type of node */
|
||||
Int traversed; /* Boolean: traversed yet? */
|
||||
Int start; /* First instruction offset */
|
||||
Int length; /* No. of instructions this BB */
|
||||
Int numHlIcodes; /* No. of high-level icodes */
|
||||
flags32 flg; /* BB flags */
|
||||
|
||||
/* In edges and out edges */
|
||||
Int numInEdges; /* Number of in edges */
|
||||
struct _BB **inEdges; /* Array of ptrs. to in edges */
|
||||
|
||||
Int numOutEdges; /* Number of out edges */
|
||||
TYPEADR_TYPE *edges; /* Array of ptrs. to out edges */
|
||||
|
||||
/* For interval construction */
|
||||
Int beenOnH; /* #times been on header list H */
|
||||
Int inEdgeCount; /* #inEdges (to find intervals) */
|
||||
struct _BB *reachingInt; /* Reaching interval header */
|
||||
interval *inInterval; /* Node's interval */
|
||||
|
||||
/* For derived sequence construction */
|
||||
interval *correspInt; /* Corresponding interval in
|
||||
* derived graph Gi-1 */
|
||||
|
||||
/* For live register analysis
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
dword liveUse; /* LiveUse(b) */
|
||||
dword def; /* Def(b) */
|
||||
dword liveIn; /* LiveIn(b) */
|
||||
dword liveOut; /* LiveOut(b) */
|
||||
|
||||
/* For structuring analysis */
|
||||
Int dfsFirstNum; /* DFS #: first visit of node */
|
||||
Int dfsLastNum; /* DFS #: last visit of node */
|
||||
Int immedDom; /* Immediate dominator (dfsLast
|
||||
* index) */
|
||||
Int ifFollow; /* node that ends the if */
|
||||
Int loopType; /* Type of loop (if any) */
|
||||
Int latchNode; /* latching node of the loop */
|
||||
Int numBackEdges; /* # of back edges */
|
||||
Int loopHead; /* most nested loop head to which
|
||||
* this node belongs (dfsLast) */
|
||||
Int loopFollow; /* node that follows the loop */
|
||||
Int caseHead; /* most nested case to which this
|
||||
node belongs (dfsLast) */
|
||||
Int caseTail; /* tail node for the case */
|
||||
|
||||
Int index; /* Index, used in several ways */
|
||||
struct _BB *next; /* Next (list link) */
|
||||
} BB;
|
||||
typedef BB *PBB;
|
||||
|
||||
|
||||
/* Derived Sequence structure */
|
||||
struct derSeq_Entry
|
||||
{
|
||||
BB * Gi; /* Graph pointer */
|
||||
interval * Ii; /* Interval list of Gi */
|
||||
derSeq_Entry() : Gi(0),Ii(0)
|
||||
{
|
||||
|
||||
}
|
||||
~derSeq_Entry();
|
||||
public:
|
||||
void findIntervals(Function *c);
|
||||
};
|
||||
class derSeq : public std::list<derSeq_Entry>
|
||||
{
|
||||
public:
|
||||
void display();
|
||||
};
|
||||
void freeDerivedSeq(derSeq &derivedG); /* reducible.c */
|
||||
typedef struct _derivedNode {
|
||||
BB *Gi; /* Graph pointer */
|
||||
interval *Ii; /* Interval list of Gi */
|
||||
struct _derivedNode *next; /* Next derived graph */
|
||||
} derSeq;
|
||||
|
||||
|
||||
@ -6,8 +6,16 @@
|
||||
|
||||
|
||||
/* High level icodes opcodes - def in file icode.h */
|
||||
struct HLICODE
|
||||
{
|
||||
/*typedef enum {
|
||||
HLI_ASSIGN,
|
||||
INC,
|
||||
DEC,
|
||||
HLI_JCOND,
|
||||
|
||||
} hlIcode; */
|
||||
|
||||
|
||||
typedef struct {
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
union { /* different operands */
|
||||
struct {
|
||||
@ -17,4 +25,12 @@ struct HLICODE
|
||||
COND_EXPR *exp; /* for HLI_JCOND, INC, DEC */
|
||||
} oper; /* operand */
|
||||
boolT valid; /* has a valid hlIcode */
|
||||
};
|
||||
} HLICODE;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Int numIcodes; /* No. of hlIcode reocrds written */
|
||||
Int numAlloc; /* No. of hlIcode records allocated */
|
||||
HLICODE *hlIcode; /* Array of high-level icodes */
|
||||
} HLICODEREC;
|
||||
|
||||
|
||||
788
include/icode.h
788
include/icode.h
@ -2,489 +2,367 @@
|
||||
* I-code related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <bitset>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <llvm/CodeGen/MachineInstr.h>
|
||||
#include <llvm/MC/MCInst.h>
|
||||
#include <llvm/MC/MCAsmInfo.h>
|
||||
#include <llvm/Value.h>
|
||||
#include <llvm/Instruction.h>
|
||||
#include <boost/range.hpp>
|
||||
#include "libdis.h"
|
||||
#include "Enums.h"
|
||||
|
||||
|
||||
/* LOW_LEVEL icode flags */
|
||||
#define B 0x000001 /* Byte operands (value implicitly used) */
|
||||
#define I 0x000002 /* Immed. source */
|
||||
#define NOT_HLL 0x000004 /* Not HLL inst. */
|
||||
#define FLOAT_OP 0x000008 /* ESC or WAIT */
|
||||
|
||||
#define SEG_IMMED 0x000010 /* Number is relocated segment value */
|
||||
#define IMPURE 0x000020 /* Instruction modifies code */
|
||||
#define WORD_OFF 0x000040 /* Inst has word offset ie.could be address */
|
||||
#define TERMINATES 0x000080 /* Instruction terminates program */
|
||||
|
||||
#define CASE 0x000100 /* Label as case part of switch */
|
||||
#define SWITCH 0x000200 /* Treat indirect JMP as switch stmt */
|
||||
#define TARGET 0x000400 /* Jump target */
|
||||
#define SYNTHETIC 0x000800 /* Synthetic jump instruction */
|
||||
#define NO_LABEL 0x001000 /* Immed. jump cannot be linked to a label */
|
||||
#define NO_CODE 0x002000 /* Hole in Icode array */
|
||||
#define SYM_USE 0x004000 /* Instruction uses a symbol */
|
||||
#define SYM_DEF 0x008000 /* Instruction defines a symbol */
|
||||
|
||||
#define NO_SRC 0x010000 /* Opcode takes no source */
|
||||
#define NO_OPS 0x020000 /* Opcode takes no operands */
|
||||
#define IM_OPS 0x040000 /* Opcode takes implicit operands */
|
||||
#define SRC_B 0x080000 /* Source operand is byte (dest is word) */
|
||||
#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */
|
||||
#define HLL_LABEL 0x100000 /* Icode has a high level language label */
|
||||
#define IM_DST 0x200000 /* Implicit DST for opcode (SIGNEX) */
|
||||
#define IM_SRC 0x400000 /* Implicit SRC for opcode (dx:ax) */
|
||||
#define IM_TMP_DST 0x800000 /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
|
||||
#define JMP_ICODE 0x1000000 /* Jmp dest immed.op converted to icode index */
|
||||
#define JX_LOOP 0x2000000 /* Cond jump is part of loop conditional exp */
|
||||
#define REST_STK 0x4000000 /* Stack needs to be restored after CALL */
|
||||
|
||||
/* Parser flags */
|
||||
#define TO_REG 0x000100 /* rm is source */
|
||||
#define S 0x000200 /* sign extend */
|
||||
#define OP386 0x000400 /* 386 op-code */
|
||||
#define NSP 0x000800 /* NOT_HLL if SP is src or dst */
|
||||
#define ICODEMASK 0xFF00FF /* Masks off parser flags */
|
||||
|
||||
/* LOW_LEVEL icode, DU flag bits */
|
||||
#define Cf 1
|
||||
#define Sf 2
|
||||
#define Zf 4
|
||||
#define Df 8
|
||||
|
||||
/* Machine registers */
|
||||
#define rAX 1 /* These are numbered relative to real 8086 */
|
||||
#define rCX 2
|
||||
#define rDX 3
|
||||
#define rBX 4
|
||||
#define rSP 5
|
||||
#define rBP 6
|
||||
#define rSI 7
|
||||
#define rDI 8
|
||||
|
||||
#define rES 9
|
||||
#define rCS 10
|
||||
#define rSS 11
|
||||
#define rDS 12
|
||||
|
||||
#define rAL 13
|
||||
#define rCL 14
|
||||
#define rDL 15
|
||||
#define rBL 16
|
||||
#define rAH 17
|
||||
#define rCH 18
|
||||
#define rDH 19
|
||||
#define rBH 20
|
||||
|
||||
#define rTMP 21 /* temp register for DIV/IDIV/MOD */
|
||||
#define INDEXBASE 22 /* Indexed modes go from INDEXBASE to
|
||||
* INDEXBASE+7 */
|
||||
|
||||
/* Byte and Word registers */
|
||||
static char *byteReg[9] = {"al", "cl", "dl", "bl",
|
||||
"ah", "ch", "dh", "bh", "tmp" };
|
||||
static char *wordReg[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
|
||||
"si", "di", "es", "cs", "ss", "ds",
|
||||
"", "", "", "", "", "", "", "", "tmp"};
|
||||
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
|
||||
//enum condId;
|
||||
/* Types of icodes */
|
||||
typedef enum {
|
||||
NOT_SCANNED = 0, /* not even scanned yet */
|
||||
LOW_LEVEL, /* low-level icode */
|
||||
HIGH_LEVEL /* high-level icode */
|
||||
} icodeType;
|
||||
|
||||
struct LOCAL_ID;
|
||||
struct BB;
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct CIcodeRec;
|
||||
struct ICODE;
|
||||
struct bundle;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
typedef std::list<ICODE>::reverse_iterator riICODE;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
extern std::bitset<32> duReg[30];
|
||||
/* uint8_t and uint16_t registers */
|
||||
|
||||
/* LOW_LEVEL icode opcodes */
|
||||
typedef enum {
|
||||
iCBW, /* 0 */
|
||||
iAAA,
|
||||
iAAD,
|
||||
iAAM,
|
||||
iAAS,
|
||||
iADC,
|
||||
iADD,
|
||||
iAND,
|
||||
iBOUND,
|
||||
iCALL,
|
||||
iCALLF, /* 10 */
|
||||
iCLC,
|
||||
iCLD,
|
||||
iCLI,
|
||||
iCMC,
|
||||
iCMP,
|
||||
iCMPS,
|
||||
iREPNE_CMPS,
|
||||
iREPE_CMPS,
|
||||
iDAA,
|
||||
iDAS, /* 20 */
|
||||
iDEC,
|
||||
iDIV,
|
||||
iENTER,
|
||||
iESC,
|
||||
iHLT,
|
||||
iIDIV,
|
||||
iIMUL,
|
||||
iIN,
|
||||
iINC,
|
||||
iINS, /* 30 */
|
||||
iREP_INS,
|
||||
iINT,
|
||||
iIRET,
|
||||
iJB,
|
||||
iJBE,
|
||||
iJAE,
|
||||
iJA,
|
||||
iJE,
|
||||
iJNE,
|
||||
iJL, /* 40 */
|
||||
iJGE,
|
||||
iJLE,
|
||||
iJG,
|
||||
iJS,
|
||||
iJNS,
|
||||
iJO,
|
||||
iJNO,
|
||||
iJP,
|
||||
iJNP,
|
||||
iJCXZ, /* 50 */
|
||||
iJMP,
|
||||
iJMPF,
|
||||
iLAHF,
|
||||
iLDS,
|
||||
iLEA,
|
||||
iLEAVE,
|
||||
iLES,
|
||||
iLOCK,
|
||||
iLODS,
|
||||
iREP_LODS, /* 60 */
|
||||
iLOOP,
|
||||
iLOOPE,
|
||||
iLOOPNE,
|
||||
iMOV, /* 64 */
|
||||
iMOVS,
|
||||
iREP_MOVS,
|
||||
iMUL, /* 67 */
|
||||
iNEG,
|
||||
iNOT,
|
||||
iOR, /* 70 */
|
||||
iOUT,
|
||||
iOUTS,
|
||||
iREP_OUTS,
|
||||
iPOP,
|
||||
iPOPA,
|
||||
iPOPF,
|
||||
iPUSH,
|
||||
iPUSHA,
|
||||
iPUSHF,
|
||||
iRCL, /* 80 */
|
||||
iRCR,
|
||||
iROL,
|
||||
iROR,
|
||||
iRET, /* 84 */
|
||||
iRETF,
|
||||
iSAHF,
|
||||
iSAR,
|
||||
iSHL,
|
||||
iSHR,
|
||||
iSBB, /* 90 */
|
||||
iSCAS,
|
||||
iREPNE_SCAS,
|
||||
iREPE_SCAS,
|
||||
iSIGNEX,
|
||||
iSTC,
|
||||
iSTD,
|
||||
iSTI,
|
||||
iSTOS,
|
||||
iREP_STOS,
|
||||
iSUB, /* 100 */
|
||||
iTEST,
|
||||
iWAIT,
|
||||
iXCHG,
|
||||
iXLAT,
|
||||
iXOR,
|
||||
iINTO,
|
||||
iNOP,
|
||||
iREPNE,
|
||||
iREPE,
|
||||
iMOD, /* 110 */
|
||||
} llIcode;
|
||||
|
||||
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
typedef enum {
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
HLI_RET, /* Return from procedure */
|
||||
/* pseudo high-level icodes */
|
||||
HLI_POP, /* Pop expression */
|
||||
HLI_PUSH, /* Push expression */
|
||||
} hlIcode;
|
||||
|
||||
|
||||
/* Operand is defined, used or both flag */
|
||||
typedef enum {
|
||||
DEF, /* Operand is defined */
|
||||
USE, /* Operand is used */
|
||||
USE_DEF, /* Operand is used and defined */
|
||||
NONE, /* No operation is required on this operand */
|
||||
} operDu;
|
||||
|
||||
// I can't believe these are necessary!
|
||||
#define E_DEF (operDu)DEF
|
||||
#define E_USE (operDu)USE
|
||||
#define E_NONE (operDu)NONE
|
||||
#define E_USE_DEF (operDu)USE_DEF
|
||||
|
||||
/* Def/use of flags - low 4 bits represent flags */
|
||||
struct DU
|
||||
{
|
||||
uint8_t d;
|
||||
uint8_t u;
|
||||
};
|
||||
typedef struct {
|
||||
byte d;
|
||||
byte u;
|
||||
} DU;
|
||||
typedef DU *PDU;
|
||||
|
||||
/* Def/Use of registers and stack variables */
|
||||
typedef struct {
|
||||
dword def; /* For Registers: position in dword is reg index*/
|
||||
dword lastDefRegi;/* Bit set if last def of this register in BB */
|
||||
dword use; /* For Registers: position in dword is reg index*/
|
||||
}DU_ICODE;
|
||||
|
||||
|
||||
/* Definition-use chain for level 1 (within a basic block) */
|
||||
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
|
||||
#define MAX_REGS_DEF 2 /* 2 regs def'd for long-reg vars */
|
||||
#define MAX_USES 5
|
||||
|
||||
typedef struct {
|
||||
Int numRegsDef; /* # registers defined by this inst */
|
||||
byte regi[MAX_REGS_DEF]; /* registers defined by this inst */
|
||||
Int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
|
||||
} DU1;
|
||||
|
||||
|
||||
struct COND_EXPR;
|
||||
struct HlTypeSupport
|
||||
{
|
||||
//hlIcode opcode; /* hlIcode opcode */
|
||||
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
|
||||
virtual std::string writeOut(Function *pProc, int *numLoc)=0;
|
||||
protected:
|
||||
void performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree);
|
||||
};
|
||||
/* LOW_LEVEL icode operand record */
|
||||
typedef struct {
|
||||
byte seg; /* CS, DS, ES, SS */
|
||||
int16 segValue; /* Value of segment seg during analysis */
|
||||
byte segOver; /* CS, DS, ES, SS if segment override */
|
||||
byte regi; /* 0 < regs < INDEXBASE <= index modes */
|
||||
int16 off; /* memory address offset */
|
||||
} ICODEMEM;
|
||||
typedef ICODEMEM *PMEM;
|
||||
|
||||
struct CallType : public HlTypeSupport
|
||||
/* LOW_LEVEL operand location: source or destination */
|
||||
typedef enum {
|
||||
SRC, /* Source operand */
|
||||
DST, /* Destination operand */
|
||||
LHS_OP, /* Left-hand side operand (for HIGH_LEVEL) */
|
||||
} opLoc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//for HLI_CALL
|
||||
Function * proc;
|
||||
STKFRAME * args; // actual arguments
|
||||
void allocStkArgs (int num);
|
||||
bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc);
|
||||
void placeStkArg(COND_EXPR *exp, int pos);
|
||||
virtual COND_EXPR * toId();
|
||||
public:
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
{
|
||||
printf("CallType : removeRegFromLong not supproted");
|
||||
return false;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc);
|
||||
};
|
||||
struct AssignType : public HlTypeSupport
|
||||
{
|
||||
/* for HLI_ASSIGN */
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
union { /* different operands */
|
||||
struct { /* for HLI_ASSIGN */
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
AssignType() : lhs(0),rhs(0) {}
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
{
|
||||
performLongRemoval(regi,locId,lhs);
|
||||
return true;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc);
|
||||
};
|
||||
struct ExpType : public HlTypeSupport
|
||||
{
|
||||
/* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
|
||||
COND_EXPR *v;
|
||||
ExpType() : v(0) {}
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
{
|
||||
performLongRemoval(regi,locId,v);
|
||||
return true;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc);
|
||||
};
|
||||
} asgn;
|
||||
COND_EXPR *exp; /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
|
||||
struct { /* for HLI_CALL */
|
||||
struct _proc *proc;
|
||||
struct _STKFRAME *args; /* actual arguments */
|
||||
} call;
|
||||
} oper; /* operand */
|
||||
} HLTYPE;
|
||||
|
||||
struct HLTYPE
|
||||
typedef struct
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
ExpType exp; /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
AssignType asgn;
|
||||
CallType call;
|
||||
HlTypeSupport *get()
|
||||
{
|
||||
switch(opcode)
|
||||
{
|
||||
case HLI_ASSIGN: return &asgn;
|
||||
case HLI_RET:
|
||||
case HLI_POP:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH: return &exp;
|
||||
case HLI_CALL: return &call;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void expr(COND_EXPR *e)
|
||||
{
|
||||
assert(e);
|
||||
exp.v=e;
|
||||
}
|
||||
void replaceExpr(COND_EXPR *e)
|
||||
{
|
||||
assert(e);
|
||||
delete exp.v;
|
||||
exp.v=e;
|
||||
}
|
||||
COND_EXPR * expr() { return exp.v;}
|
||||
const COND_EXPR * const expr() const { return exp.v;}
|
||||
void set(hlIcode i,COND_EXPR *e)
|
||||
{
|
||||
if(i!=HLI_RET)
|
||||
assert(e);
|
||||
assert(exp.v==0);
|
||||
opcode=i;
|
||||
exp.v=e;
|
||||
}
|
||||
void set(COND_EXPR *l,COND_EXPR *r)
|
||||
{
|
||||
assert(l);
|
||||
assert(r);
|
||||
opcode = HLI_ASSIGN;
|
||||
assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
||||
asgn.lhs=l;
|
||||
asgn.rhs=r;
|
||||
}
|
||||
HLTYPE(hlIcode op=HLI_INVALID) : opcode(op)
|
||||
{}
|
||||
HLTYPE & operator=(const HLTYPE &l)
|
||||
{
|
||||
exp=l.exp;
|
||||
opcode=l.opcode;
|
||||
asgn=l.asgn;
|
||||
call=l.call;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::string write1HlIcode(Function *pProc, int *numLoc);
|
||||
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs);
|
||||
} ;
|
||||
/* LOW_LEVEL icode operand record */
|
||||
struct LLOperand
|
||||
{
|
||||
llvm::MCOperand llvm_op;
|
||||
eReg seg; /* CS, DS, ES, SS */
|
||||
eReg segOver; /* CS, DS, ES, SS if segment override */
|
||||
int16_t segValue; /* Value of segment seg during analysis */
|
||||
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
|
||||
int16_t off; /* memory address offset */
|
||||
uint32_t opz; /* idx of immed src op */
|
||||
//union {/* Source operand if (flg & I) */
|
||||
llIcode opcode; /* llIcode instruction */
|
||||
byte numBytes; /* Number of bytes this instr */
|
||||
flags32 flg; /* icode flags */
|
||||
dword label; /* offset in image (20-bit adr) */
|
||||
ICODEMEM dst; /* destination operand */
|
||||
ICODEMEM src; /* source operand */
|
||||
union { /* Source operand if (flg & I) */
|
||||
dword op; /* idx of immed src op */
|
||||
struct { /* Call & # actual arg bytes */
|
||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
||||
int cb; /* # actual arg bytes */
|
||||
struct _proc *proc; /* ^ target proc (for CALL(F))*/
|
||||
Int cb; /* # actual arg bytes */
|
||||
} proc;
|
||||
LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0)
|
||||
{
|
||||
proc.proc=0;
|
||||
proc.cb=0;
|
||||
}
|
||||
int64_t getImm2() const {return opz;}
|
||||
void SetImmediateOp(uint32_t dw)
|
||||
{
|
||||
opz=dw;
|
||||
}
|
||||
eReg getReg2() {return regi;}
|
||||
bool isReg() const;
|
||||
static LLOperand CreateImm2(int64_t Val)
|
||||
{
|
||||
LLOperand Op;
|
||||
//Op.Kind = kImmediate;
|
||||
//Op.ImmVal = Val;
|
||||
Op.opz = Val;
|
||||
return Op;
|
||||
}
|
||||
static LLOperand CreateReg2(unsigned Val)
|
||||
{
|
||||
LLOperand Op;
|
||||
// Op.Kind = kRegister;
|
||||
// Op.RegVal = Reg;
|
||||
Op.regi = (eReg)Val;
|
||||
return Op;
|
||||
}
|
||||
void addProcInformation(int param_count,uint32_t call_conv);
|
||||
};
|
||||
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
|
||||
{
|
||||
protected:
|
||||
uint32_t flg; /* icode flags */
|
||||
LLOperand m_src; /* source operand */
|
||||
public:
|
||||
int codeIdx; /* Index into cCode.code */
|
||||
uint8_t numBytes; /* Number of bytes this instr */
|
||||
uint32_t label; /* offset in image (20-bit adr) */
|
||||
LLOperand dst; /* destination operand */
|
||||
} immed;
|
||||
DU flagDU; /* def/use of flags */
|
||||
int caseEntry;
|
||||
std::vector<uint32_t> caseTbl2;
|
||||
int hllLabNum; /* label # for hll codegen */
|
||||
bool conditionalJump()
|
||||
{
|
||||
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ);
|
||||
}
|
||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||
void setFlags(uint32_t flag) {flg |= flag;}
|
||||
void clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
uint32_t getFlag() const {return flg;}
|
||||
//llIcode getOpcode() const { return opcode; }
|
||||
struct { /* Case table if op==JMP && !I */
|
||||
Int numEntries; /* # entries in case table */
|
||||
dword *entries; /* array of offsets */
|
||||
} caseTbl;
|
||||
Int hllLabNum; /* label # for hll codegen */
|
||||
} LLTYPE;
|
||||
|
||||
uint32_t GetLlLabel() const { return label;}
|
||||
|
||||
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
||||
|
||||
|
||||
bool match(llIcode op)
|
||||
{
|
||||
return (getOpcode()==op);
|
||||
}
|
||||
bool match(llIcode op,eReg dest)
|
||||
{
|
||||
return (getOpcode()==op)&&dst.regi==dest;
|
||||
}
|
||||
bool match(llIcode op,eReg dest,uint32_t flgs)
|
||||
{
|
||||
return (getOpcode()==op) and (dst.regi==dest) and testFlags(flgs);
|
||||
}
|
||||
bool match(llIcode op,eReg dest,eReg src_reg)
|
||||
{
|
||||
return (getOpcode()==op)&&(dst.regi==dest)&&(m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest,eReg src_reg)
|
||||
{
|
||||
return (dst.regi==dest)&&(m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest)
|
||||
{
|
||||
return (dst.regi==dest);
|
||||
}
|
||||
bool match(llIcode op,uint32_t flgs)
|
||||
{
|
||||
return (getOpcode()==op) and testFlags(flgs);
|
||||
}
|
||||
void set(llIcode op,uint32_t flags)
|
||||
{
|
||||
setOpcode(op);
|
||||
flg =flags;
|
||||
}
|
||||
void emitGotoLabel(int indLevel);
|
||||
void findJumpTargets(CIcodeRec &_pc);
|
||||
void writeIntComment(std::ostringstream &s);
|
||||
void dis1Line(int loc_ip, int pass);
|
||||
std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false);
|
||||
|
||||
void flops(std::ostringstream &out);
|
||||
bool isJmpInst();
|
||||
HLTYPE toHighLevel(COND_EXPR *lhs, COND_EXPR *rhs, Function *func);
|
||||
HLTYPE createCall();
|
||||
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
|
||||
{
|
||||
setOpcode(0);
|
||||
}
|
||||
const LLOperand &src() const {return m_src;}
|
||||
LLOperand &src() {return m_src;}
|
||||
void replaceSrc(const LLOperand &with)
|
||||
{
|
||||
m_src = with;
|
||||
}
|
||||
void replaceSrc(eReg r)
|
||||
{
|
||||
m_src = LLOperand::CreateReg2(r);
|
||||
}
|
||||
void replaceSrc(int64_t r)
|
||||
{
|
||||
m_src = LLOperand::CreateImm2(r);
|
||||
}
|
||||
void replaceDst(const LLOperand &with)
|
||||
{
|
||||
dst = with;
|
||||
}
|
||||
void replaceDst(eReg r)
|
||||
{
|
||||
dst = LLOperand::CreateReg2(r);
|
||||
}
|
||||
ICODE *m_link;
|
||||
condId idType(opLoc sd) const;
|
||||
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &dst; }
|
||||
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &dst; }
|
||||
};
|
||||
|
||||
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
||||
struct ICODE
|
||||
{
|
||||
// use llvm names at least
|
||||
typedef BB MachineBasicBlock;
|
||||
protected:
|
||||
LLInst m_ll;
|
||||
HLTYPE m_hl;
|
||||
MachineBasicBlock * Parent; /* BB to which this icode belongs */
|
||||
bool invalid; /* Has no HIGH_LEVEL equivalent */
|
||||
public:
|
||||
x86_insn_t insn;
|
||||
template<int FLAG>
|
||||
struct FlagFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return ic->ll()->testFlags(FLAG);}
|
||||
bool operator()(ICODE &ic) {return ic.ll()->testFlags(FLAG);}
|
||||
};
|
||||
template<int TYPE>
|
||||
struct TypeFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;}
|
||||
bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;}
|
||||
};
|
||||
template<int TYPE>
|
||||
struct TypeAndValidFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return (ic->type==HIGH_LEVEL)&&(ic->valid());}
|
||||
bool operator()(ICODE &ic) {return (ic.type==HIGH_LEVEL)&&ic.valid();}
|
||||
};
|
||||
static TypeFilter<HIGH_LEVEL> select_high_level;
|
||||
static TypeAndValidFilter<HIGH_LEVEL> select_valid_high_level;
|
||||
/* Def/Use of registers and stack variables */
|
||||
struct DU_ICODE
|
||||
{
|
||||
DU_ICODE()
|
||||
{
|
||||
def.reset();
|
||||
use.reset();
|
||||
lastDefRegi.reset();
|
||||
}
|
||||
std::bitset<32> def; // For Registers: position in bitset is reg index
|
||||
std::bitset<32> use; // For Registers: position in uint32_t is reg index
|
||||
std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB
|
||||
void addDefinedAndUsed(eReg r)
|
||||
{
|
||||
def |= duReg[r];
|
||||
use |= duReg[r];
|
||||
|
||||
}
|
||||
};
|
||||
struct DU1
|
||||
{
|
||||
struct Use
|
||||
{
|
||||
int Reg; // used register
|
||||
std::vector<std::list<ICODE>::iterator> uses; // use locations [MAX_USES]
|
||||
void removeUser(std::list<ICODE>::iterator us)
|
||||
{
|
||||
// ic is no no longer an user
|
||||
auto iter=std::find(uses.begin(),uses.end(),us);
|
||||
if(iter==uses.end())
|
||||
return;
|
||||
uses.erase(iter);
|
||||
assert("Same user more then once!" && uses.end()==std::find(uses.begin(),uses.end(),us));
|
||||
}
|
||||
|
||||
};
|
||||
int numRegsDef; /* # registers defined by this inst */
|
||||
uint8_t regi[MAX_REGS_DEF+1]; /* registers defined by this inst */
|
||||
Use idx[MAX_REGS_DEF+1];
|
||||
//int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
|
||||
bool used(int regIdx)
|
||||
{
|
||||
return not idx[regIdx].uses.empty();
|
||||
}
|
||||
int numUses(int regIdx)
|
||||
{
|
||||
return idx[regIdx].uses.size();
|
||||
}
|
||||
void recordUse(int regIdx,std::list<ICODE>::iterator location)
|
||||
{
|
||||
idx[regIdx].uses.push_back(location);
|
||||
}
|
||||
void remove(int regIdx,int use_idx)
|
||||
{
|
||||
idx[regIdx].uses.erase(idx[regIdx].uses.begin()+use_idx);
|
||||
}
|
||||
void remove(int regIdx,std::list<ICODE>::iterator ic)
|
||||
{
|
||||
Use &u(idx[regIdx]);
|
||||
u.removeUser(ic);
|
||||
}
|
||||
DU1() : numRegsDef(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef struct {
|
||||
icodeType type; /* Icode type */
|
||||
boolT invalid; /* Has no HIGH_LEVEL equivalent */
|
||||
struct _BB *inBB; /* BB to which this icode belongs */
|
||||
DU_ICODE du; /* Def/use regs/vars */
|
||||
DU1 du1; /* du chain 1 */
|
||||
int loc_ip; // used by CICodeRec to number ICODEs
|
||||
Int codeIdx; /* Index into cCode.code */
|
||||
struct { /* Different types of icodes */
|
||||
LLTYPE ll;
|
||||
HLTYPE hl; /* For HIGH_LEVEL icodes */
|
||||
} ic; /* intermediate code */
|
||||
} ICODE;
|
||||
typedef ICODE* PICODE;
|
||||
|
||||
LLInst * ll() { return &m_ll;}
|
||||
const LLInst * ll() const { return &m_ll;}
|
||||
|
||||
HLTYPE * hl() { return &m_hl;}
|
||||
const HLTYPE * hl() const { return &m_hl;}
|
||||
void hl(const HLTYPE &v) { m_hl=v;}
|
||||
|
||||
void setRegDU(eReg regi, operDu du_in);
|
||||
void invalidate();
|
||||
void newCallHl();
|
||||
void writeDU();
|
||||
condId idType(opLoc sd);
|
||||
// HLL setting functions
|
||||
// set this icode to be an assign
|
||||
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
|
||||
{
|
||||
type=HIGH_LEVEL;
|
||||
hl()->setAsgn(lhs,rhs);
|
||||
}
|
||||
void setUnary(hlIcode op, COND_EXPR *_exp);
|
||||
void setJCond(COND_EXPR *cexp);
|
||||
|
||||
void emitGotoLabel(int indLevel);
|
||||
void copyDU(const ICODE &duIcode, operDu _du, operDu duDu);
|
||||
bool valid() {return not invalid;}
|
||||
void setParent(MachineBasicBlock *P) { Parent = P; }
|
||||
public:
|
||||
bool removeDefRegi(eReg regi, int thisDefIdx, LOCAL_ID *locId);
|
||||
void checkHlCall();
|
||||
bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc)
|
||||
{
|
||||
return hl()->call.newStkArg(exp,opcode,pproc);
|
||||
}
|
||||
ICODE() : m_ll(this),type(NOT_SCANNED),Parent(0),loc_ip(0),invalid(false)
|
||||
{
|
||||
}
|
||||
public:
|
||||
const MachineBasicBlock* getParent() const { return Parent; }
|
||||
MachineBasicBlock* getParent() { return Parent; }
|
||||
//unsigned getNumOperands() const { return (unsigned)Operands.size(); }
|
||||
|
||||
};
|
||||
/** Map n low level instructions to m high level instructions
|
||||
*/
|
||||
struct MappingLLtoML
|
||||
{
|
||||
typedef llvm::iplist<llvm::Instruction> InstListType;
|
||||
typedef boost::iterator_range<iICODE> rSourceRange;
|
||||
typedef boost::iterator_range<InstListType::iterator> rTargetRange;
|
||||
rSourceRange m_low_level;
|
||||
rTargetRange m_middle_level;
|
||||
};
|
||||
// This is the icode array object.
|
||||
class CIcodeRec : public std::list<ICODE>
|
||||
// The bulk of this could well be done with a class library
|
||||
class CIcodeRec
|
||||
{
|
||||
public:
|
||||
CIcodeRec(); // Constructor
|
||||
~CIcodeRec(); // Destructor
|
||||
|
||||
PICODE addIcode(PICODE pIcode);
|
||||
PICODE GetFirstIcode();
|
||||
// PICODE GetNextIcode(PICODE pCurIcode);
|
||||
boolT IsValid(PICODE pCurIcode);
|
||||
int GetNumIcodes();
|
||||
void SetInBB(int start, int end, struct _BB* pnewBB);
|
||||
void SetImmediateOp(int ip, dword dw);
|
||||
void SetLlFlag(int ip, dword flag);
|
||||
void ClearLlFlag(int ip, dword flag);
|
||||
dword GetLlFlag(int ip);
|
||||
void SetLlInvalid(int ip, boolT fInv);
|
||||
dword GetLlLabel(int ip);
|
||||
llIcode GetLlOpcode(int ip);
|
||||
boolT labelSrch(dword target, Int *pIndex);
|
||||
PICODE GetIcode(int ip);
|
||||
|
||||
protected:
|
||||
Int numIcode; /* # icodes in use */
|
||||
Int alloc; /* # icodes allocated */
|
||||
PICODE icode; /* Array of icodes */
|
||||
|
||||
ICODE * addIcode(ICODE *pIcode);
|
||||
void SetInBB(rCODE &rang, BB* pnewBB);
|
||||
bool labelSrch(uint32_t target, uint32_t &pIndex);
|
||||
iterator labelSrch(uint32_t target);
|
||||
ICODE * GetIcode(int ip);
|
||||
bool alreadyDecoded(uint32_t target);
|
||||
};
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom5 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom5() {}
|
||||
Idiom5(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom6 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom6() {}
|
||||
Idiom6(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom18 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[4];
|
||||
bool m_is_dec;
|
||||
public:
|
||||
Idiom18(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 4;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom19 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
bool m_is_dec;
|
||||
public:
|
||||
Idiom19(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom20 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[4];
|
||||
bool m_is_dec;
|
||||
public:
|
||||
Idiom20(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 4;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
struct CallIdiom : public Idiom
|
||||
{
|
||||
protected:
|
||||
int m_param_count;
|
||||
public:
|
||||
virtual ~CallIdiom() {}
|
||||
CallIdiom(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
struct Idiom3 : public CallIdiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom3() {}
|
||||
Idiom3(Function *f) : CallIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom17 : public CallIdiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
public:
|
||||
virtual ~Idiom17() {}
|
||||
Idiom17(Function *f) : CallIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
struct EpilogIdiom : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::deque<iICODE> m_icodes; // deque to push_front optional icodes from popStkVars
|
||||
void popStkVars (iICODE pIcode);
|
||||
public:
|
||||
virtual ~EpilogIdiom() {}
|
||||
EpilogIdiom(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
struct Idiom2 : public EpilogIdiom
|
||||
{
|
||||
virtual ~Idiom2() {}
|
||||
Idiom2(Function *f) : EpilogIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom4 : public EpilogIdiom
|
||||
{
|
||||
protected:
|
||||
int m_param_count;
|
||||
public:
|
||||
virtual ~Idiom4() {}
|
||||
Idiom4(Function *f) : EpilogIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
#include "icode.h"
|
||||
#include "Procedure.h"
|
||||
struct Idiom
|
||||
{
|
||||
protected:
|
||||
Function *m_func;
|
||||
iICODE m_end;
|
||||
public:
|
||||
Idiom(Function *f) : m_func(f),m_end(f->Icode.end())
|
||||
{
|
||||
}
|
||||
virtual uint8_t minimum_match_length()=0;
|
||||
virtual bool match(iICODE at)=0;
|
||||
virtual int action()=0;
|
||||
int operator ()(iICODE at)
|
||||
{
|
||||
if(match(at))
|
||||
return action();
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "idiom.h"
|
||||
struct Idiom1 : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
int m_min_off;
|
||||
int checkStkVars (iICODE pIcode);
|
||||
public:
|
||||
Idiom1(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
size_t match_length() {return m_icodes.size();}
|
||||
};
|
||||
@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom14 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
eReg m_regL;
|
||||
eReg m_regH;
|
||||
public:
|
||||
virtual ~Idiom14() {}
|
||||
Idiom14(Function *f) : Idiom(f),m_regL(rUNDEF),m_regH(rUNDEF)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom13 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
eReg m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom13() {}
|
||||
Idiom13(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom11 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[3];
|
||||
public:
|
||||
virtual ~Idiom11() {}
|
||||
Idiom11(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom16 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[3];
|
||||
public:
|
||||
virtual ~Idiom16() {}
|
||||
Idiom16(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@ -1,66 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom8 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
uint8_t m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom8() {}
|
||||
Idiom8(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom15 : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
public:
|
||||
virtual ~Idiom15() {}
|
||||
Idiom15(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom12 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
uint8_t m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom12() {}
|
||||
Idiom12(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
|
||||
struct Idiom9 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
uint8_t m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom9() {}
|
||||
Idiom9(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom21 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom21() {}
|
||||
Idiom21(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom7 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icode;
|
||||
public:
|
||||
virtual ~Idiom7() {}
|
||||
Idiom7(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom10 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom10() {}
|
||||
Idiom10(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@ -5,134 +5,106 @@
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* Type definition */
|
||||
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
|
||||
// TODO: why ?
|
||||
struct COND_EXPR;
|
||||
struct ICODE;
|
||||
struct LLInst;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
struct IDX_ARRAY : public std::vector<iICODE>
|
||||
{
|
||||
bool inList(iICODE idx)
|
||||
{
|
||||
return std::find(begin(),end(),idx)!=end();
|
||||
}
|
||||
};
|
||||
typedef struct {
|
||||
Int csym; /* # symbols used */
|
||||
Int alloc; /* # symbols allocated */
|
||||
Int *idx; /* Array of integer indexes */
|
||||
} IDX_ARRAY;
|
||||
|
||||
/* Type definitions used in the decompiled program */
|
||||
typedef enum {
|
||||
TYPE_UNKNOWN = 0, /* unknown so far */
|
||||
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
|
||||
TYPE_BYTE_UNSIGN, /* unsigned byte */
|
||||
TYPE_WORD_SIGN, /* signed word (16 bits) */
|
||||
TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */
|
||||
TYPE_LONG_SIGN, /* signed long (32 bits) */
|
||||
TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */
|
||||
TYPE_RECORD, /* record structure */
|
||||
TYPE_PTR, /* pointer (32 bit ptr) */
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE, /* double precision float */
|
||||
} hlType;
|
||||
|
||||
static char *hlTypes[13] = {"", "char", "unsigned char", "int", "unsigned int",
|
||||
"long", "unsigned long", "record", "int *", "char *",
|
||||
"", "float", "double"};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STK_FRAME, /* For stack vars */
|
||||
REG_FRAME, /* For register variables */
|
||||
GLB_FRAME /* For globals */
|
||||
GLB_FRAME, /* For globals */
|
||||
} frameType;
|
||||
|
||||
|
||||
/* Enumeration to determine whether pIcode points to the high or low part
|
||||
* of a long number */
|
||||
typedef enum {
|
||||
HIGH_FIRST, /* High value is first */
|
||||
LOW_FIRST, /* Low value is first */
|
||||
} hlFirst;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16_t seg; /* segment value */
|
||||
int16_t off; /* offset */
|
||||
eReg regi; /* optional indexed register */
|
||||
int16 seg; /* segment value */
|
||||
int16 off; /* offset */
|
||||
byte regi; /* optional indexed register */
|
||||
} BWGLB_TYPE;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
int offH; /* high offset from BP */
|
||||
int offL; /* low offset from BP */
|
||||
Int offH; /* high offset from BP */
|
||||
Int offL; /* low offset from BP */
|
||||
} LONG_STKID_TYPE;
|
||||
struct LONGID_TYPE
|
||||
typedef struct
|
||||
{ /* For TYPE_LONG_(UN)SIGN registers */
|
||||
eReg h; /* high register */
|
||||
eReg l; /* low register */
|
||||
bool srcDstRegMatch(iICODE a,iICODE b) const;
|
||||
};
|
||||
byte h; /* high register */
|
||||
byte l; /* low register */
|
||||
} LONGID_TYPE;
|
||||
|
||||
|
||||
/* ID, LOCAL_ID */
|
||||
struct ID
|
||||
{
|
||||
typedef struct {
|
||||
hlType type; /* Probable type */
|
||||
bool illegal; /* Boolean: not a valid field any more */
|
||||
//std::vector<iICODE> idx;
|
||||
boolT illegal;/* Boolean: not a valid field any more */
|
||||
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
|
||||
frameType loc; /* Frame location */
|
||||
bool hasMacro; /* Identifier requires a macro */
|
||||
char macro[10]; /* Macro for this identifier */
|
||||
std::string name; /* Identifier's name */
|
||||
boolT hasMacro;/* Identifier requires a macro */
|
||||
char macro[10];/* Macro for this identifier */
|
||||
char name[20];/* Identifier's name */
|
||||
union { /* Different types of identifiers */
|
||||
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
|
||||
uint8_t regOff; /* register offset (if any) */
|
||||
int off; /* offset from BP */
|
||||
byte regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
|
||||
byte regOff; /* register offset (if any) */
|
||||
Int off; /* offset from BP */
|
||||
} bwId;
|
||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
|
||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(WORD)_(UN)SIGN globals */
|
||||
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
LONG_STKID_TYPE longStkId;/* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
struct { /* For TYPE_LONG_(UN)SIGN globals */
|
||||
int16_t seg; /* segment value */
|
||||
int16_t offH; /* offset high */
|
||||
int16_t offL; /* offset low */
|
||||
uint8_t regi; /* optional indexed register */
|
||||
int16 seg; /* segment value */
|
||||
int16 offH; /* offset high */
|
||||
int16 offL; /* offset low */
|
||||
byte regi; /* optional indexed register */
|
||||
} longGlb;
|
||||
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
||||
uint32_t h; /* high uint16_t */
|
||||
uint32_t l; /* low uint16_t */
|
||||
dword h; /* high word */
|
||||
dword l; /* low word */
|
||||
} longKte;
|
||||
} id;
|
||||
ID();
|
||||
ID(hlType t, frameType f);
|
||||
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);}
|
||||
uint16_t typeBitsize() const
|
||||
{
|
||||
return TypeContainer::typeSize(type)*8;
|
||||
}
|
||||
void setLocalName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "loc%ld", i);
|
||||
name=buf;
|
||||
}
|
||||
};
|
||||
} ID;
|
||||
|
||||
struct LOCAL_ID
|
||||
{
|
||||
std::vector<ID> id_arr;
|
||||
protected:
|
||||
int newLongIdx(int16_t seg, int16_t offH, int16_t offL, uint8_t regi, hlType t);
|
||||
int newLongGlb(int16_t seg, int16_t offH, int16_t offL, hlType t);
|
||||
int newLongStk(hlType t, int offH, int offL);
|
||||
public:
|
||||
LOCAL_ID()
|
||||
{
|
||||
id_arr.reserve(256);
|
||||
}
|
||||
// interface to allow range based iteration
|
||||
std::vector<ID>::iterator begin() {return id_arr.begin();}
|
||||
std::vector<ID>::iterator end() {return id_arr.end();}
|
||||
int newByteWordReg(hlType t, eReg regi);
|
||||
int newByteWordStk(hlType t, int off, uint8_t regOff);
|
||||
int newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t);
|
||||
int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_);
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, int off);
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
void newIdent(hlType t, frameType f);
|
||||
void flagByteWordId(int off);
|
||||
void propLongId(uint8_t regL, uint8_t regH, const char *name);
|
||||
size_t csym() const {return id_arr.size();}
|
||||
void newRegArg(iICODE picode, iICODE ticode) const;
|
||||
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const;
|
||||
void forwardSubs(COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const;
|
||||
COND_EXPR *createId(const ID *retVal, iICODE ix_);
|
||||
};
|
||||
typedef struct {
|
||||
Int csym; /* No. of symbols in the table */
|
||||
Int alloc; /* No. of symbols allocated */
|
||||
ID *id; /* Identifier */
|
||||
} LOCAL_ID;
|
||||
|
||||
|
||||
|
||||
@ -1,82 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
/* Machine registers */
|
||||
enum eReg
|
||||
{
|
||||
rUNDEF = 0,
|
||||
rAX = 1, /* These are numbered relative to real 8086 */
|
||||
rCX = 2,
|
||||
rDX = 3,
|
||||
rBX = 4,
|
||||
rSP = 5,
|
||||
rBP = 6,
|
||||
rSI = 7,
|
||||
rDI = 8,
|
||||
|
||||
rES = 9,
|
||||
rCS = 10,
|
||||
rSS = 11,
|
||||
rDS = 12,
|
||||
|
||||
rAL = 13,
|
||||
rCL = 14,
|
||||
rDL = 15,
|
||||
rBL = 16,
|
||||
rAH = 17,
|
||||
rCH = 18,
|
||||
rDH = 19,
|
||||
rBH = 20,
|
||||
|
||||
rTMP= 21, /* temp register for DIV/IDIV/MOD */
|
||||
/* Indexed modes go from INDEXBASE to INDEXBASE+7 */
|
||||
INDEX_BX_SI = 22, // "bx+si"
|
||||
INDEX_BX_DI, // "bx+di"
|
||||
INDEX_BP_SI, // "bp+si"
|
||||
INDEX_BP_DI, // "bp+di"
|
||||
INDEX_SI, // "si"
|
||||
INDEX_DI, // "di"
|
||||
INDEX_BP, // "bp"
|
||||
INDEX_BX, // "bx"
|
||||
LAST_REG
|
||||
};
|
||||
class SourceMachine
|
||||
{
|
||||
public:
|
||||
virtual bool physicalReg(eReg r)=0;
|
||||
|
||||
};
|
||||
//class Machine_X86_Disassembler
|
||||
//{
|
||||
// void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm);
|
||||
//};
|
||||
class Machine_X86 : public SourceMachine
|
||||
{
|
||||
public:
|
||||
Machine_X86();
|
||||
virtual ~Machine_X86() {}
|
||||
static const std::string ®Name(eReg r);
|
||||
static const std::string &opcodeName(unsigned r);
|
||||
static const std::string &floatOpName(unsigned r);
|
||||
bool physicalReg(eReg r);
|
||||
/* Writes the registers that are set in the bitvector */
|
||||
//TODO: move this into Machine_X86 ?
|
||||
static void writeRegVector (std::ostream &ostr,const std::bitset<32> ®i)
|
||||
{
|
||||
int j;
|
||||
for (j = rAX; j < INDEX_BX_SI; j++)
|
||||
{
|
||||
if (regi.test(j-1))
|
||||
ostr << regName(eReg(j))<<" ";
|
||||
}
|
||||
}
|
||||
static eReg subRegH(eReg reg); //TODO: move these into machine_x86
|
||||
static eReg subRegL(eReg reg);
|
||||
|
||||
static bool isMemOff(eReg r);
|
||||
static bool isSubRegisterOf(eReg reg, eReg parent);
|
||||
|
||||
};
|
||||
@ -1,41 +1,34 @@
|
||||
#pragma once
|
||||
/* Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
//#define bool unsigned char
|
||||
#define uint8_t unsigned char
|
||||
#define uint16_t unsigned short
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define bool unsigned char
|
||||
#define byte unsigned char
|
||||
#define word unsigned short
|
||||
|
||||
/* Prototypes */
|
||||
void hashParams(int NumEntry, int EntryLen, int SetSize, char SetMin,
|
||||
int NumVert); /* Set the parameters for the hash table */
|
||||
void hashCleanup(void); /* Frees memory allocated by hashParams() */
|
||||
void map(void); /* Part 1 of creating the tables */
|
||||
void assign(void); /* Part 2 of creating the tables */
|
||||
int hash(byte *s); /* Hash the string to an int 0 .. NUMENTRY-1 */
|
||||
|
||||
word *readT1(void); /* Returns a pointer to the T1 table */
|
||||
word *readT2(void); /* Returns a pointer to the T2 table */
|
||||
word *readG(void); /* Returns a pointer to the g table */
|
||||
|
||||
|
||||
/* The application must provide these functions: */
|
||||
void getKey(int i, uint8_t **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void getKey(int i, byte **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void dispKey(int i); /* Display the key */
|
||||
class PatternHasher
|
||||
{
|
||||
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
int *graphNode; /* The array of edges */
|
||||
int *graphNext; /* Linked list of edges */
|
||||
int *graphFirst;/* First edge at a vertex */
|
||||
public:
|
||||
uint16_t *readT1(void); /* Returns a pointer to the T1 table */
|
||||
uint16_t *readT2(void); /* Returns a pointer to the T2 table */
|
||||
uint16_t *readG(void); /* Returns a pointer to the g table */
|
||||
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
|
||||
void cleanup();
|
||||
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
|
||||
};
|
||||
extern PatternHasher g_pattern_hasher;
|
||||
/* Macro reads a LH uint16_t from the image regardless of host convention */
|
||||
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
#ifndef LH
|
||||
#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
|
||||
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
|
||||
#endif
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include "symtab.h"
|
||||
#include "BinaryImage.h"
|
||||
struct Function;
|
||||
struct SourceMachine;
|
||||
struct CALL_GRAPH;
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
|
||||
struct Project
|
||||
{
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
|
||||
std::string m_fname;
|
||||
FunctionListType pProcList;
|
||||
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
Project() {}
|
||||
// no copies
|
||||
Project(const Project&) = delete;
|
||||
const Project &operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(Project && l)
|
||||
{
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
}
|
||||
Project &operator=(Project && l)
|
||||
{
|
||||
if(this == &l)
|
||||
return *this;
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
ilFunction funcIter(Function *to_find);
|
||||
ilFunction findByEntry(uint32_t entry);
|
||||
ilFunction createFunction();
|
||||
bool valid(ilFunction iter);
|
||||
|
||||
int getSymIdxByAdd(uint32_t adr);
|
||||
bool validSymIdx(size_t idx);
|
||||
size_t symbolSize(size_t idx);
|
||||
hlType symbolType(size_t idx);
|
||||
const std::string &symbolName(size_t idx);
|
||||
const SYM &getSymByIdx(size_t idx) const;
|
||||
|
||||
static Project *get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
|
||||
protected:
|
||||
void writeGlobSymTable();
|
||||
};
|
||||
//extern Project g_proj;
|
||||
@ -1,12 +1,38 @@
|
||||
#pragma once
|
||||
/* Scanner functions
|
||||
* (C) Cristina Cifuentes, Jeff Ledermann
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
|
||||
#define REG(x) ((uint8_t)(x & 0x38) >> 3)
|
||||
|
||||
struct ICODE;
|
||||
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
|
||||
|
||||
extern eErrorId scan(uint32_t ip, ICODE &p);
|
||||
static void rm(Int i);
|
||||
static void modrm(Int i);
|
||||
static void segrm(Int i);
|
||||
static void data1(Int i);
|
||||
static void data2(Int i);
|
||||
static void regop(Int i);
|
||||
static void segop(Int i);
|
||||
static void strop(Int i);
|
||||
static void escop(Int i);
|
||||
static void axImp(Int i);
|
||||
static void alImp(Int i);
|
||||
static void axSrcIm(Int i);
|
||||
static void memImp(Int i);
|
||||
static void memReg0(Int i);
|
||||
static void memOnly(Int i);
|
||||
static void dispM(Int i);
|
||||
static void dispS(Int i);
|
||||
static void dispN(Int i);
|
||||
static void dispF(Int i);
|
||||
static void prefix(Int i);
|
||||
static void immed(Int i);
|
||||
static void shift(Int i);
|
||||
static void arith(Int i);
|
||||
static void trans(Int i);
|
||||
static void const1(Int i);
|
||||
static void const3(Int i);
|
||||
static void none1(Int i);
|
||||
static void none2(Int i);
|
||||
static void checkInt(Int i);
|
||||
|
||||
/* Extracts reg bits from middle of mod-reg-rm byte */
|
||||
#define REG(x) ((byte)(x & 0x38) >> 3)
|
||||
|
||||
@ -2,34 +2,18 @@
|
||||
* dcc project header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* STATE TABLE */
|
||||
struct STATE
|
||||
typedef struct
|
||||
{
|
||||
uint32_t IP; /* Offset into Image */
|
||||
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
|
||||
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
|
||||
dword IP; /* Offset into Image */
|
||||
int16 r[INDEXBASE]; /* Value of segs and AX */
|
||||
byte f[INDEXBASE]; /* True if r[.] has a value */
|
||||
struct
|
||||
{ /* For case stmt indexed reg */
|
||||
uint8_t regi; /* Last conditional jump */
|
||||
int16_t immed; /* Contents of the previous register */
|
||||
byte regi; /* Last conditional jump */
|
||||
int16 immed; /* Contents of the previous register */
|
||||
} JCond;
|
||||
void setState(uint16_t reg, int16_t value);
|
||||
void checkStartup();
|
||||
bool isKnown(eReg v) {return f[v];}
|
||||
void kill(eReg v) { f[v]=false;}
|
||||
STATE() : IP(0)
|
||||
{
|
||||
JCond.regi=0;
|
||||
JCond.immed=0;
|
||||
|
||||
memset(r,0,sizeof(int16_t)*INDEX_BX_SI); //TODO: move this to machine_x86
|
||||
memset(f,0,sizeof(uint8_t)*INDEX_BX_SI);
|
||||
}
|
||||
};
|
||||
|
||||
} STATE;
|
||||
typedef STATE *PSTATE;
|
||||
|
||||
|
||||
116
include/symtab.h
116
include/symtab.h
@ -2,112 +2,42 @@
|
||||
* Symbol table prototypes
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
struct COND_EXPR;
|
||||
struct TypeContainer;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
/* Symbol table structs and protos */
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
struct SymbolCommon
|
||||
{
|
||||
std::string name; /* New name for this variable/symbol/argument */
|
||||
int size; /* Size/maximum size */
|
||||
hlType type; /* probable type */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
SymbolCommon() : size(0),type(TYPE_UNKNOWN)
|
||||
{}
|
||||
};
|
||||
struct SYM : public SymbolCommon
|
||||
{
|
||||
SYM() : label(0),flg(0)
|
||||
{
|
||||
|
||||
}
|
||||
int32_t label; /* physical address (20 bit) */
|
||||
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
};
|
||||
/* STACK FRAME */
|
||||
struct STKSYM : public SymbolCommon
|
||||
typedef struct
|
||||
{
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16_t label; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro; /* This type needs a macro */
|
||||
std::string macro; /* Macro name */
|
||||
bool invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
STKSYM()
|
||||
{
|
||||
actual=regs=0;
|
||||
label=0;
|
||||
regOff=0;
|
||||
invalid=hasMacro = false;
|
||||
}
|
||||
void setArgName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "arg%d", i);
|
||||
name = buf;
|
||||
}
|
||||
};
|
||||
template<class T>
|
||||
class SymbolTableCommon : public std::vector<T>
|
||||
{
|
||||
public:
|
||||
typedef typename std::vector<T>::iterator iterator;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
iterator findByLabel(int lab)
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
const_iterator findByLabel(int lab) const
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](const T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
char *pSymName; /* Ptr to symbolic name or comment */
|
||||
dword symOff; /* Symbol image offset */
|
||||
PPROC symProc; /* Procedure pointer */
|
||||
word preHash; /* Hash value before the modulo */
|
||||
word postHash; /* Hash value after the modulo */
|
||||
word nextOvf; /* Next entry this hash bucket, or -1 */
|
||||
word prevOvf; /* Back link in Ovf chain */
|
||||
} SYMTABLE;
|
||||
|
||||
};
|
||||
/* SYMBOL TABLE */
|
||||
class SYMTAB : public SymbolTableCommon<SYM>
|
||||
{
|
||||
|
||||
public:
|
||||
void updateSymType(uint32_t symbol, const TypeContainer &tc);
|
||||
SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new);
|
||||
};
|
||||
struct Function;
|
||||
struct SYMTABLE
|
||||
{
|
||||
std::string pSymName; /* Ptr to symbolic name or comment */
|
||||
uint32_t symOff; /* Symbol image offset */
|
||||
Function *symProc; /* Procedure pointer */
|
||||
SYMTABLE() : symOff(0),symProc(0) {}
|
||||
SYMTABLE(uint32_t _sym,Function *_proc) : symOff(_sym),symProc(_proc)
|
||||
{}
|
||||
bool operator == (const SYMTABLE &other) const
|
||||
{
|
||||
// does not yse pSymName, to ease finding by symOff/symProc combo
|
||||
// in map<SYMTABLE,X>
|
||||
return (symOff==other.symOff) && symProc==(other.symProc);
|
||||
}
|
||||
};
|
||||
|
||||
enum tableType /* The table types */
|
||||
enum _tableType /* The table types */
|
||||
{
|
||||
Label=0, /* The label table */
|
||||
Comment, /* The comment table */
|
||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||
};
|
||||
|
||||
typedef enum _tableType tableType; /* For convenience */
|
||||
|
||||
void createSymTables(void);
|
||||
void destroySymTables(void);
|
||||
boolT readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc);
|
||||
void enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo);
|
||||
boolT readSym (char *symName, dword *pSymOff, PPROC *pSymProc);
|
||||
boolT readVal (char *symName, dword symOff, PPROC symProc);
|
||||
void deleteSym(char *symName);
|
||||
void deleteVal(dword symOff, PPROC symProc, boolT bSymToo);
|
||||
boolT findVal(dword symOff, PPROC symProc, word *pIndex);
|
||||
word symHash(char *name, word *pre);
|
||||
word valHash(dword off, PPROC proc, word *pre);
|
||||
void selectTable(tableType); /* Select a particular table */
|
||||
|
||||
char *addStrTbl(char *pStr); /* Add string to string table */
|
||||
|
||||
|
||||
@ -2,12 +2,19 @@
|
||||
* dcc project general header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <cassert>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
|
||||
/**** Common definitions and macros ****/
|
||||
#ifdef __MSDOS__ /* Intel: 16 bit integer */
|
||||
typedef long Int; /* Int: 0x80000000..0x7FFFFFFF */
|
||||
typedef unsigned long flags32; /* 32 bits */
|
||||
typedef unsigned long dword; /* 32 bits */
|
||||
#define MAX 0x7FFFFFFF
|
||||
#else /* Unix: 32 bit integer */
|
||||
typedef int Int; /* Int: 0x80000000..0x7FFFFFFF */
|
||||
typedef unsigned int flags32; /* 32 bits */
|
||||
typedef unsigned int dword; /* 32 bits */
|
||||
#define MAX 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
/* Type definitions used in the program */
|
||||
typedef unsigned char byte; /* 8 bits */
|
||||
@ -15,6 +22,14 @@ typedef unsigned short word;/* 16 bits */
|
||||
typedef short int16; /* 16 bits */
|
||||
typedef unsigned char boolT; /* 8 bits */
|
||||
|
||||
#if defined(__MSDOS__) | defined(WIN32)
|
||||
#define unlink _unlink // Compiler is picky about non Ansi names
|
||||
#endif
|
||||
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */
|
||||
|
||||
/* These are for C library signature detection */
|
||||
@ -24,15 +39,17 @@ typedef unsigned char boolT; /* 8 bits */
|
||||
|
||||
/****** MACROS *******/
|
||||
|
||||
/* Macro to allocate a node of size sizeof(structType). */
|
||||
#define allocStruc(structType) (structType *)allocMem(sizeof(structType))
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
/* Returns a 16 bit quantity, e.g. C000 is read into an Int as C000 */
|
||||
//#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
|
||||
#define LH(p) ((word)((byte *)(p))[0] + ((word)((byte *)(p))[1] << 8))
|
||||
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
/* Returns a signed quantity, e.g. C000 is read into an Int as FFFFC000 */
|
||||
#define LH_SIGNED(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
|
||||
#define LHS(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
|
||||
|
||||
/* Macro tests bit b for type t in prog.map */
|
||||
#define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1)))
|
||||
@ -40,68 +57,3 @@ typedef unsigned char boolT; /* 8 bits */
|
||||
/* Macro to convert a segment, offset definition into a 20 bit address */
|
||||
#define opAdr(seg,off) ((seg << 4) + off)
|
||||
|
||||
/* duVal FLAGS */
|
||||
struct eDuVal
|
||||
{
|
||||
eDuVal()
|
||||
{
|
||||
def=use=val=0;
|
||||
}
|
||||
enum flgs
|
||||
{
|
||||
DEF=1,
|
||||
USE=2,
|
||||
VAL=4
|
||||
};
|
||||
int def :1; /* Variable was first defined than used */
|
||||
int use :1; /* Variable was first used than defined */
|
||||
int val :1; /* Variable has an initial value. 2 cases:
|
||||
* 1. When variable is used first (ie. global)
|
||||
* 2. When a value is moved into the variable
|
||||
* for the first time. */
|
||||
void setFlags(uint16_t x)
|
||||
{
|
||||
def = x&DEF;
|
||||
use = x&USE;
|
||||
val = x&VAL;
|
||||
}
|
||||
bool isUSE_VAL() {return use&&val;} /* Use and Val */
|
||||
};
|
||||
static constexpr const char * hlTypes[13] = {
|
||||
"", "char", "unsigned char", "int", "unsigned int",
|
||||
"long", "unsigned long", "record", "int *", "char *",
|
||||
"", "float", "double"
|
||||
};
|
||||
|
||||
struct TypeContainer
|
||||
{
|
||||
hlType m_type;
|
||||
size_t m_size;
|
||||
TypeContainer(hlType t,size_t sz) : m_type(t),m_size(sz)
|
||||
{
|
||||
}
|
||||
static size_t typeSize(hlType t)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
return 2;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static hlType defaultTypeForSize(size_t x)
|
||||
{
|
||||
/* Type of the symbol according to the number of bytes it uses */
|
||||
static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN,
|
||||
TYPE_UNKNOWN, TYPE_LONG_SIGN};
|
||||
|
||||
assert(x < sizeof(cbType)/sizeof(hlType));
|
||||
return cbType[x];
|
||||
}
|
||||
static constexpr const char *typeName(hlType t)
|
||||
{
|
||||
return hlTypes[t];
|
||||
}
|
||||
};
|
||||
|
||||
BIN
prototypes/dcclibs.dat
Normal file
BIN
prototypes/dcclibs.dat
Normal file
Binary file not shown.
BIN
sigs/dccb2s.sig
Normal file
BIN
sigs/dccb2s.sig
Normal file
Binary file not shown.
@ -1,443 +0,0 @@
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include "BasicBlock.h"
|
||||
#include "Procedure.h"
|
||||
#include "dcc.h"
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
|
||||
{
|
||||
BB *pnewBB = new BB;
|
||||
pnewBB->Parent = parent;
|
||||
return pnewBB;
|
||||
}
|
||||
/**
|
||||
* @arg start - basic block starts here, might be parent->Icode.end()
|
||||
* @arg fin - last of basic block's instructions
|
||||
*/
|
||||
BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
{
|
||||
BB* pnewBB;
|
||||
pnewBB = new BB;
|
||||
pnewBB->nodeType = _nodeType; /* Initialise */
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
pnewBB->instructions = make_iterator_range(start,fin);
|
||||
if(start==parent->Icode.end())
|
||||
{
|
||||
pnewBB->instructions = make_iterator_range(parent->Icode.end(),parent->Icode.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
pnewBB->instructions.advance_end(1); // 1 after fin, to create range where fin is inclusive
|
||||
}
|
||||
if (numOutEdges)
|
||||
pnewBB->edges.resize(numOutEdges);
|
||||
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if(parent)
|
||||
{
|
||||
if (start != parent->Icode.end())
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
parent->heldBBs.push_back(pnewBB);
|
||||
parent->m_cfg.push_back(pnewBB);
|
||||
pnewBB->Parent = parent;
|
||||
}
|
||||
if ( start != parent->Icode.end() ) /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
return pnewBB;
|
||||
}
|
||||
BB *BB::Create(int start, int ip, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
{
|
||||
iICODE st(parent->Icode.begin());
|
||||
iICODE fin(parent->Icode.begin());
|
||||
if(start==-1)
|
||||
{
|
||||
st = parent->Icode.end();
|
||||
fin = parent->Icode.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
advance(st,start);
|
||||
advance(fin,ip);
|
||||
}
|
||||
return Create(st,fin,_nodeType,numOutEdges,parent);
|
||||
}
|
||||
|
||||
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
|
||||
"loop", "repeat", "interval", "cycleHead",
|
||||
"caseHead", "terminate",
|
||||
"nowhere" };
|
||||
|
||||
static const char *const s_loopType[] = {"noLoop", "while", "repeat", "loop", "for"};
|
||||
|
||||
|
||||
void BB::display()
|
||||
{
|
||||
printf("\nnode type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #out edges = %ld\n", begin()->loc_ip, size(), edges.size());
|
||||
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if(edges[i].BBptr==0)
|
||||
printf(" outEdge[%2d] = Unlinked out edge to %d\n",i, edges[i].ip);
|
||||
else
|
||||
printf(" outEdge[%2d] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
|
||||
}
|
||||
}
|
||||
/*****************************************************************************
|
||||
* displayDfs - Displays the CFG using a depth first traversal
|
||||
****************************************************************************/
|
||||
void BB::displayDfs()
|
||||
{
|
||||
int i;
|
||||
assert(this);
|
||||
traversed = DFS_DISP;
|
||||
|
||||
printf("node type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
|
||||
begin()->loc_ip, size(), inEdges.size(), edges.size());
|
||||
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
|
||||
dfsFirstNum, dfsLastNum,
|
||||
immedDom == MAX ? -1 : immedDom);
|
||||
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
|
||||
s_loopType[loopType],
|
||||
loopHead == MAX ? -1 : loopHead,
|
||||
latchNode == MAX ? -1 : latchNode,
|
||||
loopFollow == MAX ? -1 : loopFollow);
|
||||
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
|
||||
ifFollow == MAX ? -1 : ifFollow,
|
||||
caseHead == MAX ? -1 : caseHead,
|
||||
caseTail == MAX ? -1 : caseTail);
|
||||
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf("corresponding interval = %ld\n", correspInt->numInt);
|
||||
else
|
||||
{
|
||||
int edge_idx=0;
|
||||
for(BB *node : inEdges)
|
||||
{
|
||||
printf (" inEdge[%ld] = %ld\n", edge_idx, node->begin()->loc_ip);
|
||||
edge_idx++;
|
||||
}
|
||||
}
|
||||
/* Display out edges information */
|
||||
i=0;
|
||||
for(TYPEADR_TYPE &edg : edges)
|
||||
{
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf(" outEdge[%ld] = %ld\n", i, edg.BBptr->correspInt->numInt);
|
||||
else
|
||||
printf(" outEdge[%d] = %ld\n", i, edg.BBptr->begin()->loc_ip);
|
||||
++i;
|
||||
}
|
||||
printf("----\n");
|
||||
|
||||
/* Recursive call on successors of current node */
|
||||
for(TYPEADR_TYPE &pb : edges)
|
||||
{
|
||||
if (pb.BBptr->traversed != DFS_DISP)
|
||||
pb.BBptr->displayDfs();
|
||||
}
|
||||
}
|
||||
/* Recursive procedure that writes the code for the given procedure, pointed
|
||||
* to by pBB.
|
||||
* Parameters: pBB: pointer to the cfg.
|
||||
* Icode: pointer to the Icode array for the cfg graph of the
|
||||
* current procedure.
|
||||
* indLevel: indentation level - used for formatting.
|
||||
* numLoc: last # assigned to local variables */
|
||||
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond)
|
||||
{
|
||||
latch = pProc->m_dfsLast[this->latchNode];
|
||||
std::ostringstream ostr;
|
||||
ICODE* picode;
|
||||
switch (loopType)
|
||||
{
|
||||
case WHILE_TYPE:
|
||||
picode = &this->back();
|
||||
|
||||
/* Check for error in while condition */
|
||||
if (picode->hl()->opcode != HLI_JCOND)
|
||||
reportError (WHILE_FAIL);
|
||||
|
||||
/* Check if condition is more than 1 HL instruction */
|
||||
if (numHlIcodes > 1)
|
||||
{
|
||||
/* Write the code for this basic block */
|
||||
writeBB(ostr,indLevel, pProc, numLoc);
|
||||
repCond = true;
|
||||
}
|
||||
|
||||
/* Condition needs to be inverted if the loop body is along
|
||||
* the THEN path of the header node */
|
||||
if (edges[ELSE].BBptr->dfsLastNum == loopFollow)
|
||||
{
|
||||
picode->hl()->replaceExpr(picode->hl()->expr()->inverse());
|
||||
}
|
||||
{
|
||||
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
|
||||
ostr << "\n"<<indentStr(indLevel)<<"while ("<<e<<") {\n";
|
||||
}
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case REPEAT_TYPE:
|
||||
ostr << "\n"<<indentStr(indLevel)<<"do {\n";
|
||||
picode = &latch->back();
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case ENDLESS_TYPE:
|
||||
ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
|
||||
}
|
||||
cCode.appendCode(ostr.str());
|
||||
stats.numHLIcode += 1;
|
||||
indLevel++;
|
||||
return picode;
|
||||
}
|
||||
bool BB::isEndOfPath(int latch_node_idx) const
|
||||
{
|
||||
return nodeType == RETURN_NODE || nodeType == TERMINATE_NODE ||
|
||||
nodeType == NOWHERE_NODE || (dfsLastNum == latch_node_idx);
|
||||
}
|
||||
void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int _ifFollow)
|
||||
{
|
||||
int follow; /* ifFollow */
|
||||
BB * succ, *latch; /* Successor and latching node */
|
||||
ICODE * picode; /* Pointer to HLI_JCOND instruction */
|
||||
char *l; /* Pointer to HLI_JCOND expression */
|
||||
boolT emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
|
||||
/* Check if this basic block should be analysed */
|
||||
if ((_ifFollow != UN_INIT) && (this == pProc->m_dfsLast[_ifFollow]))
|
||||
return;
|
||||
|
||||
if (wasTraversedAtLevel(DFS_ALPHA))
|
||||
return;
|
||||
traversed = DFS_ALPHA;
|
||||
|
||||
/* Check for start of loop */
|
||||
repCond = false;
|
||||
latch = NULL;
|
||||
if (loopType)
|
||||
{
|
||||
picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond);
|
||||
}
|
||||
|
||||
/* Write the code for this basic block */
|
||||
if (repCond == false)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
writeBB(ostr,indLevel, pProc, numLoc);
|
||||
cCode.appendCode(ostr.str());
|
||||
}
|
||||
|
||||
/* Check for end of path */
|
||||
if (isEndOfPath(_latchNode))
|
||||
return;
|
||||
|
||||
/* Check type of loop/node and process code */
|
||||
if ( loopType) /* there is a loop */
|
||||
{
|
||||
assert(latch);
|
||||
if (this != latch) /* loop is over several bbs */
|
||||
{
|
||||
if (loopType == WHILE_TYPE)
|
||||
{
|
||||
succ = edges[THEN].BBptr;
|
||||
if (succ->dfsLastNum == loopFollow)
|
||||
succ = edges[ELSE].BBptr;
|
||||
}
|
||||
else
|
||||
succ = edges[0].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, latch->dfsLastNum,_ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
succ->front().ll()->emitGotoLabel (indLevel);
|
||||
}
|
||||
|
||||
/* Loop epilogue: generate the loop trailer */
|
||||
indLevel--;
|
||||
if (loopType == WHILE_TYPE)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
/* Check if there is need to repeat other statements involved
|
||||
* in while condition, then, emit the loop trailer */
|
||||
if (repCond)
|
||||
{
|
||||
writeBB(ostr,indLevel+1, pProc, numLoc);
|
||||
}
|
||||
ostr <<indentStr(indLevel)<< "} /* end of while */\n";
|
||||
cCode.appendCode(ostr.str());
|
||||
}
|
||||
else if (loopType == ENDLESS_TYPE)
|
||||
cCode.appendCode( "%s} /* end of loop */\n",indentStr(indLevel));
|
||||
else if (loopType == REPEAT_TYPE)
|
||||
{
|
||||
if (picode->hl()->opcode != HLI_JCOND)
|
||||
reportError (REPEAT_FAIL);
|
||||
{
|
||||
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
|
||||
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),e.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Recurse on the loop follow */
|
||||
if (loopFollow != MAX)
|
||||
{
|
||||
succ = pProc->m_dfsLast[loopFollow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
succ->front().ll()->emitGotoLabel (indLevel);
|
||||
}
|
||||
}
|
||||
|
||||
else /* no loop, process nodeType of the graph */
|
||||
{
|
||||
if (nodeType == TWO_BRANCH) /* if-then[-else] */
|
||||
{
|
||||
stats.numHLIcode++;
|
||||
indLevel++;
|
||||
emptyThen = false;
|
||||
|
||||
if (ifFollow != MAX) /* there is a follow */
|
||||
{
|
||||
/* process the THEN part */
|
||||
follow = ifFollow;
|
||||
succ = edges[THEN].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* THEN part */
|
||||
{
|
||||
l = writeJcond ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l);
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow);
|
||||
}
|
||||
else /* empty THEN part => negate ELSE part */
|
||||
{
|
||||
l = writeJcondInv ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l);
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow);
|
||||
emptyThen = true;
|
||||
}
|
||||
}
|
||||
else /* already visited => emit label */
|
||||
succ->front().ll()->emitGotoLabel(indLevel);
|
||||
|
||||
/* process the ELSE part */
|
||||
succ = edges[ELSE].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* ELSE part */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode, follow);
|
||||
}
|
||||
/* else (empty ELSE part) */
|
||||
}
|
||||
else if (! emptyThen) /* already visited => emit label */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
succ->front().ll()->emitGotoLabel (indLevel);
|
||||
}
|
||||
cCode.appendCode( "%s}\n", indentStr(--indLevel));
|
||||
|
||||
/* Continue with the follow */
|
||||
succ = pProc->m_dfsLast[follow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode,_ifFollow);
|
||||
}
|
||||
else /* no follow => if..then..else */
|
||||
{
|
||||
l = writeJcond ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "%s%s", indentStr(indLevel-1), l);
|
||||
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
cCode.appendCode( "%s}\n", indentStr(--indLevel));
|
||||
}
|
||||
}
|
||||
|
||||
else /* fall, call, 1w */
|
||||
{
|
||||
succ = edges[0].BBptr; /* fall-through edge */
|
||||
assert(succ->size()>0);
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
{
|
||||
succ->writeCode (indLevel, pProc,numLoc, _latchNode,_ifFollow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Writes the code for the current basic block.
|
||||
* Args: pBB: pointer to the current basic block.
|
||||
* Icode: pointer to the array of icodes for current procedure.
|
||||
* lev: indentation level - used for formatting. */
|
||||
void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
{
|
||||
/* Save the index into the code table in case there is a later goto
|
||||
* into this instruction (first instruction of the BB) */
|
||||
front().ll()->codeIdx = cCode.code.nextIdx();
|
||||
|
||||
/* Generate code for each hlicode that is not a HLI_JCOND */
|
||||
|
||||
for(ICODE &pHli : instructions)
|
||||
{
|
||||
if ((pHli.type == HIGH_LEVEL) && ( pHli.valid() )) //TODO: use filtering range here.
|
||||
{
|
||||
std::string line = pHli.hl()->write1HlIcode(pProc, numLoc);
|
||||
if (!line.empty())
|
||||
{
|
||||
ostr<<indentStr(lev)<<line;
|
||||
stats.numHLIcode++;
|
||||
}
|
||||
if (option.verbose)
|
||||
pHli.writeDU();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iICODE BB::begin()
|
||||
{
|
||||
return instructions.begin();//range_start;
|
||||
}
|
||||
|
||||
iICODE BB::end() const
|
||||
{
|
||||
return instructions.end();//range_end
|
||||
}
|
||||
ICODE &BB::back()
|
||||
{
|
||||
return instructions.back();//*rbegin();
|
||||
}
|
||||
|
||||
size_t BB::size()
|
||||
{
|
||||
|
||||
return distance(instructions.begin(),instructions.end());
|
||||
}
|
||||
|
||||
ICODE &BB::front()
|
||||
{
|
||||
return instructions.front();//*begin();
|
||||
}
|
||||
|
||||
riICODE BB::rbegin()
|
||||
{
|
||||
return riICODE( instructions.end() );
|
||||
}
|
||||
riICODE BB::rend()
|
||||
{
|
||||
return riICODE( instructions.begin() );
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
SET(dcc_test_SOURCES tests/comwrite.cpp)
|
||||
include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include)
|
||||
enable_testing()
|
||||
add_executable(tester ${dcc_test_SOURCES})
|
||||
target_link_libraries(tester
|
||||
${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES})
|
||||
add_test(dcc-tests tester)
|
||||
@ -1,32 +0,0 @@
|
||||
#include "Procedure.h"
|
||||
#include "project.h"
|
||||
#include "scanner.h"
|
||||
//FunctionType *Function::getFunctionType() const
|
||||
//{
|
||||
// return &m_type;
|
||||
//}
|
||||
|
||||
/* Does some heuristic pruning. Looks for ptrs. into the table
|
||||
* and for addresses that don't appear to point to valid code.
|
||||
*/
|
||||
void JumpTable::pruneEntries(uint16_t cs)
|
||||
{
|
||||
PROG *prg(Project::get()->binary());
|
||||
for (uint32_t i = start; i < finish; i += 2)
|
||||
{
|
||||
uint32_t target = cs + LH(&prg->Image[i]);
|
||||
if (target < finish && target >= start)
|
||||
finish = target;
|
||||
else if (target >= (uint32_t)prg->cbImage)
|
||||
finish = i;
|
||||
}
|
||||
ICODE _Icode; // used as scan input
|
||||
for (uint32_t i = start; i < finish; i += 2)
|
||||
{
|
||||
uint32_t target = cs + LH(&prg->Image[i]);
|
||||
/* Be wary of 00 00 as code - it's probably data */
|
||||
if (! (prg->Image[target] || prg->Image[target+1]) || scan(target, _Icode))
|
||||
finish = i;
|
||||
}
|
||||
|
||||
}
|
||||
1060
src/ast.cpp
1060
src/ast.cpp
File diff suppressed because it is too large
Load Diff
609
src/backend.cpp
609
src/backend.cpp
@ -4,35 +4,42 @@
|
||||
* Purpose: Back-end module. Generates C code for each procedure.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "project.h"
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
using namespace std;
|
||||
|
||||
/* Returns a unique index to the next label */
|
||||
int getNextLabel()
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
|
||||
/* Indentation buffer */
|
||||
#define indSize 81 /* size of the indentation buffer. Each indentation
|
||||
* is of 4 spaces => max. 20 indentation levels */
|
||||
static char indentBuf[indSize] =
|
||||
" ";
|
||||
|
||||
|
||||
static char *indent (Int indLevel)
|
||||
/* Indentation according to the depth of the statement */
|
||||
{
|
||||
static int labelIdx = 1; /* index of the next label */
|
||||
return (&indentBuf[indSize-(indLevel*4)-1]);
|
||||
}
|
||||
|
||||
|
||||
static Int getNextLabel()
|
||||
/* Returns a unique index to the next label */
|
||||
{ static Int labelIdx = 1; /* index of the next label */
|
||||
|
||||
return (labelIdx++);
|
||||
}
|
||||
|
||||
|
||||
static void displayStats (PPROC pProc)
|
||||
/* displays statistics on the subroutine */
|
||||
void Function::displayStats ()
|
||||
{
|
||||
printf("\nStatistics - Subroutine %s\n", name.c_str());
|
||||
printf("\nStatistics - Subroutine %s\n", pProc->name);
|
||||
printf ("Number of Icode instructions:\n");
|
||||
printf (" Low-level : %4d\n", stats.numLLIcode);
|
||||
if (! (flg & PROC_ASM))
|
||||
if (! (pProc->flg & PROC_ASM))
|
||||
{
|
||||
printf (" High-level: %4d\n", stats.numHLIcode);
|
||||
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
|
||||
@ -48,24 +55,23 @@ static void fixupLabels (PPROC pProc)
|
||||
* a unique label number for it. This label is placed in the associated
|
||||
* icode for the node (pProc->Icode). The procedure is done in sequential
|
||||
* order of dsfLast numbering. */
|
||||
{ int i; /* index into the dfsLast array */
|
||||
{ Int i; /* index into the dfsLast array */
|
||||
PBB *dfsLast; /* pointer to the dfsLast array */
|
||||
|
||||
dfsLast = pProc->dfsLast;
|
||||
for (i = 0; i < pProc->numBBs; i++)
|
||||
if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) {
|
||||
pProc->Icode.icode[dfsLast[i]->start].ll()->flg |= HLL_LABEL;
|
||||
pProc->Icode.icode[dfsLast[i]->start].ll()->hllLabNum = getNextLabel();
|
||||
pProc->Icode.icode[dfsLast[i]->start].ic.ll.flg |= HLL_LABEL;
|
||||
pProc->Icode.icode[dfsLast[i]->start].ic.ll.hllLabNum = getNextLabel();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
char *cChar (byte c)
|
||||
/* Returns the corresponding C string for the given character c. Character
|
||||
* constants such as carriage return and line feed, require 2 C characters. */
|
||||
char *cChar (uint8_t c)
|
||||
{
|
||||
static char res[3];
|
||||
{ static char res[3];
|
||||
|
||||
switch (c) {
|
||||
case 0x8: /* backspace */
|
||||
@ -90,216 +96,515 @@ char *cChar (uint8_t c)
|
||||
}
|
||||
|
||||
|
||||
static void printGlobVar (PSYM psym)
|
||||
/* Prints the variable's name and initial contents on the file.
|
||||
* Note: to get to the value of the variable:
|
||||
* com file: prog.Image[operand]
|
||||
* exe file: prog.Image[operand+0x100] */
|
||||
static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
{
|
||||
int j;
|
||||
PROG &prog(Project::get()->prog);
|
||||
uint32_t relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
|
||||
{ Int j;
|
||||
dword relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
|
||||
char *strContents; /* initial contents of variable */
|
||||
|
||||
switch (psym->size)
|
||||
{
|
||||
case 1:
|
||||
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.Image[relocOp]<<";\n";
|
||||
switch (psym->size) {
|
||||
case 1: appendStrTab (&cCode.decl, "byte\t%s = %ld;\n",
|
||||
psym->name, prog.Image[relocOp]);
|
||||
break;
|
||||
case 2:
|
||||
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
|
||||
case 2: appendStrTab (&cCode.decl, "word\t%s = %ld;\n",
|
||||
psym->name, LH(prog.Image+relocOp));
|
||||
break;
|
||||
case 4: if (psym->type == TYPE_PTR) /* pointer */
|
||||
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
|
||||
appendStrTab (&cCode.decl, "word\t*%s = %ld;\n",
|
||||
psym->name, LH(prog.Image+relocOp));
|
||||
else /* char */
|
||||
ostr << "char\t"<<psym->name<<"[4] = \""<<
|
||||
prog.Image[relocOp]<<prog.Image[relocOp+1]<<
|
||||
prog.Image[relocOp+2]<<prog.Image[relocOp+3]<<";\n";
|
||||
appendStrTab (&cCode.decl,
|
||||
"char\t%s[4] = \"%c%c%c%c\";\n",
|
||||
psym->name, prog.Image[relocOp],
|
||||
prog.Image[relocOp+1], prog.Image[relocOp+2],
|
||||
prog.Image[relocOp+3]);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ostringstream strContents;
|
||||
default:strContents = (char *)allocMem((psym->size*2+1) *sizeof(char));
|
||||
strContents[0] = '\0';
|
||||
for (j=0; j < psym->size; j++)
|
||||
strContents << cChar(prog.Image[relocOp + j]);
|
||||
ostr << "char\t*"<<psym->name<<" = \""<<strContents.str()<<"\";\n";
|
||||
}
|
||||
strcat (strContents, cChar(prog.Image[relocOp + j]));
|
||||
appendStrTab (&cCode.decl, "char\t*%s = \"%s\";\n",
|
||||
psym->name, strContents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note: Not called at present.
|
||||
static void writeGlobSymTable()
|
||||
/* Writes the contents of the symbol table, along with any variable
|
||||
* initialization. */
|
||||
void Project::writeGlobSymTable()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
{ Int idx;
|
||||
char type[10];
|
||||
PSYM pSym;
|
||||
|
||||
if (symtab.empty())
|
||||
return;
|
||||
ostr<<"/* Global variables */\n";
|
||||
for (SYM &sym : symtab)
|
||||
if (symtab.csym)
|
||||
{
|
||||
if (sym.duVal.isUSE_VAL()) /* first used */
|
||||
printGlobVar (ostr,&sym);
|
||||
appendStrTab (&cCode.decl, "/* Global variables */\n");
|
||||
for (idx = 0; idx < symtab.csym; idx++)
|
||||
{
|
||||
pSym = &symtab.sym[idx];
|
||||
if (symtab.sym[idx].duVal & USEVAL) /* first used */
|
||||
printGlobVar (&(symtab.sym[idx]));
|
||||
else { /* first defined */
|
||||
switch (sym.size) {
|
||||
case 1: ostr<<"uint8_t\t"; break;
|
||||
case 2: ostr<<"int\t"; break;
|
||||
case 4: if (sym.type == TYPE_PTR)
|
||||
ostr<<"int\t*";
|
||||
switch (pSym->size) {
|
||||
case 1: strcpy (type, "byte\t"); break;
|
||||
case 2: strcpy (type, "int\t"); break;
|
||||
case 4: if (pSym->type == TYPE_PTR)
|
||||
strcpy (type, "int\t*");
|
||||
else
|
||||
ostr<<"char\t*";
|
||||
strcpy (type, "char\t*");
|
||||
break;
|
||||
default: ostr<<"char\t*";
|
||||
default: strcpy (type, "char\t*");
|
||||
}
|
||||
ostr<<sym.name<<";\t/* size = "<<sym.size<<" */\n";
|
||||
appendStrTab (&cCode.decl, "%s%s;\t/* size = %ld */\n",
|
||||
type, pSym->name, pSym->size);
|
||||
}
|
||||
}
|
||||
ostr<< "\n";
|
||||
cCode.appendDecl( ostr.str() );
|
||||
appendStrTab (&cCode.decl, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void writeHeader (FILE *fp, char *fileName)
|
||||
/* Writes the header information and global variables to the output C file
|
||||
* fp. */
|
||||
static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
/* Write header information */
|
||||
cCode.init();
|
||||
cCode.appendDecl( "/*\n");
|
||||
cCode.appendDecl( " * Input file\t: %s\n", fileName);
|
||||
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
|
||||
newBundle (&cCode);
|
||||
appendStrTab (&cCode.decl, "/*\n");
|
||||
appendStrTab (&cCode.decl, " * Input file\t: %s\n", fileName);
|
||||
appendStrTab (&cCode.decl, " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
appendStrTab (&cCode.decl, " */\n\n#include \"dcc.h\"\n\n");
|
||||
|
||||
/* Write global symbol table */
|
||||
/** writeGlobSymTable(); *** need to change them into locident fmt ***/
|
||||
writeBundle (_ios, cCode);
|
||||
writeBundle (fp, cCode);
|
||||
freeBundle (&cCode);
|
||||
}
|
||||
|
||||
|
||||
static void writeBitVector (dword regi)
|
||||
/* Writes the registers that are set in the bitvector */
|
||||
{ Int j;
|
||||
|
||||
for (j = 0; j < INDEXBASE; j++)
|
||||
{
|
||||
if ((regi & power2(j)) != 0)
|
||||
printf ("%s ", allRegs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void emitGotoLabel (PICODE pt, Int indLevel)
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be backpatched
|
||||
* onto code in cCode.code */
|
||||
{
|
||||
if (! (pt->ic.ll.flg & HLL_LABEL)) /* node hasn't got a lab */
|
||||
{
|
||||
/* Generate new label */
|
||||
pt->ic.ll.hllLabNum = getNextLabel();
|
||||
pt->ic.ll.flg |= HLL_LABEL;
|
||||
|
||||
/* Node has been traversed already, so backpatch this label into
|
||||
* the code */
|
||||
addLabelBundle (&cCode.code, pt->codeIdx, pt->ic.ll.hllLabNum);
|
||||
}
|
||||
appendStrTab (&cCode.code, "%sgoto L%ld;\n", indent(indLevel),
|
||||
pt->ic.ll.hllLabNum);
|
||||
stats.numHLIcode++;
|
||||
}
|
||||
|
||||
|
||||
// Note: Not currently called!
|
||||
static void emitFwdGotoLabel (PICODE pt, Int indLevel)
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be forward on
|
||||
* the code; that is, the target code has not been traversed yet. */
|
||||
static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
{
|
||||
if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */
|
||||
if (! (pt->ic.ll.flg & HLL_LABEL)) /* node hasn't got a lab */
|
||||
{
|
||||
/* Generate new label */
|
||||
pt->ll()->hllLabNum = getNextLabel();
|
||||
pt->ll()->setFlags(HLL_LABEL);
|
||||
pt->ic.ll.hllLabNum = getNextLabel();
|
||||
pt->ic.ll.flg |= HLL_LABEL;
|
||||
}
|
||||
cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum);
|
||||
appendStrTab (&cCode.code, "%sgoto l%ld;\n", indent(indLevel),
|
||||
pt->ic.ll.hllLabNum);
|
||||
}
|
||||
|
||||
|
||||
static void writeBB (PBB pBB, PICODE hli, Int lev, PPROC pProc, Int *numLoc)
|
||||
/* Writes the code for the current basic block.
|
||||
* Args: pBB: pointer to the current basic block.
|
||||
* Icode: pointer to the array of icodes for current procedure.
|
||||
* lev: indentation level - used for formatting. */
|
||||
{ Int i, last;
|
||||
char *line; /* Pointer to the HIGH-LEVEL line */
|
||||
|
||||
/* Save the index into the code table in case there is a later goto
|
||||
* into this instruction (first instruction of the BB) */
|
||||
hli[pBB->start].codeIdx = nextBundleIdx (&cCode.code);
|
||||
|
||||
/* Generate code for each hlicode that is not a HLI_JCOND */
|
||||
for (i = pBB->start, last = i + pBB->length; i < last; i++)
|
||||
if ((hli[i].type == HIGH_LEVEL) && (hli[i].invalid == FALSE))
|
||||
{
|
||||
line = write1HlIcode (hli[i].ic.hl, pProc, numLoc);
|
||||
if (line[0] != '\0')
|
||||
{
|
||||
appendStrTab (&cCode.code, "%s%s", indent(lev), line);
|
||||
stats.numHLIcode++;
|
||||
}
|
||||
if (option.verbose)
|
||||
writeDU (&hli[i], i);
|
||||
}
|
||||
//if (hli[i].invalid)
|
||||
//printf("Invalid icode: %d!\n", hli[i].invalid);
|
||||
}
|
||||
|
||||
|
||||
static void writeCode (PBB pBB, Int indLevel, PPROC pProc , Int *numLoc,
|
||||
Int latchNode, Int ifFollow)
|
||||
/* Recursive procedure that writes the code for the given procedure, pointed
|
||||
* to by pBB.
|
||||
* Parameters: pBB: pointer to the cfg.
|
||||
* Icode: pointer to the Icode array for the cfg graph of the
|
||||
* current procedure.
|
||||
* indLevel: indentation level - used for formatting.
|
||||
* numLoc: last # assigned to local variables */
|
||||
{
|
||||
Int follow, /* ifFollow */
|
||||
loopType, /* Type of loop, if any */
|
||||
nodeType; /* Type of node */
|
||||
PBB succ, latch; /* Successor and latching node */
|
||||
PICODE picode; /* Pointer to HLI_JCOND instruction */
|
||||
char *l; /* Pointer to HLI_JCOND expression */
|
||||
boolT emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
|
||||
/* Check if this basic block should be analysed */
|
||||
if (!pBB) return;
|
||||
if ((ifFollow != UN_INIT) && (pBB == pProc->dfsLast[ifFollow]))
|
||||
return;
|
||||
|
||||
if (pBB->traversed == DFS_ALPHA)
|
||||
return;
|
||||
pBB->traversed = DFS_ALPHA;
|
||||
|
||||
/* Check for start of loop */
|
||||
repCond = FALSE;
|
||||
latch = NULL;
|
||||
loopType = pBB->loopType;
|
||||
if (loopType)
|
||||
{
|
||||
latch = pProc->dfsLast[pBB->latchNode];
|
||||
switch (loopType) {
|
||||
case WHILE_TYPE:
|
||||
picode = pProc->Icode.GetIcode(pBB->start + pBB->length - 1);
|
||||
|
||||
/* Check for error in while condition */
|
||||
if (picode->ic.hl.opcode != HLI_JCOND)
|
||||
reportError (WHILE_FAIL);
|
||||
|
||||
/* Check if condition is more than 1 HL instruction */
|
||||
if (pBB->numHlIcodes > 1)
|
||||
{
|
||||
/* Write the code for this basic block */
|
||||
writeBB(pBB, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
|
||||
repCond = TRUE;
|
||||
}
|
||||
|
||||
/* Condition needs to be inverted if the loop body is along
|
||||
* the THEN path of the header node */
|
||||
if (pBB->edges[ELSE].BBptr->dfsLastNum == pBB->loopFollow)
|
||||
inverseCondOp (&picode->ic.hl.oper.exp);
|
||||
appendStrTab (&cCode.code, "\n%swhile (%s) {\n", indent(indLevel),
|
||||
walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc));
|
||||
invalidateIcode (picode);
|
||||
break;
|
||||
|
||||
case REPEAT_TYPE:
|
||||
appendStrTab (&cCode.code, "\n%sdo {\n", indent(indLevel));
|
||||
picode = pProc->Icode.GetIcode(latch->start+latch->length-1);
|
||||
invalidateIcode (picode);
|
||||
break;
|
||||
|
||||
case ENDLESS_TYPE:
|
||||
appendStrTab (&cCode.code, "\n%sfor (;;) {\n", indent(indLevel));
|
||||
}
|
||||
stats.numHLIcode += 1;
|
||||
indLevel++;
|
||||
}
|
||||
|
||||
/* Write the code for this basic block */
|
||||
if (repCond == FALSE)
|
||||
writeBB (pBB, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
|
||||
|
||||
/* Check for end of path */
|
||||
nodeType = pBB->nodeType;
|
||||
if (nodeType == RETURN_NODE || nodeType == TERMINATE_NODE ||
|
||||
nodeType == NOWHERE_NODE || (pBB->dfsLastNum == latchNode))
|
||||
return;
|
||||
|
||||
/* Check type of loop/node and process code */
|
||||
if (loopType) /* there is a loop */
|
||||
{
|
||||
if (pBB != latch) /* loop is over several bbs */
|
||||
{
|
||||
if (loopType == WHILE_TYPE)
|
||||
{
|
||||
succ = pBB->edges[THEN].BBptr;
|
||||
if (succ->dfsLastNum == pBB->loopFollow)
|
||||
succ = pBB->edges[ELSE].BBptr;
|
||||
}
|
||||
else
|
||||
succ = pBB->edges[0].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
writeCode (succ, indLevel, pProc, numLoc, latch->dfsLastNum,
|
||||
ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
}
|
||||
|
||||
/* Loop epilogue: generate the loop trailer */
|
||||
indLevel--;
|
||||
if (loopType == WHILE_TYPE)
|
||||
{
|
||||
/* Check if there is need to repeat other statements involved
|
||||
* in while condition, then, emit the loop trailer */
|
||||
if (repCond)
|
||||
writeBB (pBB, pProc->Icode.GetFirstIcode(), indLevel+1, pProc, numLoc);
|
||||
appendStrTab (&cCode.code, "%s} /* end of while */\n",
|
||||
indent(indLevel));
|
||||
}
|
||||
else if (loopType == ENDLESS_TYPE)
|
||||
appendStrTab (&cCode.code, "%s} /* end of loop */\n",
|
||||
indent(indLevel));
|
||||
else if (loopType == REPEAT_TYPE)
|
||||
{
|
||||
if (picode->ic.hl.opcode != HLI_JCOND)
|
||||
reportError (REPEAT_FAIL);
|
||||
appendStrTab (&cCode.code, "%s} while (%s);\n", indent(indLevel),
|
||||
walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc));
|
||||
}
|
||||
|
||||
/* Recurse on the loop follow */
|
||||
if (pBB->loopFollow != MAX)
|
||||
{
|
||||
succ = pProc->dfsLast[pBB->loopFollow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
writeCode (succ, indLevel, pProc, numLoc, latchNode, ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
}
|
||||
}
|
||||
|
||||
else /* no loop, process nodeType of the graph */
|
||||
{
|
||||
if (nodeType == TWO_BRANCH) /* if-then[-else] */
|
||||
{
|
||||
stats.numHLIcode++;
|
||||
indLevel++;
|
||||
emptyThen = FALSE;
|
||||
|
||||
if (pBB->ifFollow != MAX) /* there is a follow */
|
||||
{
|
||||
/* process the THEN part */
|
||||
follow = pBB->ifFollow;
|
||||
succ = pBB->edges[THEN].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* THEN part */
|
||||
{
|
||||
l = writeJcond (
|
||||
pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl,
|
||||
pProc, numLoc);
|
||||
appendStrTab (&cCode.code, "\n%s%s", indent(indLevel-1), l);
|
||||
writeCode (succ, indLevel, pProc, numLoc, latchNode,
|
||||
follow);
|
||||
}
|
||||
else /* empty THEN part => negate ELSE part */
|
||||
{
|
||||
l = writeJcondInv (
|
||||
pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl,
|
||||
pProc, numLoc);
|
||||
appendStrTab (&cCode.code, "\n%s%s", indent(indLevel-1), l);
|
||||
writeCode (pBB->edges[ELSE].BBptr, indLevel, pProc, numLoc,
|
||||
latchNode, follow);
|
||||
emptyThen = TRUE;
|
||||
}
|
||||
}
|
||||
else /* already visited => emit label */
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
|
||||
/* process the ELSE part */
|
||||
succ = pBB->edges[ELSE].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* ELSE part */
|
||||
{
|
||||
appendStrTab (&cCode.code, "%s}\n%selse {\n",
|
||||
indent(indLevel-1), indent(indLevel - 1));
|
||||
writeCode (succ, indLevel, pProc, numLoc, latchNode,
|
||||
follow);
|
||||
}
|
||||
/* else (empty ELSE part) */
|
||||
}
|
||||
else if (! emptyThen) /* already visited => emit label */
|
||||
{
|
||||
appendStrTab (&cCode.code, "%s}\n%selse {\n",
|
||||
indent(indLevel-1), indent(indLevel - 1));
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
}
|
||||
appendStrTab (&cCode.code, "%s}\n", indent(--indLevel));
|
||||
|
||||
/* Continue with the follow */
|
||||
succ = pProc->dfsLast[follow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
writeCode (succ, indLevel, pProc, numLoc, latchNode,
|
||||
ifFollow);
|
||||
}
|
||||
else /* no follow => if..then..else */
|
||||
{
|
||||
l = writeJcond (
|
||||
pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl,
|
||||
pProc, numLoc);
|
||||
appendStrTab (&cCode.code, "%s%s", indent(indLevel-1), l);
|
||||
writeCode (pBB->edges[THEN].BBptr, indLevel, pProc, numLoc,
|
||||
latchNode, ifFollow);
|
||||
appendStrTab (&cCode.code, "%s}\n%selse {\n", indent(indLevel-1),
|
||||
indent(indLevel - 1));
|
||||
writeCode (pBB->edges[ELSE].BBptr, indLevel, pProc, numLoc,
|
||||
latchNode, ifFollow);
|
||||
appendStrTab (&cCode.code, "%s}\n", indent(--indLevel));
|
||||
}
|
||||
}
|
||||
|
||||
else /* fall, call, 1w */
|
||||
{
|
||||
succ = pBB->edges[0].BBptr; /* fall-through edge */
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
writeCode (succ, indLevel, pProc,numLoc, latchNode,ifFollow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void codeGen (PPROC pProc, FILE *fp)
|
||||
/* Writes the procedure's declaration (including arguments), local variables,
|
||||
* and invokes the procedure that writes the code of the given record *hli */
|
||||
void Function::codeGen (std::ostream &fs)
|
||||
{
|
||||
int numLoc;
|
||||
ostringstream ostr;
|
||||
//STKFRAME * args; /* Procedure arguments */
|
||||
//char buf[200], /* Procedure's definition */
|
||||
// arg[30]; /* One argument */
|
||||
{ Int i, numLoc;
|
||||
PSTKFRAME args; /* Procedure arguments */
|
||||
char buf[200], /* Procedure's definition */
|
||||
arg[30]; /* One argument */
|
||||
ID *locid; /* Pointer to one local identifier */
|
||||
BB *pBB; /* Pointer to basic block */
|
||||
|
||||
/* Write procedure/function header */
|
||||
cCode.init();
|
||||
if (flg & PROC_IS_FUNC) /* Function */
|
||||
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" (";
|
||||
newBundle (&cCode);
|
||||
if (pProc->flg & PROC_IS_FUNC) /* Function */
|
||||
appendStrTab (&cCode.decl, "\n%s %s (", hlTypes[pProc->retVal.type],
|
||||
pProc->name);
|
||||
else /* Procedure */
|
||||
ostr<< "\nvoid "<<name<<" (";
|
||||
appendStrTab (&cCode.decl, "\nvoid %s (", pProc->name);
|
||||
|
||||
/* Write arguments */
|
||||
for (size_t i = 0; i < args.size(); i++)
|
||||
args = &pProc->args;
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < args->csym; i++)
|
||||
{
|
||||
if ( args[i].invalid )
|
||||
continue;
|
||||
ostr<<hlTypes[args[i].type]<<" "<<args[i].name;
|
||||
if (i < (args.size() - 1))
|
||||
ostr<<", ";
|
||||
if (args->sym[i].invalid == FALSE)
|
||||
{
|
||||
sprintf (arg,"%s %s",hlTypes[args->sym[i].type], args->sym[i].name);
|
||||
strcat (buf, arg);
|
||||
if (i < (args->numArgs - 1))
|
||||
strcat (buf, ", ");
|
||||
}
|
||||
ostr<<")\n";
|
||||
}
|
||||
strcat (buf, ")\n");
|
||||
appendStrTab (&cCode.decl, "%s", buf);
|
||||
|
||||
/* Write comments */
|
||||
writeProcComments( ostr );
|
||||
writeProcComments (pProc, &cCode.decl);
|
||||
|
||||
/* Write local variables */
|
||||
if (! (flg & PROC_ASM))
|
||||
if (! (pProc->flg & PROC_ASM))
|
||||
{
|
||||
locid = &pProc->localId.id[0];
|
||||
numLoc = 0;
|
||||
for (ID &refId : localId )
|
||||
for (i = 0; i < pProc->localId.csym; i++, locid++)
|
||||
{
|
||||
/* Output only non-invalidated entries */
|
||||
if ( refId.illegal )
|
||||
continue;
|
||||
if (refId.loc == REG_FRAME)
|
||||
if (locid->illegal == FALSE)
|
||||
{
|
||||
if (locid->loc == REG_FRAME)
|
||||
{
|
||||
/* Register variables are assigned to a local variable */
|
||||
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) ||
|
||||
((flg & DI_REGVAR) && (refId.id.regi == rDI)))
|
||||
if (((pProc->flg & SI_REGVAR) && (locid->id.regi == rSI)) ||
|
||||
((pProc->flg & DI_REGVAR) && (locid->id.regi == rDI)))
|
||||
{
|
||||
refId.setLocalName(++numLoc);
|
||||
ostr << "int "<<refId.name<<";\n";
|
||||
sprintf (locid->name, "loc%ld", ++numLoc);
|
||||
appendStrTab (&cCode.decl, "int %s;\n", locid->name);
|
||||
}
|
||||
/* Other registers are named when they are first used in
|
||||
* the output C code, and appended to the proc decl. */
|
||||
}
|
||||
else if (refId.loc == STK_FRAME)
|
||||
|
||||
else if (locid->loc == STK_FRAME)
|
||||
{
|
||||
/* Name local variables and output appropriate type */
|
||||
refId.setLocalName(++numLoc);
|
||||
ostr << TypeContainer::typeName(refId.type)<<" "<<refId.name<<";\n";
|
||||
sprintf (locid->name, "loc%ld", ++numLoc);
|
||||
appendStrTab (&cCode.decl, "%s %s;\n",
|
||||
hlTypes[locid->type], locid->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fs<<ostr.str();
|
||||
/* Write procedure's code */
|
||||
if (flg & PROC_ASM) /* generate assembler */
|
||||
{
|
||||
Disassembler ds(3);
|
||||
ds.disassem(this);
|
||||
}
|
||||
if (pProc->flg & PROC_ASM) /* generate assembler */
|
||||
disassem (3, pProc);
|
||||
else /* generate C */
|
||||
{
|
||||
m_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
|
||||
}
|
||||
writeCode (pProc->cfg, 1, pProc, &numLoc, MAX, UN_INIT);
|
||||
|
||||
cCode.appendCode( "}\n\n");
|
||||
writeBundle (fs, cCode);
|
||||
appendStrTab (&cCode.code, "}\n\n");
|
||||
writeBundle (fp, cCode);
|
||||
freeBundle (&cCode);
|
||||
|
||||
/* Write Live register analysis information */
|
||||
if (option.verbose)
|
||||
for (size_t i = 0; i < numBBs; i++)
|
||||
for (i = 0; i < pProc->numBBs; i++)
|
||||
{
|
||||
pBB = m_dfsLast[i];
|
||||
pBB = pProc->dfsLast[i];
|
||||
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
|
||||
cout << "BB "<<i<<"\n";
|
||||
cout << " Start = "<<pBB->begin()->loc_ip;
|
||||
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
|
||||
cout << " LiveUse = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveUse);
|
||||
cout << "\n Def = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->def);
|
||||
cout << "\n LiveOut = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveOut);
|
||||
cout << "\n LiveIn = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveIn);
|
||||
cout <<"\n\n";
|
||||
printf ("BB %d\n", i);
|
||||
printf (" Start = %d, end = %d\n", pBB->start, pBB->start +
|
||||
pBB->length - 1);
|
||||
printf (" LiveUse = ");
|
||||
writeBitVector (pBB->liveUse);
|
||||
printf ("\n Def = ");
|
||||
writeBitVector (pBB->def);
|
||||
printf ("\n LiveOut = ");
|
||||
writeBitVector (pBB->liveOut);
|
||||
printf ("\n LiveIn = ");
|
||||
writeBitVector (pBB->liveIn);
|
||||
printf ("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void backBackEnd (char *filename, PCALL_GRAPH pcallGraph, FILE *fp)
|
||||
/* Recursive procedure. Displays the procedure's code in depth-first order
|
||||
* of the call graph. */
|
||||
static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &_ios)
|
||||
{
|
||||
{ Int i;
|
||||
|
||||
// IFace.Yield(); /* This is a good place to yield to other apps */
|
||||
// IFace.Yield(); /* This is a good place to yield to other apps */
|
||||
|
||||
/* Check if this procedure has been processed already */
|
||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
|
||||
@ -308,19 +613,22 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
|
||||
pcallGraph->proc->flg |= PROC_OUTPUT;
|
||||
|
||||
/* Dfs if this procedure has any successors */
|
||||
for (size_t i = 0; i < pcallGraph->outEdges.size(); i++)
|
||||
if (pcallGraph->numOutEdges > 0)
|
||||
{
|
||||
backBackEnd (filename, pcallGraph->outEdges[i], _ios);
|
||||
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||
{
|
||||
backBackEnd (filename, pcallGraph->outEdges[i], fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate code for this procedure */
|
||||
stats.numLLIcode = pcallGraph->proc->Icode.size();
|
||||
stats.numLLIcode = pcallGraph->proc->Icode.GetNumIcodes();
|
||||
stats.numHLIcode = 0;
|
||||
pcallGraph->proc->codeGen (_ios);
|
||||
codeGen (pcallGraph->proc, fp);
|
||||
|
||||
/* Generate statistics */
|
||||
if (option.Stats)
|
||||
pcallGraph->proc->displayStats ();
|
||||
displayStats (pcallGraph->proc);
|
||||
if (! (pcallGraph->proc->flg & PROC_ASM))
|
||||
{
|
||||
stats.totalLL += stats.numLLIcode;
|
||||
@ -329,33 +637,36 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
|
||||
}
|
||||
|
||||
|
||||
void BackEnd (char *fileName, PCALL_GRAPH pcallGraph)
|
||||
/* Invokes the necessary routines to produce code one procedure at a time. */
|
||||
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
{
|
||||
std::ofstream fs; /* Output C file */
|
||||
char* outName, *ext;
|
||||
FILE* fp; /* Output C file */
|
||||
|
||||
/* Get output file name */
|
||||
std::string outNam(fileName);
|
||||
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
|
||||
outName = strcpy ((char*)allocMem(strlen(fileName)+1), fileName);
|
||||
if ((ext = strrchr (outName, '.')) != NULL)
|
||||
*ext = '\0';
|
||||
strcat (outName, ".b"); /* b for beta */
|
||||
|
||||
/* Open output file */
|
||||
fs.open(outNam);
|
||||
if(!fs.is_open())
|
||||
fatalError (CANNOT_OPEN, outNam.c_str());
|
||||
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
|
||||
fp = fopen (outName, "wt");
|
||||
if (!fp)
|
||||
fatalError (CANNOT_OPEN, outName);
|
||||
printf ("dcc: Writing C beta file %s\n", outName);
|
||||
|
||||
/* Header information */
|
||||
writeHeader (fs, fileName);
|
||||
writeHeader (fp, fileName);
|
||||
|
||||
/* Initialize total Icode instructions statistics */
|
||||
stats.totalLL = 0;
|
||||
stats.totalHL = 0;
|
||||
|
||||
/* Process each procedure at a time */
|
||||
backBackEnd (fileName, pcallGraph, fs);
|
||||
backBackEnd (fileName, pcallGraph, fp);
|
||||
|
||||
/* Close output file */
|
||||
fs.close();
|
||||
fclose (fp);
|
||||
printf ("dcc: Finished writing C beta file\n");
|
||||
}
|
||||
|
||||
|
||||
124
src/bundle.cpp
124
src/bundle.cpp
@ -6,89 +6,107 @@
|
||||
|
||||
#include "dcc.h"
|
||||
#include <stdarg.h>
|
||||
#include <iostream>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define deltaProcLines 20
|
||||
|
||||
using namespace std;
|
||||
|
||||
void newBundle (bundle *procCode)
|
||||
/* Allocates memory for a new bundle and initializes it to zero. */
|
||||
{
|
||||
memset (&(procCode->decl), 0, sizeof(strTable));
|
||||
memset (&(procCode->code), 0, sizeof(strTable));
|
||||
}
|
||||
|
||||
|
||||
static void incTableSize (strTable *strTab)
|
||||
/* Increments the size of the table strTab by deltaProcLines and copies all
|
||||
* the strings to the new table. */
|
||||
{
|
||||
strTab->allocLines += deltaProcLines;
|
||||
strTab->str = (char**)reallocVar (strTab->str, strTab->allocLines*sizeof(char *));
|
||||
memset (&strTab->str[strTab->allocLines - deltaProcLines], 0,
|
||||
deltaProcLines * sizeof(char *));
|
||||
}
|
||||
|
||||
|
||||
void appendStrTab (strTable *strTab, char *format, ...)
|
||||
/* Appends the new line (in printf style) to the string table strTab. */
|
||||
{ va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
if (strTab->numLines == strTab->allocLines)
|
||||
{
|
||||
incTableSize (strTab);
|
||||
}
|
||||
strTab->str[strTab->numLines] = (char *)malloc(lineSize * sizeof(char));
|
||||
if (strTab->str == NULL)
|
||||
{
|
||||
fatalError(MALLOC_FAILED, lineSize * sizeof(char));
|
||||
}
|
||||
vsprintf (strTab->str[strTab->numLines], format, args);
|
||||
strTab->numLines++;
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
Int nextBundleIdx (strTable *strTab)
|
||||
/* Returns the next available index into the table */
|
||||
{
|
||||
return (strTab->numLines);
|
||||
}
|
||||
|
||||
|
||||
void addLabelBundle (strTable *strTab, Int idx, Int label)
|
||||
/* Adds the given label to the start of the line strTab[idx]. The first
|
||||
* tab is removed and replaced by this label */
|
||||
void strTable::addLabelBundle (int idx, int label)
|
||||
{
|
||||
char s[16];
|
||||
sprintf (s, "l%d: ", label);
|
||||
if(at(idx).size()<4)
|
||||
at(idx)=s;
|
||||
else
|
||||
at(idx) = string(s)+at(idx).substr(4);
|
||||
{ char s[lineSize];
|
||||
|
||||
sprintf (s, "l%ld: %s", label, &strTab->str[idx][4]);
|
||||
strcpy (strTab->str[idx], s);
|
||||
}
|
||||
|
||||
|
||||
static void writeStrTab (FILE *fp, strTable strTab)
|
||||
/* Writes the contents of the string table on the file fp. */
|
||||
static void writeStrTab (std::ostream &ios, strTable &strTab)
|
||||
{
|
||||
for (size_t i = 0; i < strTab.size(); i++)
|
||||
ios << strTab[i];
|
||||
{ Int i;
|
||||
|
||||
for (i = 0; i < strTab.numLines; i++)
|
||||
fprintf (fp, "%s", strTab.str[i]);
|
||||
}
|
||||
|
||||
|
||||
void writeBundle (FILE *fp, bundle procCode)
|
||||
/* Writes the contents of the bundle (procedure code and declaration) to
|
||||
* a file. */
|
||||
void writeBundle (std::ostream &ios, bundle procCode)
|
||||
{
|
||||
writeStrTab (ios, procCode.decl);
|
||||
writeStrTab (ios, procCode.code);
|
||||
writeStrTab (fp, procCode.decl);
|
||||
if (procCode.decl.str[procCode.decl.numLines - 1][0] != ' ')
|
||||
fprintf (fp, "\n");
|
||||
writeStrTab (fp, procCode.code);
|
||||
}
|
||||
|
||||
|
||||
static void freeStrTab (strTable *strTab)
|
||||
/* Frees the storage allocated by the string table. */
|
||||
static void freeStrTab (strTable &strTab)
|
||||
{
|
||||
strTab.clear();
|
||||
{ Int i;
|
||||
|
||||
if (strTab->allocLines > 0) {
|
||||
for (i = 0; i < strTab->numLines; i++)
|
||||
free (strTab->str[i]);
|
||||
free (strTab->str);
|
||||
memset (strTab, 0, sizeof(strTable));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Deallocates the space taken by the bundle procCode */
|
||||
void freeBundle (bundle *procCode)
|
||||
/* Deallocates the space taken by the bundle procCode */
|
||||
{
|
||||
freeStrTab (procCode->decl);
|
||||
freeStrTab (procCode->code);
|
||||
}
|
||||
|
||||
void bundle::appendCode(const char *format,...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[lineSize]={0};
|
||||
va_start (args, format);
|
||||
vsprintf (buf, format, args);
|
||||
code.push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
void bundle::appendCode(const std::string &s)
|
||||
{
|
||||
code.push_back(s);
|
||||
}
|
||||
|
||||
void bundle::appendDecl(const char *format,...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[lineSize]={0};
|
||||
va_start (args, format);
|
||||
vsprintf (buf, format, args);
|
||||
decl.push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void bundle::appendDecl(const std::string &v)
|
||||
{
|
||||
decl.push_back(v);
|
||||
freeStrTab (&(procCode->decl));
|
||||
freeStrTab (&(procCode->code));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
400
src/chklib.cpp
400
src/chklib.cpp
@ -14,7 +14,6 @@
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include "perfhlib.h"
|
||||
|
||||
#define NIL -1 /* Used like NULL, but 0 is valid */
|
||||
@ -23,7 +22,7 @@
|
||||
typedef struct HT_tag
|
||||
{
|
||||
char htSym[SYMLEN];
|
||||
uint8_t htPat[PATLEN];
|
||||
byte htPat[PATLEN];
|
||||
} HT;
|
||||
|
||||
/* Structure of the prototypes table. Same as the struct in parsehdr.h,
|
||||
@ -36,7 +35,7 @@ struct ph_func_tag
|
||||
hlType typ; /* Return type */
|
||||
int numArg; /* Number of args */
|
||||
int firstArg; /* Index of first arg in chain */
|
||||
// int next; /* Index of next function in chain */
|
||||
// int next; /* Index of next function in chain */
|
||||
bool bVararg; /* True if variable arguements */
|
||||
} PH_FUNC_STRUCT;
|
||||
|
||||
@ -44,27 +43,27 @@ struct ph_func_tag
|
||||
#define NUM_PLIST 64 /* Number of entries to increase allocation by */
|
||||
|
||||
/* statics */
|
||||
static char buf[100]; /* A general purpose buffer */
|
||||
char buf[100]; /* A general purpose buffer */
|
||||
int numKeys; /* Number of hash table entries (keys) */
|
||||
int numVert; /* Number of vertices in the graph (also size of g[]) */
|
||||
unsigned PatLen; /* Size of the keys (pattern length) */
|
||||
unsigned SymLen; /* Max size of the symbols, including null */
|
||||
static FILE *g_file; /* File being read */
|
||||
FILE *f; /* File being read */
|
||||
static char sSigName[100]; /* Full path name of .sig file */
|
||||
|
||||
static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static uint16_t *g; /* g[] */
|
||||
static word *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static word *g; /* g[] */
|
||||
static HT *ht; /* The hash table */
|
||||
static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */
|
||||
static hlType *pArg=0; /* Points to the array of param types */
|
||||
static hlType *pArg; /* Points to the array of param types */
|
||||
static int numFunc; /* Number of func names actually stored */
|
||||
static int numArg; /* Number of param names actually stored */
|
||||
#define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */
|
||||
|
||||
/* prototypes */
|
||||
void grab(int n, FILE *_file);
|
||||
uint16_t readFileShort(FILE *_file);
|
||||
void readFileSection(uint16_t* p, int len, FILE *_file);
|
||||
void grab(int n, FILE *f);
|
||||
word readFileShort(FILE *f);
|
||||
void readFileSection(word* p, int len, FILE *f);
|
||||
void cleanup(void);
|
||||
void checkStartup(STATE *state);
|
||||
void readProtoFile(void);
|
||||
@ -72,17 +71,17 @@ void fixNewline(char *s);
|
||||
int searchPList(char *name);
|
||||
void checkHeap(char *msg); /* For debugging */
|
||||
|
||||
void fixWildCards(uint8_t pat[]); /* In fixwild.c */
|
||||
void fixWildCards(byte pat[]); /* In fixwild.c */
|
||||
|
||||
static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern,
|
||||
int iPatLen, int *index);
|
||||
boolT locatePattern(byte *source, Int iMin, Int iMax, byte *pattern,
|
||||
Int iPatLen, Int *index);
|
||||
|
||||
/* * * * * * * * * * * * * * * *\
|
||||
* *
|
||||
* S t a r t P a t t e r n s ( V e n d o r i d ) *
|
||||
* *
|
||||
\* * * * * * * * * * * * * * * */
|
||||
static uint8_t pattMsC5Start[] =
|
||||
static byte pattMsC5Start[] =
|
||||
{
|
||||
0xB4, 0x30, /* Mov ah, 30 */
|
||||
0xCD, 0x21, /* int 21 (dos version number) */
|
||||
@ -91,7 +90,7 @@ static uint8_t pattMsC5Start[] =
|
||||
0xCD, 0x20, /* int 20 (exit) */
|
||||
0xBF /* Mov di, DSEG */
|
||||
};
|
||||
static uint8_t pattMsC8Start[] =
|
||||
static byte pattMsC8Start[] =
|
||||
{
|
||||
0xB4, 0x30, /* Mov ah, 30 */
|
||||
0xCD, 0x21, /* int 21 */
|
||||
@ -102,7 +101,7 @@ static uint8_t pattMsC8Start[] =
|
||||
0xCB, /* retf */
|
||||
0xBF /* mov di, DSEG */
|
||||
};
|
||||
static uint8_t pattMsC8ComStart[] =
|
||||
static byte pattMsC8ComStart[] =
|
||||
{
|
||||
0xB4, 0x30, /* Mov ah, 30 */
|
||||
0xCD, 0x21, /* int 21 (dos version number) */
|
||||
@ -111,7 +110,7 @@ static uint8_t pattMsC8ComStart[] =
|
||||
0xC3, /* ret */
|
||||
0x8C, 0xDF /* Mov di, ds */
|
||||
};
|
||||
static uint8_t pattBorl2Start[] =
|
||||
static byte pattBorl2Start[] =
|
||||
{
|
||||
0xBA, WILD, WILD, /* Mov dx, dseg */
|
||||
0x2E, 0x89, 0x16, /* mov cs:[], dx */
|
||||
@ -127,7 +126,7 @@ static uint8_t pattBorl2Start[] =
|
||||
0x89, 0x2E, WILD, WILD, /* mov [xx], bp */
|
||||
0xC7 /* mov [xx], -1 */
|
||||
};
|
||||
static uint8_t pattBorl3Start[] =
|
||||
static byte pattBorl3Start[] =
|
||||
{
|
||||
0xBA, WILD, WILD, /* Mov dx, dseg */
|
||||
0x2E, 0x89, 0x16, /* mov cs:[], dx */
|
||||
@ -144,12 +143,12 @@ static uint8_t pattBorl3Start[] =
|
||||
0xE8 /* call ... */
|
||||
};
|
||||
|
||||
static uint8_t pattBorl4on[] =
|
||||
static byte pattBorl4on[] =
|
||||
{
|
||||
0x9A, 0, 0, WILD, WILD /* Call init (offset always 0) */
|
||||
};
|
||||
|
||||
static uint8_t pattBorl4Init[] =
|
||||
static byte pattBorl4Init[] =
|
||||
{
|
||||
0xBA, WILD, WILD, /* Mov dx, dseg */
|
||||
0x8E, 0xDA, /* mov ds, dx */
|
||||
@ -161,7 +160,7 @@ static uint8_t pattBorl4Init[] =
|
||||
0x8C, 0xD2 /* mov dx, ss */
|
||||
};
|
||||
|
||||
static uint8_t pattBorl5Init[] =
|
||||
static byte pattBorl5Init[] =
|
||||
{
|
||||
0xBA, WILD, WILD, /* Mov dx, dseg */
|
||||
0x8E, 0xDA, /* mov ds, dx */
|
||||
@ -174,7 +173,7 @@ static uint8_t pattBorl5Init[] =
|
||||
0x8C, 0xD2 /* mov dx, ss */
|
||||
};
|
||||
|
||||
static uint8_t pattBorl7Init[] =
|
||||
static byte pattBorl7Init[] =
|
||||
{
|
||||
0xBA, WILD, WILD, /* Mov dx, dseg */
|
||||
0x8E, 0xDA, /* mov ds, dx */
|
||||
@ -189,7 +188,7 @@ static uint8_t pattBorl7Init[] =
|
||||
};
|
||||
|
||||
|
||||
static uint8_t pattLogiStart[] =
|
||||
static byte pattLogiStart[] =
|
||||
{
|
||||
0xEB, 0x04, /* jmp short $+6 */
|
||||
WILD, WILD, /* Don't know what this is */
|
||||
@ -198,7 +197,7 @@ static uint8_t pattLogiStart[] =
|
||||
0x8E, 0xD8 /* mov ds, ax */
|
||||
};
|
||||
|
||||
static uint8_t pattTPasStart[] =
|
||||
static byte pattTPasStart[] =
|
||||
{
|
||||
0xE9, 0x79, 0x2C /* Jmp 2D7C - Turbo pascal 3.0 */
|
||||
};
|
||||
@ -213,34 +212,34 @@ static uint8_t pattTPasStart[] =
|
||||
|
||||
|
||||
/* This pattern works for MS and Borland, small and tiny model */
|
||||
static uint8_t pattMainSmall[] =
|
||||
static byte pattMainSmall[] =
|
||||
{
|
||||
0xFF, 0x36, WILD, WILD, /* Push environment pointer */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0xE8, WILD, WILD /* call _main */
|
||||
/* 0x50, /* push ax... not in Borland V3 */
|
||||
/* 0xE8 /* call _exit */
|
||||
/* 0x50, /* push ax... not in Borland V3 */
|
||||
/* 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINSMALL 13
|
||||
|
||||
/* This pattern works for MS and Borland, medium model */
|
||||
static uint8_t pattMainMedium[] =
|
||||
static byte pattMainMedium[] =
|
||||
{
|
||||
0xFF, 0x36, WILD, WILD, /* Push environment pointer */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0x9A, WILD, WILD, WILD, WILD /* call far _main */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs NB not tested Borland */
|
||||
/* 0xE8 /* call _exit */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs NB not tested Borland */
|
||||
/* 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINMEDIUM 13
|
||||
|
||||
/* This pattern works for MS and Borland, compact model */
|
||||
static uint8_t pattMainCompact[] =
|
||||
static byte pattMainCompact[] =
|
||||
{
|
||||
0xFF, 0x36, WILD, WILD, /* Push environment pointer lo */
|
||||
0xFF, 0x36, WILD, WILD, /* Push environment pointer hi */
|
||||
@ -248,14 +247,14 @@ static uint8_t pattMainCompact[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv hi */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0xE8, WILD, WILD, /* call _main */
|
||||
/* 0x50, /* push ax */
|
||||
/* 0xE8 /* call _exit */
|
||||
/* 0x50, /* push ax */
|
||||
/* 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINCOMPACT 21
|
||||
|
||||
/* This pattern works for MS and Borland, large model */
|
||||
static uint8_t pattMainLarge[] =
|
||||
static byte pattMainLarge[] =
|
||||
{
|
||||
0xFF, 0x36, WILD, WILD, /* Push environment pointer lo */
|
||||
0xFF, 0x36, WILD, WILD, /* Push environment pointer hi */
|
||||
@ -263,9 +262,9 @@ static uint8_t pattMainLarge[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv hi */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0x9A, WILD, WILD, WILD, WILD /* call far _main */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs */
|
||||
/* 0xE8 /* call _exit */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs */
|
||||
/* 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINLARGE 21
|
||||
@ -278,7 +277,7 @@ static uint8_t pattMainLarge[] =
|
||||
\* * * * * * * * * * * * * * * */
|
||||
|
||||
/* This pattern is for the stack check code in Microsoft compilers */
|
||||
static uint8_t pattMsChkstk[] =
|
||||
static byte pattMsChkstk[] =
|
||||
{
|
||||
0x59, /* pop cx */
|
||||
0x8B, 0xDC, /* mov bx, sp */
|
||||
@ -296,13 +295,13 @@ static uint8_t pattMsChkstk[] =
|
||||
|
||||
|
||||
/* This procedure is called to initialise the library check code */
|
||||
void SetupLibCheck(void)
|
||||
void
|
||||
SetupLibCheck(void)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
uint16_t w, len;
|
||||
word w, len;
|
||||
int i;
|
||||
|
||||
if ((g_file = fopen(sSigName, "rb")) == NULL)
|
||||
if ((f = fopen(sSigName, "rb")) == NULL)
|
||||
{
|
||||
printf("Warning: cannot open signature file %s\n", sSigName);
|
||||
return;
|
||||
@ -311,18 +310,18 @@ void SetupLibCheck(void)
|
||||
readProtoFile();
|
||||
|
||||
|
||||
prog.bSigs = false; /* False unless everything goes right */
|
||||
prog.bSigs = FALSE; /* False unless everything goes right */
|
||||
/* Read the parameters */
|
||||
grab(4, g_file);
|
||||
grab(4, f);
|
||||
if (memcmp("dccs", buf, 4) != 0)
|
||||
{
|
||||
printf("Not a dcc signature file!\n");
|
||||
exit(3);
|
||||
}
|
||||
numKeys = readFileShort(g_file);
|
||||
numVert = readFileShort(g_file);
|
||||
PatLen = readFileShort(g_file);
|
||||
SymLen = readFileShort(g_file);
|
||||
numKeys = readFileShort(f);
|
||||
numVert = readFileShort(f);
|
||||
PatLen = readFileShort(f);
|
||||
SymLen = readFileShort(f);
|
||||
if ((PatLen != PATLEN) || (SymLen != SYMLEN))
|
||||
{
|
||||
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n",
|
||||
@ -331,81 +330,80 @@ void SetupLibCheck(void)
|
||||
}
|
||||
|
||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||
/* Set the parameters for the hash table */
|
||||
g_pattern_hasher.init(
|
||||
hashParams( /* Set the parameters for the hash table */
|
||||
numKeys, /* The number of symbols */
|
||||
PatLen, /* The length of the pattern to be hashed */
|
||||
256, /* The character set of the pattern (0-FF) */
|
||||
0, /* Minimum pattern character value */
|
||||
numVert); /* Specifies c, the sparseness of the graph.
|
||||
See Czech, Havas and Majewski for details */
|
||||
T1base = g_pattern_hasher.readT1();
|
||||
T2base = g_pattern_hasher.readT2();
|
||||
g = g_pattern_hasher.readG();
|
||||
|
||||
T1base = readT1();
|
||||
T2base = readT2();
|
||||
g = readG();
|
||||
|
||||
/* Read T1 and T2 tables */
|
||||
grab(2, g_file);
|
||||
grab(2, f);
|
||||
if (memcmp("T1", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T1'\n");
|
||||
exit(3);
|
||||
}
|
||||
len = (uint16_t) (PatLen * 256 * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
len = (word) (PatLen * 256 * sizeof(word));
|
||||
w = readFileShort(f);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T1: file %d, calc %d\n", w, len);
|
||||
exit(4);
|
||||
}
|
||||
readFileSection(T1base, len, g_file);
|
||||
readFileSection(T1base, len, f);
|
||||
|
||||
grab(2, g_file);
|
||||
grab(2, f);
|
||||
if (memcmp("T2", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T2'\n");
|
||||
exit(3);
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
w = readFileShort(f);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T2: file %d, calc %d\n", w, len);
|
||||
exit(4);
|
||||
}
|
||||
readFileSection(T2base, len, g_file);
|
||||
readFileSection(T2base, len, f);
|
||||
|
||||
/* Now read the function g[] */
|
||||
grab(2, g_file);
|
||||
grab(2, f);
|
||||
if (memcmp("gg", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'gg'\n");
|
||||
exit(3);
|
||||
}
|
||||
len = (uint16_t)(numVert * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
len = (word)(numVert * sizeof(word));
|
||||
w = readFileShort(f);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of g[]: file %d, calc %d\n", w, len);
|
||||
exit(4);
|
||||
}
|
||||
readFileSection(g, len, g_file);
|
||||
readFileSection(g, len, f);
|
||||
|
||||
|
||||
/* This is now the hash table */
|
||||
/* First allocate space for the table */
|
||||
ht = new HT[numKeys];
|
||||
if ( 0 == ht)
|
||||
if ((ht = (HT *)allocMem(numKeys * sizeof(HT))) == 0)
|
||||
{
|
||||
printf("Could not allocate hash table\n");
|
||||
exit(1);
|
||||
}
|
||||
grab(2, g_file);
|
||||
grab(2, f);
|
||||
if (memcmp("ht", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'ht'\n");
|
||||
exit(3);
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != numKeys * (SymLen + PatLen + sizeof(uint16_t)))
|
||||
w = readFileShort(f);
|
||||
if (w != numKeys * (SymLen + PatLen + sizeof(word)))
|
||||
{
|
||||
printf("Problem with size of hash table: file %d, calc %d\n", w, len);
|
||||
exit(6);
|
||||
@ -414,136 +412,143 @@ void SetupLibCheck(void)
|
||||
|
||||
for (i=0; i < numKeys; i++)
|
||||
{
|
||||
if (fread(&ht[i], 1, SymLen + PatLen, g_file) != SymLen + PatLen)
|
||||
if (fread(&ht[i], 1, SymLen + PatLen, f) != SymLen + PatLen)
|
||||
{
|
||||
printf("Could not read signature\n");
|
||||
exit(11);
|
||||
}
|
||||
}
|
||||
fclose(g_file);
|
||||
prog.bSigs = true;
|
||||
fclose(f);
|
||||
prog.bSigs = TRUE;
|
||||
}
|
||||
|
||||
|
||||
void CleanupLibCheck(void)
|
||||
void
|
||||
CleanupLibCheck(void)
|
||||
{
|
||||
/* Deallocate all the stuff allocated in SetupLibCheck() */
|
||||
delete [] ht;
|
||||
delete [] pFunc;
|
||||
if (T1base) free(T1base);
|
||||
if (T1base) free(T2base);
|
||||
if (g) free(g);
|
||||
if (ht) free(ht);
|
||||
if (pFunc)free(pFunc);
|
||||
}
|
||||
|
||||
|
||||
/* Check this function to see if it is a library function. Return true if
|
||||
/* Check this function to see if it is a library function. Return TRUE if
|
||||
it is, and copy its name to pProc->name
|
||||
*/
|
||||
bool LibCheck(Function & pProc)
|
||||
boolT
|
||||
LibCheck(PPROC pProc)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
long fileOffset;
|
||||
int h, i, j, arg;
|
||||
int Idx;
|
||||
uint8_t pat[PATLEN];
|
||||
Int Idx;
|
||||
byte pat[PATLEN];
|
||||
|
||||
if (prog.bSigs == false)
|
||||
if (prog.bSigs == FALSE)
|
||||
{
|
||||
/* No signatures... can't rely on hash parameters to be initialised
|
||||
so always return false */
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fileOffset = pProc.procEntry; /* Offset into the image */
|
||||
fileOffset = pProc->procEntry; /* Offset into the image */
|
||||
if (fileOffset == prog.offMain)
|
||||
{
|
||||
/* Easy - this function is called main! */
|
||||
pProc.name = "main";
|
||||
return false;
|
||||
strcpy(pProc->name, "main");
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(pat, &prog.Image[fileOffset], PATLEN);
|
||||
//memmove(pat, &prog.Image[fileOffset], PATLEN);
|
||||
|
||||
memmove(pat, &prog.Image[fileOffset], PATLEN);
|
||||
fixWildCards(pat); /* Fix wild cards in the copy */
|
||||
h = g_pattern_hasher.hash(pat); /* Hash the found proc */
|
||||
h = hash(pat); /* Hash the found proc */
|
||||
/* We always have to compare keys, because the hash function will
|
||||
always return a valid index */
|
||||
if (memcmp(ht[h].htPat, pat, PATLEN) == 0)
|
||||
{
|
||||
/* We have a match. Save the name, if not already set */
|
||||
if (pProc.name.empty() ) /* Don't overwrite existing name */
|
||||
if (pProc->name[0] == '\0') /* Don't overwrite existing name */
|
||||
{
|
||||
/* Give proc the new name */
|
||||
pProc.name = ht[h].htSym;
|
||||
strcpy(pProc->name, ht[h].htSym);
|
||||
}
|
||||
/* But is it a real library function? */
|
||||
i = NIL;
|
||||
if ((numFunc == 0) || (i=searchPList(ht[h].htSym)) != NIL)
|
||||
{
|
||||
pProc.flg |= PROC_ISLIB; /* It's a lib function */
|
||||
pProc->flg |= PROC_ISLIB; /* It's a lib function */
|
||||
if (i != NIL)
|
||||
{
|
||||
/* Allocate space for the arg struct, and copy the hlType to
|
||||
the appropriate field */
|
||||
arg = pFunc[i].firstArg;
|
||||
pProc.args.numArgs = pFunc[i].numArg;
|
||||
pProc.args.resize(pFunc[i].numArg);
|
||||
pProc->args.csym = pFunc[i].numArg;
|
||||
pProc->args.alloc = pFunc[i].numArg;
|
||||
pProc->args.numArgs = pFunc[i].numArg;
|
||||
pProc->args.sym = (STKSYM*)allocMem(pFunc[i].numArg * sizeof(STKSYM));
|
||||
memset(pProc->args.sym, 0, pFunc[i].numArg * sizeof(STKSYM));
|
||||
for (j=0; j < pFunc[i].numArg; j++)
|
||||
{
|
||||
pProc.args[j].type = pArg[arg++];
|
||||
pProc->args.sym[j].type = pArg[arg++];
|
||||
}
|
||||
if (pFunc[i].typ != TYPE_UNKNOWN)
|
||||
{
|
||||
pProc.retVal.type = pFunc[i].typ;
|
||||
pProc.flg |= PROC_IS_FUNC;
|
||||
switch (pProc.retVal.type) {
|
||||
pProc->retVal.type = pFunc[i].typ;
|
||||
pProc->flg |= PROC_IS_FUNC;
|
||||
switch (pProc->retVal.type) {
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
pProc.liveOut = duReg[rDX] | duReg[rAX];
|
||||
pProc->liveOut = duReg[rDX] | duReg[rAX];
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
pProc.liveOut = duReg[rAX];
|
||||
pProc->liveOut = duReg[rAX];
|
||||
break;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
pProc.liveOut = duReg[rAL];
|
||||
pProc->liveOut = duReg[rAL];
|
||||
break;
|
||||
/*** other types are not considered yet ***/
|
||||
}
|
||||
}
|
||||
if (pFunc[i].bVararg)
|
||||
pProc.flg |= PROC_VARARG;
|
||||
if (pFunc[i].bVararg) pProc->flg |= PROC_VARARG;
|
||||
}
|
||||
}
|
||||
else if (i == NIL)
|
||||
{
|
||||
/* Have a symbol for it, but does not appear in a header file.
|
||||
Treat it as if it is not a library function */
|
||||
pProc.flg |= PROC_RUNTIME; /* => is a runtime routine */
|
||||
pProc->flg |= PROC_RUNTIME; /* => is a runtime routine */
|
||||
}
|
||||
}
|
||||
if (locatePattern(prog.Image, pProc.procEntry,
|
||||
pProc.procEntry+sizeof(pattMsChkstk),
|
||||
|
||||
if (locatePattern(prog.Image, pProc->procEntry,
|
||||
pProc->procEntry+sizeof(pattMsChkstk),
|
||||
pattMsChkstk, sizeof(pattMsChkstk), &Idx))
|
||||
{
|
||||
/* Found _chkstk */
|
||||
pProc.name = "chkstk";
|
||||
pProc.flg |= PROC_ISLIB; /* We'll say its a lib function */
|
||||
pProc.args.numArgs = 0; /* With no args */
|
||||
strcpy(pProc->name, "chkstk");
|
||||
pProc->flg |= PROC_ISLIB; /* We'll say its a lib function */
|
||||
pProc->args.numArgs = 0; /* With no args */
|
||||
}
|
||||
|
||||
return (boolT)((pProc.flg & PROC_ISLIB) != 0);
|
||||
return (boolT)((pProc->flg & PROC_ISLIB) != 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void grab(int n, FILE *_file)
|
||||
void grab(int n, FILE *f)
|
||||
{
|
||||
if (fread(buf, 1, n, _file) != (unsigned)n)
|
||||
if (fread(buf, 1, n, f) != (unsigned)n)
|
||||
{
|
||||
printf("Could not grab\n");
|
||||
exit(11);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
word
|
||||
readFileShort(FILE *f)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
byte b1, b2;
|
||||
|
||||
if (fread(&b1, 1, 1, f) != 1)
|
||||
{
|
||||
@ -555,12 +560,12 @@ readFileShort(FILE *f)
|
||||
printf("Could not read short\n");
|
||||
exit(11);
|
||||
}
|
||||
return (uint16_t)(b2 << 8) + (uint16_t)b1;
|
||||
return (word)(b2 << 8) + (word)b1;
|
||||
}
|
||||
|
||||
// Read a section of the file, considering endian issues
|
||||
void
|
||||
readFileSection(uint16_t* p, int len, FILE* f)
|
||||
readFileSection(word* p, int len, FILE* f)
|
||||
{
|
||||
for (int i=0; i < len; i += 2)
|
||||
{
|
||||
@ -569,7 +574,7 @@ readFileSection(uint16_t* p, int len, FILE* f)
|
||||
}
|
||||
|
||||
/* The following two functions are dummies, since we don't call map() */
|
||||
void getKey(int i, uint8_t **keys)
|
||||
void getKey(int i, byte **keys)
|
||||
{
|
||||
|
||||
}
|
||||
@ -581,16 +586,17 @@ void dispKey(int i)
|
||||
|
||||
/* Search the source array between limits iMin and iMax for the pattern (length
|
||||
iPatLen). The pattern can contain wild bytes; if you really want to match
|
||||
for the pattern that is used up by the WILD uint8_t, tough - it will match with
|
||||
for the pattern that is used up by the WILD byte, tough - it will match with
|
||||
everything else as well. */
|
||||
static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen,
|
||||
int *index)
|
||||
boolT
|
||||
locatePattern(byte *source, Int iMin, Int iMax, byte *pattern, Int iPatLen,
|
||||
Int *index)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t *pSrc; /* Pointer to start of considered source */
|
||||
int iLast;
|
||||
Int i, j;
|
||||
byte *pSrc; /* Pointer to start of considered source */
|
||||
Int iLast;
|
||||
|
||||
iLast = iMax - iPatLen; /* Last source uint8_t to consider */
|
||||
iLast = iMax - iPatLen; /* Last source byte to consider */
|
||||
|
||||
for (i=iMin; i <= iLast; i++)
|
||||
{
|
||||
@ -598,13 +604,12 @@ static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern
|
||||
/* i is the index of the start of the moving pattern */
|
||||
for (j=0; j < iPatLen; j++)
|
||||
{
|
||||
/* j is the index of the uint8_t being considered in the pattern. */
|
||||
if ((*pSrc != pattern[j]) && (pattern[j] != WILD))
|
||||
/* j is the index of the byte being considered in the pattern. */
|
||||
if ((*pSrc++ != pattern[j]) && (pattern[j] != WILD))
|
||||
{
|
||||
/* A definite mismatch */
|
||||
break; /* Break to outer loop */
|
||||
}
|
||||
pSrc++;
|
||||
}
|
||||
if (j >= iPatLen)
|
||||
{
|
||||
@ -620,53 +625,54 @@ static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern
|
||||
}
|
||||
|
||||
|
||||
void STATE::checkStartup()
|
||||
void
|
||||
checkStartup(STATE *pState)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
/* This function checks the startup code for various compilers' way of
|
||||
loading DS. If found, it sets DS. This may not be needed in the future if
|
||||
pushing and popping of registers is implemented.
|
||||
Also sets prog.offMain and prog.segMain if possible */
|
||||
|
||||
|
||||
int startOff; /* Offset into the Image of the initial CS:IP */
|
||||
int i, rel, para, init;
|
||||
Int startOff; /* Offset into the Image of the initial CS:IP */
|
||||
Int i, rel, para, init;
|
||||
char chModel = 'x';
|
||||
char chVendor = 'x';
|
||||
char chVersion = 'x';
|
||||
char *pPath;
|
||||
char temp[4];
|
||||
|
||||
startOff = ((uint32_t)prog.initCS << 4) + prog.initIP;
|
||||
startOff = ((dword)prog.initCS << 4) + prog.initIP;
|
||||
|
||||
/* Check the Turbo Pascal signatures first, since they involve only the
|
||||
first 3 bytes, and false positives may be founf with the others later */
|
||||
if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
|
||||
if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on,
|
||||
sizeof(pattBorl4on), &i))
|
||||
{
|
||||
/* The first 5 bytes are a far call. Follow that call and
|
||||
determine the version from that */
|
||||
rel = LH(&prog.Image[startOff+1]); /* This is abs off of init */
|
||||
para= LH(&prog.Image[startOff+3]);/* This is abs seg of init */
|
||||
init = ((uint32_t)para << 4) + rel;
|
||||
init = ((dword)para << 4) + rel;
|
||||
if (locatePattern(prog.Image, init, init+26, pattBorl4Init,
|
||||
sizeof(pattBorl4Init), &i))
|
||||
{
|
||||
|
||||
setState(rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland Pascal v4 detected\n");
|
||||
setState(pState, rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland Pascal v4 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
chVersion = '4'; /* Version 4 */
|
||||
prog.offMain = startOff; /* Code starts immediately */
|
||||
prog.segMain = prog.initCS; /* At the 5 uint8_t jump */
|
||||
prog.segMain = prog.initCS; /* At the 5 byte jump */
|
||||
goto gotVendor; /* Already have vendor */
|
||||
}
|
||||
else if (locatePattern(prog.Image, init, init+26, pattBorl5Init,
|
||||
sizeof(pattBorl5Init), &i))
|
||||
{
|
||||
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland Pascal v5.0 detected\n");
|
||||
setState(pState, rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland Pascal v5.0 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
chVersion = '5'; /* Version 5 */
|
||||
@ -678,8 +684,8 @@ void STATE::checkStartup()
|
||||
sizeof(pattBorl7Init), &i))
|
||||
{
|
||||
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland Pascal v7 detected\n");
|
||||
setState(pState, rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland Pascal v7 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
chVersion = '7'; /* Version 7 */
|
||||
@ -695,21 +701,20 @@ void STATE::checkStartup()
|
||||
but decides the model required. Note: must do the far data models
|
||||
(large and compact) before the others, since they are the same pattern
|
||||
as near data, just more pushes at the start. */
|
||||
if(prog.cbImage>startOff+0x180+sizeof(pattMainLarge))
|
||||
{
|
||||
if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
|
||||
if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,
|
||||
sizeof(pattMainLarge), &i))
|
||||
{
|
||||
rel = LH(&prog.Image[i+OFFMAINLARGE]); /* This is abs off of main */
|
||||
para= LH(&prog.Image[i+OFFMAINLARGE+2]);/* This is abs seg of main */
|
||||
/* Save absolute image offset */
|
||||
prog.offMain = ((uint32_t)para << 4) + rel;
|
||||
prog.segMain = (uint16_t)para;
|
||||
prog.offMain = ((dword)para << 4) + rel;
|
||||
prog.segMain = (word)para;
|
||||
chModel = 'l'; /* Large model */
|
||||
}
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainCompact,
|
||||
sizeof(pattMainCompact), &i))
|
||||
{
|
||||
rel = LH_SIGNED(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
|
||||
rel = LHS(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
|
||||
prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */
|
||||
prog.segMain = prog.initCS;
|
||||
chModel = 'c'; /* Compact model */
|
||||
@ -719,29 +724,29 @@ void STATE::checkStartup()
|
||||
{
|
||||
rel = LH(&prog.Image[i+OFFMAINMEDIUM]); /* This is abs off of main */
|
||||
para= LH(&prog.Image[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
|
||||
prog.offMain = ((uint32_t)para << 4) + rel;
|
||||
prog.segMain = (uint16_t)para;
|
||||
prog.offMain = ((dword)para << 4) + rel;
|
||||
prog.segMain = (word)para;
|
||||
chModel = 'm'; /* Medium model */
|
||||
}
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainSmall,
|
||||
sizeof(pattMainSmall), &i))
|
||||
{
|
||||
rel = LH_SIGNED(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */
|
||||
rel = LHS(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */
|
||||
prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */
|
||||
prog.segMain = prog.initCS;
|
||||
chModel = 's'; /* Small model */
|
||||
}
|
||||
else if (memcmp(&prog.Image[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
|
||||
{
|
||||
rel = LH_SIGNED(&prog.Image[startOff+1]); /* Get the jump offset */
|
||||
rel = LHS(&prog.Image[startOff+1]); /* Get the jump offset */
|
||||
prog.offMain = rel+startOff+3; /* Save absolute image offset */
|
||||
prog.offMain += 0x20; /* These first 32 bytes are setting up */
|
||||
prog.segMain = prog.initCS;
|
||||
chVendor = 't'; /* Turbo.. */
|
||||
chModel = 'p'; /* ...Pascal... (only 1 model) */
|
||||
chVersion = '3'; /* 3.0 */
|
||||
printf("Turbo Pascal 3.0 detected\n");
|
||||
printf("Main at %04X\n", prog.offMain);
|
||||
printf("Turbo Pascal 3.0 detected\n");
|
||||
printf("Main at %04X\n", prog.offMain);
|
||||
goto gotVendor; /* Already have vendor */
|
||||
}
|
||||
else
|
||||
@ -749,14 +754,7 @@ void STATE::checkStartup()
|
||||
printf("Main could not be located!\n");
|
||||
prog.offMain = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Main could not be located!\n");
|
||||
prog.offMain = -1;
|
||||
}
|
||||
|
||||
printf("Model: %c\n", chModel);
|
||||
printf("Model: %c\n", chModel);
|
||||
|
||||
|
||||
/* Now decide the compiler vendor and version number */
|
||||
@ -764,17 +762,17 @@ void STATE::checkStartup()
|
||||
{
|
||||
/* Yes, this is Microsoft startup code. The DS is sitting right here
|
||||
in the next 2 bytes */
|
||||
setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)]));
|
||||
setState(pState, rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)]));
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '5'; /* Version 5 */
|
||||
printf("MSC 5 detected\n");
|
||||
printf("MSC 5 detected\n");
|
||||
}
|
||||
|
||||
/* The C8 startup pattern is different from C5's */
|
||||
else if (memcmp(&prog.Image[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
|
||||
{
|
||||
setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)]));
|
||||
printf("MSC 8 detected\n");
|
||||
setState(pState, rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)]));
|
||||
printf("MSC 8 detected\n");
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '8'; /* Version 8 */
|
||||
}
|
||||
@ -783,7 +781,7 @@ void STATE::checkStartup()
|
||||
else if (memcmp(&prog.Image[startOff], pattMsC8ComStart,
|
||||
sizeof(pattMsC8ComStart)) == 0)
|
||||
{
|
||||
printf("MSC 8 .com detected\n");
|
||||
printf("MSC 8 .com detected\n");
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '8'; /* Version 8 */
|
||||
}
|
||||
@ -791,9 +789,9 @@ void STATE::checkStartup()
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl2Start,
|
||||
sizeof(pattBorl2Start), &i))
|
||||
{
|
||||
/* Borland startup. DS is at the second uint8_t (offset 1) */
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland v2 detected\n");
|
||||
/* Borland startup. DS is at the second byte (offset 1) */
|
||||
setState(pState, rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland v2 detected\n");
|
||||
chVendor = 'b'; /* Borland compiler */
|
||||
chVersion = '2'; /* Version 2 */
|
||||
}
|
||||
@ -801,9 +799,9 @@ void STATE::checkStartup()
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl3Start,
|
||||
sizeof(pattBorl3Start), &i))
|
||||
{
|
||||
/* Borland startup. DS is at the second uint8_t (offset 1) */
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland v3 detected\n");
|
||||
/* Borland startup. DS is at the second byte (offset 1) */
|
||||
setState(pState, rDS, LH(&prog.Image[i+1]));
|
||||
printf("Borland v3 detected\n");
|
||||
chVendor = 'b'; /* Borland compiler */
|
||||
chVersion = '3'; /* Version 3 */
|
||||
}
|
||||
@ -812,7 +810,7 @@ void STATE::checkStartup()
|
||||
sizeof(pattLogiStart), &i))
|
||||
{
|
||||
/* Logitech modula startup. DS is 0, despite appearances */
|
||||
printf("Logitech modula detected\n");
|
||||
printf("Logitech modula detected\n");
|
||||
chVendor = 'l'; /* Logitech compiler */
|
||||
chVersion = '1'; /* Version 1 */
|
||||
}
|
||||
@ -849,7 +847,7 @@ gotVendor:
|
||||
temp[0] = chModel;
|
||||
strcat(sSigName, temp); /* Add model */
|
||||
strcat(sSigName, ".sig"); /* Add extension */
|
||||
printf("Signature file: %s\n", sSigName);
|
||||
printf("Signature file: %s\n", sSigName);
|
||||
|
||||
}
|
||||
|
||||
@ -860,7 +858,8 @@ gotVendor:
|
||||
by dcc, rather than considered as known functions. When a prototype is
|
||||
found (in searchPList()), the parameter info is written to the proc struct.
|
||||
*/
|
||||
void readProtoFile(void)
|
||||
void
|
||||
readProtoFile(void)
|
||||
{
|
||||
FILE *fProto;
|
||||
char *pPath; /* Point to the environment string */
|
||||
@ -907,21 +906,15 @@ void readProtoFile(void)
|
||||
numFunc = readFileShort(fProto); /* Num of entries to allocate */
|
||||
|
||||
/* Allocate exactly correct # entries */
|
||||
pFunc = new PH_FUNC_STRUCT[numFunc];
|
||||
pFunc = (PH_FUNC_STRUCT*) allocMem(numFunc * sizeof(PH_FUNC_STRUCT));
|
||||
|
||||
for (i=0; i < numFunc; i++)
|
||||
{
|
||||
size_t read_size=fread(&pFunc[i], 1, SYMLEN, fProto);
|
||||
assert(read_size==SYMLEN);
|
||||
if(read_size!=SYMLEN)
|
||||
break;
|
||||
fread(&pFunc[i], 1, SYMLEN, fProto);
|
||||
pFunc[i].typ = (hlType)readFileShort(fProto);
|
||||
pFunc[i].numArg = readFileShort(fProto);
|
||||
pFunc[i].firstArg = readFileShort(fProto);
|
||||
if(feof(fProto))
|
||||
break;
|
||||
int c = fgetc(fProto);
|
||||
pFunc[i].bVararg = (c!=0); //fread(&pFunc[i].bVararg, 1, 1, fProto);
|
||||
fread(&pFunc[i].bVararg, 1, 1, fProto);
|
||||
}
|
||||
|
||||
grab(2, fProto);
|
||||
@ -934,12 +927,11 @@ void readProtoFile(void)
|
||||
numArg = readFileShort(fProto); /* Num of entries to allocate */
|
||||
|
||||
/* Allocate exactly correct # entries */
|
||||
delete [] pArg;
|
||||
pArg = new hlType[numArg];
|
||||
pArg = (hlType*) allocMem(numArg * sizeof(hlType));
|
||||
|
||||
for (i=0; i < numArg; i++)
|
||||
{
|
||||
// fread(&pArg[i], 1, SYMLEN, fProto); /* No names to read as yet */
|
||||
// fread(&pArg[i], 1, SYMLEN, fProto); /* No names to read as yet */
|
||||
pArg[i] = (hlType) readFileShort(fProto);
|
||||
}
|
||||
|
||||
@ -991,4 +983,36 @@ searchPList(char *name)
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_HEAP
|
||||
void
|
||||
checkHeap(char *msg)
|
||||
|
||||
/* HEAPCHK.C: This program checks the heap for
|
||||
* consistency and prints an appropriate message.
|
||||
*/
|
||||
{
|
||||
int heapstatus;
|
||||
|
||||
printf("%s\n", msg);
|
||||
|
||||
/* Check heap status */
|
||||
heapstatus = _heapchk();
|
||||
switch( heapstatus )
|
||||
{
|
||||
case _HEAPOK:
|
||||
printf(" OK - heap is fine\n" );
|
||||
break;
|
||||
case _HEAPEMPTY:
|
||||
printf(" OK - heap is empty\n" );
|
||||
break;
|
||||
case _HEAPBADBEGIN:
|
||||
printf( "ERROR - bad start of heap\n" );
|
||||
break;
|
||||
case _HEAPBADNODE:
|
||||
printf( "ERROR - bad node in heap\n" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
172
src/comwrite.cpp
172
src/comwrite.cpp
@ -7,15 +7,11 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "machine_x86.h"
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
#define intSize 40
|
||||
|
||||
static const char *int21h[] =
|
||||
{
|
||||
"Terminate process",
|
||||
static char *int21h[] =
|
||||
{"Terminate process",
|
||||
"Character input with echo",
|
||||
"Character output",
|
||||
"Auxiliary input",
|
||||
@ -114,7 +110,7 @@ static const char *int21h[] =
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Get PSP address",
|
||||
"Get DBCS lead uint8_t table",
|
||||
"Get DBCS lead byte table",
|
||||
"Reserved",
|
||||
"Get extended country information",
|
||||
"Get or set code page",
|
||||
@ -127,7 +123,7 @@ static const char *int21h[] =
|
||||
};
|
||||
|
||||
|
||||
static const char *intOthers[] = {
|
||||
static char *intOthers[] = {
|
||||
"Exit", /* 0x20 */
|
||||
"", /* other table */
|
||||
"Terminate handler address", /* 0x22 */
|
||||
@ -146,135 +142,123 @@ static const char *intOthers[] = {
|
||||
};
|
||||
|
||||
|
||||
void writeIntComment (PICODE icode, char *s)
|
||||
/* Writes the description of the current interrupt. Appends it to the
|
||||
* string s. */
|
||||
void LLInst::writeIntComment (std::ostringstream &s)
|
||||
{
|
||||
uint32_t src_immed=src().getImm2();
|
||||
s<<"\t/* ";
|
||||
if (src_immed == 0x21)
|
||||
{
|
||||
s <<int21h[dst.off];
|
||||
{ char *t;
|
||||
|
||||
t = (char *)allocMem(intSize * sizeof(char));
|
||||
if (icode->ic.ll.immed.op == 0x21)
|
||||
{ sprintf (t, "\t/* %s */\n", int21h[icode->ic.ll.dst.off]);
|
||||
strcat (s, t);
|
||||
}
|
||||
else if (src_immed > 0x1F && src_immed < 0x2F)
|
||||
else if (icode->ic.ll.immed.op > 0x1F && icode->ic.ll.immed.op < 0x2F)
|
||||
{
|
||||
s <<intOthers[src_immed - 0x20];
|
||||
sprintf (t, "\t/* %s */\n", intOthers[icode->ic.ll.immed.op - 0x20]);
|
||||
strcat (s, t);
|
||||
}
|
||||
else if (src_immed == 0x2F)
|
||||
{
|
||||
switch (dst.off)
|
||||
{
|
||||
case 0x01 :
|
||||
s << "Print spooler";
|
||||
else if (icode->ic.ll.immed.op == 0x2F)
|
||||
switch (icode->ic.ll.dst.off) {
|
||||
case 0x01 : strcat (s, "\t/* Print spooler */\n");
|
||||
break;
|
||||
case 0x02:
|
||||
s << "Assign";
|
||||
case 0x02: strcat (s, "\t/* Assign */\n");
|
||||
break;
|
||||
case 0x10:
|
||||
s << "Share";
|
||||
case 0x10: strcat (s, "\t/* Share */\n");
|
||||
break;
|
||||
case 0xB7:
|
||||
s << "Append";
|
||||
}
|
||||
case 0xB7: strcat (s, "\t/* Append */\n");
|
||||
}
|
||||
else
|
||||
s<<"Unknown int";
|
||||
s<<" */\n";
|
||||
strcat (s, "\n");
|
||||
}
|
||||
|
||||
|
||||
//, &cCode.decl
|
||||
void Function::writeProcComments()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
writeProcComments(ostr);
|
||||
cCode.appendDecl(ostr.str());
|
||||
}
|
||||
|
||||
void Function::writeProcComments(std::ostream &ostr)
|
||||
{
|
||||
int i;
|
||||
void writeProcComments (PPROC p, strTable *strTab)
|
||||
{ int i;
|
||||
ID *id; /* Pointer to register argument identifier */
|
||||
STKSYM * psym; /* Pointer to register argument symbol */
|
||||
PSTKSYM psym; /* Pointer to register argument symbol */
|
||||
|
||||
/* About the parameters */
|
||||
if (this->cbParam)
|
||||
ostr << "/* Takes "<<this->cbParam<<" bytes of parameters.\n";
|
||||
else if (this->flg & REG_ARGS)
|
||||
if (p->cbParam)
|
||||
appendStrTab (strTab, "/* Takes %d bytes of parameters.\n",
|
||||
p->cbParam);
|
||||
else if (p->flg & REG_ARGS)
|
||||
{
|
||||
ostr << "/* Uses register arguments:\n";
|
||||
for (i = 0; i < this->args.numArgs; i++)
|
||||
appendStrTab (strTab, "/* Uses register arguments:\n");
|
||||
for (i = 0; i < p->args.numArgs; i++)
|
||||
{
|
||||
psym = &this->args[i];
|
||||
ostr << " * "<<psym->name<<" = ";
|
||||
psym = &p->args.sym[i];
|
||||
if (psym->regs->expr.ident.idType == REGISTER)
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.regiIdx];
|
||||
ostr << Machine_X86::regName(id->id.regi);
|
||||
id = &p->localId.id[psym->regs->expr.ident.idNode.regiIdx];
|
||||
if (psym->regs->expr.ident.regiType == WORD_REG)
|
||||
appendStrTab (strTab, " * %s = %s.\n", psym->name,
|
||||
wordReg[id->id.regi - rAX]);
|
||||
else /* BYTE_REG */
|
||||
appendStrTab (strTab, " * %s = %s.\n", psym->name,
|
||||
byteReg[id->id.regi - rAL]);
|
||||
}
|
||||
else /* long register */
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.longIdx];
|
||||
ostr << Machine_X86::regName(id->id.longId.h) << ":";
|
||||
ostr << Machine_X86::regName(id->id.longId.l);
|
||||
id = &p->localId.id[psym->regs->expr.ident.idNode.longIdx];
|
||||
appendStrTab (strTab, " * %s = %s:%s.\n", psym->name,
|
||||
wordReg[id->id.longId.h - rAX],
|
||||
wordReg[id->id.longId.l - rAX]);
|
||||
}
|
||||
ostr << ".\n";
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
ostr << "/* Takes no parameters.\n";
|
||||
appendStrTab (strTab, "/* Takes no parameters.\n");
|
||||
|
||||
/* Type of procedure */
|
||||
if (this->flg & PROC_RUNTIME)
|
||||
ostr << " * Runtime support routine of the compiler.\n";
|
||||
if (this->flg & PROC_IS_HLL)
|
||||
ostr << " * High-level language prologue code.\n";
|
||||
if (this->flg & PROC_ASM)
|
||||
if (p->flg & PROC_RUNTIME)
|
||||
appendStrTab (strTab," * Runtime support routine of the compiler.\n");
|
||||
if (p->flg & PROC_IS_HLL)
|
||||
appendStrTab (strTab," * High-level language prologue code.\n");
|
||||
if (p->flg & PROC_ASM)
|
||||
{
|
||||
ostr << " * Untranslatable routine. Assembler provided.\n";
|
||||
if (this->flg & PROC_IS_FUNC)
|
||||
switch (this->retVal.type) { // TODO: Functions return value in various regs
|
||||
appendStrTab (strTab,
|
||||
" * Untranslatable routine. Assembler provided.\n");
|
||||
if (p->flg & PROC_IS_FUNC)
|
||||
switch (p->retVal.type) {
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
ostr << " * Return value in register al.\n";
|
||||
appendStrTab (strTab, " * Return value in register al.\n");
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
ostr << " * Return value in register ax.\n";
|
||||
appendStrTab (strTab, " * Return value in register ax.\n");
|
||||
break;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
appendStrTab (strTab, " * Return value in registers dx:ax.\n");
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
/* Calling convention */
|
||||
if (this->flg & CALL_PASCAL)
|
||||
ostr << " * Pascal calling convention.\n";
|
||||
else if (this->flg & CALL_C)
|
||||
ostr << " * C calling convention.\n";
|
||||
else if (this->flg & CALL_UNKNOWN)
|
||||
ostr << " * Unknown calling convention.\n";
|
||||
if (p->flg & CALL_PASCAL)
|
||||
appendStrTab (strTab, " * Pascal calling convention.\n");
|
||||
else if (p->flg & CALL_C)
|
||||
appendStrTab (strTab, " * C calling convention.\n");
|
||||
else if (p->flg & CALL_UNKNOWN)
|
||||
appendStrTab (strTab, " * Unknown calling convention.\n");
|
||||
|
||||
/* Other flags */
|
||||
if (this->flg & (PROC_BADINST | PROC_IJMP))
|
||||
{
|
||||
ostr << " * Incomplete due to an ";
|
||||
if(this->flg & PROC_BADINST)
|
||||
ostr << "untranslated opcode.\n";
|
||||
else
|
||||
ostr << "indirect JMP.\n";
|
||||
}
|
||||
if (this->flg & PROC_ICALL)
|
||||
ostr << " * Indirect call procedure.\n";
|
||||
if (this->flg & IMPURE)
|
||||
ostr << " * Contains impure code.\n";
|
||||
if (this->flg & NOT_HLL)
|
||||
ostr << " * Contains instructions not normally used by compilers.\n";
|
||||
if (this->flg & FLOAT_OP)
|
||||
ostr << " * Contains coprocessor instructions.\n";
|
||||
if (p->flg & (PROC_BADINST | PROC_IJMP))
|
||||
appendStrTab (strTab, " * Incomplete due to an %s.\n",
|
||||
(p->flg & PROC_BADINST)? "untranslated opcode":
|
||||
"indirect JMP");
|
||||
if (p->flg & PROC_ICALL)
|
||||
appendStrTab (strTab, " * Indirect call procedure.\n");
|
||||
if (p->flg & IMPURE)
|
||||
appendStrTab (strTab, " * Contains impure code.\n");
|
||||
if (p->flg & NOT_HLL)
|
||||
appendStrTab (strTab,
|
||||
" * Contains instructions not normally used by compilers.\n");
|
||||
if (p->flg & FLOAT_OP)
|
||||
appendStrTab (strTab," * Contains coprocessor instructions.\n");
|
||||
|
||||
/* Graph reducibility */
|
||||
if (this->flg & GRAPH_IRRED)
|
||||
ostr << " * Irreducible control flow graph.\n";
|
||||
ostr << " */\n{\n";
|
||||
if (p->flg & GRAPH_IRRED)
|
||||
appendStrTab (strTab," * Irreducible control flow graph.\n");
|
||||
appendStrTab (strTab, " */\n{\n");
|
||||
}
|
||||
|
||||
|
||||
677
src/control.cpp
677
src/control.cpp
@ -2,21 +2,21 @@
|
||||
* Description : Performs control flow analysis on the CFG
|
||||
* (C) Cristina Cifuentes
|
||||
********************************************************************/
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "dcc.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
typedef struct list {
|
||||
Int nodeIdx; /* dfsLast index to the node */
|
||||
struct list *next;
|
||||
} nodeList;
|
||||
|
||||
//typedef struct list {
|
||||
// int nodeIdx;
|
||||
// struct list *next;
|
||||
//} nodeList;
|
||||
typedef std::list<int> nodeList; /* dfsLast index to the node */
|
||||
|
||||
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) && (a->dfsFirstNum < b->dfsFirstNum))
|
||||
/* there is a path on the DFST from a to b if the a was first visited in a
|
||||
@ -24,24 +24,24 @@ typedef std::list<int> nodeList; /* dfsLast index to the node */
|
||||
* node. */
|
||||
|
||||
|
||||
static boolT isBackEdge (PBB p,PBB s)
|
||||
/* Checks if the edge (p,s) is a back edge. If node s was visited first
|
||||
* during the dfs traversal (ie. s has a smaller dfsFirst number) or s == p,
|
||||
* then it is a backedge.
|
||||
* Also incrementes the number of backedges entries to the header node. */
|
||||
static bool isBackEdge (BB * p,BB * s)
|
||||
{
|
||||
if (p->dfsFirstNum >= s->dfsFirstNum)
|
||||
{
|
||||
s->numBackEdges++;
|
||||
return true;
|
||||
return (TRUE);
|
||||
}
|
||||
return false;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static Int commonDom (Int currImmDom, Int predImmDom, PPROC pProc)
|
||||
/* Finds the common dominator of the current immediate dominator
|
||||
* currImmDom and its predecessor's immediate dominator predImmDom */
|
||||
static int commonDom (int currImmDom, int predImmDom, Function * pProc)
|
||||
{
|
||||
if (currImmDom == NO_DOM)
|
||||
return (predImmDom);
|
||||
@ -52,113 +52,141 @@ static int commonDom (int currImmDom, int predImmDom, Function * pProc)
|
||||
(currImmDom != predImmDom))
|
||||
{
|
||||
if (currImmDom < predImmDom)
|
||||
predImmDom = pProc->m_dfsLast[predImmDom]->immedDom;
|
||||
predImmDom = pProc->dfsLast[predImmDom]->immedDom;
|
||||
else
|
||||
currImmDom = pProc->m_dfsLast[currImmDom]->immedDom;
|
||||
currImmDom = pProc->dfsLast[currImmDom]->immedDom;
|
||||
}
|
||||
return (currImmDom);
|
||||
}
|
||||
|
||||
|
||||
static void findImmedDom (PPROC pProc)
|
||||
/* Finds the immediate dominator of each node in the graph pProc->cfg.
|
||||
* Adapted version of the dominators algorithm by Hecht and Ullman; finds
|
||||
* immediate dominators only.
|
||||
* Note: graph should be reducible */
|
||||
void Function::findImmedDom ()
|
||||
{
|
||||
BB * currNode;
|
||||
for (size_t currIdx = 0; currIdx < numBBs; currIdx++)
|
||||
{ PBB currNode;
|
||||
Int currIdx, j, predIdx;
|
||||
|
||||
for (currIdx = 0; currIdx < pProc->numBBs; currIdx++)
|
||||
{
|
||||
currNode = m_dfsLast[currIdx];
|
||||
currNode = pProc->dfsLast[currIdx];
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
for (BB * inedge : currNode->inEdges)
|
||||
|
||||
for (j = 0; j < currNode->numInEdges; j++)
|
||||
{
|
||||
size_t predIdx = inedge->dfsLastNum;
|
||||
predIdx = currNode->inEdges[j]->dfsLastNum;
|
||||
if (predIdx < currIdx)
|
||||
currNode->immedDom = commonDom (currNode->immedDom, predIdx, this);
|
||||
currNode->immedDom = commonDom (currNode->immedDom,
|
||||
predIdx, pProc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void insertList (nodeList **l, Int n)
|
||||
/* Inserts the node n to the list l. */
|
||||
static void insertList (nodeList &l, int n)
|
||||
{
|
||||
l.push_back(n);
|
||||
nodeList *newNode;
|
||||
|
||||
newNode = allocStruc(nodeList);
|
||||
memset(newNode, 0, sizeof(nodeList));
|
||||
newNode->nodeIdx = n;
|
||||
newNode->next = *l;
|
||||
*l = newNode;
|
||||
}
|
||||
|
||||
|
||||
static boolT inList (nodeList *l, Int n)
|
||||
/* Returns whether or not the node n (dfsLast numbering of a basic block)
|
||||
* is on the list l. */
|
||||
static bool inList (const nodeList &l, int n)
|
||||
{
|
||||
return std::find(l.begin(),l.end(),n)!=l.end();
|
||||
while (l)
|
||||
if (l->nodeIdx == n)
|
||||
return (TRUE);
|
||||
else
|
||||
l = l->next;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void freeList (nodeList **l)
|
||||
/* Frees space allocated by the list l. */
|
||||
static void freeList (nodeList &l)
|
||||
{
|
||||
l.clear();
|
||||
{ nodeList *next;
|
||||
|
||||
if (*l)
|
||||
{
|
||||
next = (*l)->next;
|
||||
free (*l);
|
||||
*l = next;
|
||||
}
|
||||
*l = NULL;
|
||||
}
|
||||
|
||||
|
||||
static boolT inInt(PBB n, queue *q)
|
||||
/* Returns whether the node n belongs to the queue list q. */
|
||||
static boolT inInt(BB * n, queue &q)
|
||||
{
|
||||
return std::find(q.begin(),q.end(),n)!=q.end();
|
||||
while (q)
|
||||
if (q->node == n)
|
||||
return (TRUE);
|
||||
else
|
||||
q = q->next;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void findEndlessFollow (PPROC pProc, nodeList *loopNodes, PBB head)
|
||||
/* Finds the follow of the endless loop headed at node head (if any).
|
||||
* The follow node is the closest node to the loop. */
|
||||
static void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
|
||||
{
|
||||
{ nodeList *p;
|
||||
Int j, succ;
|
||||
|
||||
head->loopFollow = MAX;
|
||||
for( int loop_node : loopNodes)
|
||||
p = loopNodes;
|
||||
while (p != NULL)
|
||||
{
|
||||
for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
|
||||
for (j = 0; j < pProc->dfsLast[p->nodeIdx]->numOutEdges; j++)
|
||||
{
|
||||
int succ = typeaddr.BBptr->dfsLastNum;
|
||||
succ = pProc->dfsLast[p->nodeIdx]->edges[j].BBptr->dfsLastNum;
|
||||
if ((! inList(loopNodes, succ)) && (succ < head->loopFollow))
|
||||
head->loopFollow = succ;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes)
|
||||
static void findNodesInLoop(PBB latchNode,PBB head,PPROC pProc,queue *intNodes)
|
||||
/* Flags nodes that belong to the loop determined by (latchNode, head) and
|
||||
* determines the type of loop. */
|
||||
static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &intNodes)
|
||||
{
|
||||
int i, headDfsNum, intNodeType;
|
||||
nodeList loopNodes;
|
||||
int immedDom, /* dfsLast index to immediate dominator */
|
||||
{ Int i, headDfsNum, intNodeType, j;
|
||||
nodeList *loopNodes = NULL, p;
|
||||
Int immedDom, /* dfsLast index to immediate dominator */
|
||||
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
|
||||
BB * pbb;
|
||||
PBB pbb;
|
||||
|
||||
/* Flag nodes in loop headed by head (except header node) */
|
||||
headDfsNum = head->dfsLastNum;
|
||||
head->loopHead = headDfsNum;
|
||||
insertList (loopNodes, headDfsNum);
|
||||
insertList (&loopNodes, headDfsNum);
|
||||
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
|
||||
{
|
||||
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
if (pProc->dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
continue;
|
||||
|
||||
immedDom = pProc->m_dfsLast[i]->immedDom;
|
||||
if (inList (loopNodes, immedDom) && inInt(pProc->m_dfsLast[i], intNodes))
|
||||
immedDom = pProc->dfsLast[i]->immedDom;
|
||||
if (inList (loopNodes, immedDom) && inInt(pProc->dfsLast[i], intNodes))
|
||||
{
|
||||
insertList (loopNodes, i);
|
||||
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
|
||||
pProc->m_dfsLast[i]->loopHead = headDfsNum;
|
||||
insertList (&loopNodes, i);
|
||||
if (pProc->dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
|
||||
pProc->dfsLast[i]->loopHead = headDfsNum;
|
||||
}
|
||||
}
|
||||
latchNode->loopHead = headDfsNum;
|
||||
if (latchNode != head)
|
||||
insertList (loopNodes, latchNode->dfsLastNum);
|
||||
insertList (&loopNodes, latchNode->dfsLastNum);
|
||||
|
||||
/* Determine type of loop and follow node */
|
||||
intNodeType = head->nodeType;
|
||||
@ -173,7 +201,8 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
pProc->Icode.SetLlFlag(latchNode->start + latchNode->length - 1,
|
||||
JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -182,7 +211,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = head->edges[THEN].BBptr->dfsLastNum;
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
pProc->Icode.SetLlFlag(head->start + head->length - 1, JX_LOOP);
|
||||
}
|
||||
else /* head = anything besides 2-way, latch = 2-way */
|
||||
{
|
||||
@ -191,7 +220,8 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
pProc->Icode.SetLlFlag(latchNode->start + latchNode->length - 1,
|
||||
JX_LOOP);
|
||||
}
|
||||
else /* latch = 1-way */
|
||||
if (latchNode->nodeType == LOOP_NODE)
|
||||
@ -226,11 +256,11 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
break;
|
||||
}
|
||||
pbb = pProc->m_dfsLast[pbb->immedDom];
|
||||
pbb = pProc->dfsLast[pbb->immedDom];
|
||||
}
|
||||
if (pbb->dfsLastNum > head->dfsLastNum)
|
||||
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
pProc->dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
pProc->Icode.SetLlFlag(head->start + head->length - 1, JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -238,65 +268,57 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
}
|
||||
|
||||
freeList(loopNodes);
|
||||
freeList(&loopNodes);
|
||||
}
|
||||
|
||||
//static void findNodesInInt (queue **intNodes, int level, interval *Ii)
|
||||
|
||||
static void findNodesInInt (queue **intNodes, Int level, interval *Ii)
|
||||
/* Recursive procedure to find nodes that belong to the interval (ie. nodes
|
||||
* from G1). */
|
||||
static void findNodesInInt (queue &intNodes, int level, interval *Ii)
|
||||
{
|
||||
{ queue *l;
|
||||
|
||||
if (level == 1)
|
||||
{
|
||||
for(BB *en : Ii->nodes)
|
||||
{
|
||||
appendQueue(intNodes,en);
|
||||
}
|
||||
}
|
||||
for (l = Ii->nodes; l; l = l->next)
|
||||
appendQueue (intNodes, l->node);
|
||||
else
|
||||
{
|
||||
for(BB *en : Ii->nodes)
|
||||
{
|
||||
findNodesInInt(intNodes,level-1,en->correspInt);
|
||||
}
|
||||
}
|
||||
for (l = Ii->nodes; l; l= l->next)
|
||||
findNodesInInt (intNodes, level - 1, l->node->correspInt);
|
||||
}
|
||||
|
||||
|
||||
static void structLoops(PPROC pProc, derSeq *derivedG)
|
||||
/* Algorithm for structuring loops */
|
||||
void Function::structLoops(derSeq *derivedG)
|
||||
{
|
||||
interval *Ii;
|
||||
BB * intHead, /* interval header node */
|
||||
* pred, /* predecessor node */
|
||||
* latchNode;/* latching node (in case of loops) */
|
||||
size_t level = 0; /* derived sequence level */
|
||||
{ interval *Ii;
|
||||
PBB intHead, /* interval header node */
|
||||
pred, /* predecessor node */
|
||||
latchNode; /* latching node (in case of loops) */
|
||||
Int i, /* counter */
|
||||
level = 0; /* derived sequence level */
|
||||
interval *initInt; /* initial interval */
|
||||
queue intNodes; /* list of interval nodes */
|
||||
queue *intNodes; /* list of interval nodes */
|
||||
|
||||
/* Structure loops */
|
||||
/* for all derived sequences Gi */
|
||||
for(derSeq::iterator iter=derivedG->begin(); iter!=derivedG->end(); ++iter)
|
||||
while (derivedG) /* for all derived sequences Gi */
|
||||
{
|
||||
level++;
|
||||
Ii = iter->Ii;
|
||||
Ii = derivedG->Ii;
|
||||
while (Ii) /* for all intervals Ii of Gi */
|
||||
{
|
||||
latchNode = NULL;
|
||||
intNodes.clear();
|
||||
intNodes = NULL;
|
||||
|
||||
/* Find interval head (original BB node in G1) and create
|
||||
* list of nodes of interval Ii. */
|
||||
initInt = Ii;
|
||||
for (size_t i = 1; i < level; i++)
|
||||
initInt = (*initInt->nodes.begin())->correspInt;
|
||||
intHead = *initInt->nodes.begin();
|
||||
for (i = 1; i < level; i++)
|
||||
initInt = initInt->nodes->node->correspInt;
|
||||
intHead = initInt->nodes->node;
|
||||
|
||||
/* Find nodes that belong to the interval (nodes from G1) */
|
||||
findNodesInInt (intNodes, level, Ii);
|
||||
findNodesInInt (&intNodes, level, Ii);
|
||||
|
||||
/* Find greatest enclosing back edge (if any) */
|
||||
for (size_t i = 0; i < intHead->inEdges.size(); i++)
|
||||
for (i = 0; i < intHead->numInEdges; i++)
|
||||
{
|
||||
pred = intHead->inEdges[i];
|
||||
if (inInt(pred, intNodes) && isBackEdge(pred, intHead))
|
||||
@ -319,7 +341,7 @@ void Function::structLoops(derSeq *derivedG)
|
||||
(latchNode->loopHead == NO_NODE))
|
||||
{
|
||||
intHead->latchNode = latchNode->dfsLastNum;
|
||||
findNodesInLoop(latchNode, intHead, this, intNodes);
|
||||
findNodesInLoop(latchNode, intHead, pProc, intNodes);
|
||||
latchNode->flg |= IS_LATCH_NODE;
|
||||
}
|
||||
}
|
||||
@ -329,141 +351,141 @@ void Function::structLoops(derSeq *derivedG)
|
||||
}
|
||||
|
||||
/* Next derived sequence */
|
||||
derivedG = derivedG->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolT successor (Int s, Int h, PPROC pProc)
|
||||
/* Returns whether the BB indexed by s is a successor of the BB indexed by
|
||||
* h. Note that h is a case node. */
|
||||
static bool successor (int s, int h, Function * pProc)
|
||||
{
|
||||
BB * header;
|
||||
{ Int i;
|
||||
PBB header;
|
||||
|
||||
header = pProc->m_dfsLast[h];
|
||||
auto iter = std::find_if(header->edges.begin(),
|
||||
header->edges.end(),
|
||||
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
|
||||
return iter!=header->edges.end();
|
||||
header = pProc->dfsLast[h];
|
||||
for (i = 0; i < header->numOutEdges; i++)
|
||||
if (header->edges[i].BBptr->dfsLastNum == s)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void tagNodesInCase (PBB pBB, nodeList **l, Int head, Int tail)
|
||||
/* Recursive procedure to tag nodes that belong to the case described by
|
||||
* the list l, head and tail (dfsLast index to first and exit node of the
|
||||
* case). */
|
||||
static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
{
|
||||
int current, /* index to current node */
|
||||
{ Int current, /* index to current node */
|
||||
i;
|
||||
|
||||
pBB->traversed = DFS_CASE;
|
||||
current = pBB->dfsLastNum;
|
||||
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && (inList (l, pBB->immedDom)))
|
||||
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) &&
|
||||
(inList (*l, pBB->immedDom)))
|
||||
{
|
||||
insertList (l, current);
|
||||
pBB->caseHead = head;
|
||||
for(TYPEADR_TYPE &edge : pBB->edges)
|
||||
{
|
||||
if (edge.BBptr->traversed != DFS_CASE)
|
||||
tagNodesInCase (edge.BBptr, l, head, tail);
|
||||
}
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
if (pBB->edges[i].BBptr->traversed != DFS_CASE)
|
||||
tagNodesInCase (pBB->edges[i].BBptr, l, head, tail);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void structCases(PPROC pProc)
|
||||
/* Structures case statements. This procedure is invoked only when pProc
|
||||
* has a case node. */
|
||||
void Function::structCases()
|
||||
{
|
||||
int i, j;
|
||||
BB * caseHeader; /* case header node */
|
||||
int exitNode = NO_NODE; /* case exit node */
|
||||
nodeList caseNodes; /* temporary: list of nodes in case */
|
||||
{ Int i, j;
|
||||
PBB caseHeader; /* case header node */
|
||||
Int exitNode = NO_NODE; /* case exit node */
|
||||
nodeList *caseNodes = NULL; /* temporary: list of nodes in case */
|
||||
|
||||
/* Linear scan of the nodes in reverse dfsLast order, searching for
|
||||
* case nodes */
|
||||
for (i = numBBs - 1; i >= 0; i--)
|
||||
if (m_dfsLast[i]->nodeType == MULTI_BRANCH)
|
||||
for (i = pProc->numBBs - 1; i >= 0; i--)
|
||||
if (pProc->dfsLast[i]->nodeType == MULTI_BRANCH)
|
||||
{
|
||||
caseHeader = m_dfsLast[i];
|
||||
caseHeader = pProc->dfsLast[i];
|
||||
|
||||
/* Find descendant node which has as immediate predecessor
|
||||
* the current header node, and is not a successor. */
|
||||
for (j = i + 2; j < numBBs; j++)
|
||||
for (j = i + 2; j < pProc->numBBs; j++)
|
||||
{
|
||||
if ((!successor(j, i, this)) &&
|
||||
(m_dfsLast[j]->immedDom == i))
|
||||
if ((!successor(j, i, pProc)) &&
|
||||
(pProc->dfsLast[j]->immedDom == i))
|
||||
if (exitNode == NO_NODE)
|
||||
exitNode = j;
|
||||
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
|
||||
else if (pProc->dfsLast[exitNode]->numInEdges <
|
||||
pProc->dfsLast[j]->numInEdges)
|
||||
exitNode = j;
|
||||
}
|
||||
m_dfsLast[i]->caseTail = exitNode;
|
||||
pProc->dfsLast[i]->caseTail = exitNode;
|
||||
|
||||
/* Tag nodes that belong to the case by recording the
|
||||
* header field with caseHeader. */
|
||||
insertList (caseNodes, i);
|
||||
m_dfsLast[i]->caseHead = i;
|
||||
for(TYPEADR_TYPE &pb : caseHeader->edges)
|
||||
{
|
||||
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
|
||||
}
|
||||
//for (j = 0; j < caseHeader->edges[j]; j++)
|
||||
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
|
||||
insertList (&caseNodes, i);
|
||||
pProc->dfsLast[i]->caseHead = i;
|
||||
for (j = 0; j < caseHeader->numOutEdges; j++)
|
||||
tagNodesInCase (caseHeader->edges[j].BBptr, &caseNodes, i,
|
||||
exitNode);
|
||||
if (exitNode != NO_NODE)
|
||||
m_dfsLast[exitNode]->caseHead = i;
|
||||
pProc->dfsLast[exitNode]->caseHead = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void flagNodes (nodeList **l, Int f, PPROC pProc)
|
||||
/* Flags all nodes in the list l as having follow node f, and deletes all
|
||||
* nodes from the list. */
|
||||
static void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
{
|
||||
nodeList::iterator p;
|
||||
for(int idx : l)
|
||||
{ nodeList *p;
|
||||
|
||||
p = *l;
|
||||
while (p)
|
||||
{
|
||||
pProc->m_dfsLast[idx]->ifFollow = f;
|
||||
pProc->dfsLast[p->nodeIdx]->ifFollow = f;
|
||||
p = p->next;
|
||||
free (*l);
|
||||
*l = p;
|
||||
}
|
||||
l.clear();
|
||||
*l = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void structIfs (PPROC pProc)
|
||||
/* Structures if statements */
|
||||
void Function::structIfs ()
|
||||
{
|
||||
int curr, /* Index for linear scan of nodes */
|
||||
{ Int curr, /* Index for linear scan of nodes */
|
||||
desc, /* Index for descendant */
|
||||
followInEdges, /* Largest # in-edges so far */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved /* List of unresolved if nodes */
|
||||
;
|
||||
BB * currNode, /* Pointer to current node */
|
||||
* pbb;
|
||||
nodeList *domDesc = NULL, /* List of nodes dominated by curr */
|
||||
*unresolved = NULL, /* List of unresolved if nodes */
|
||||
*l; /* Temporary list */
|
||||
PBB currNode, /* Pointer to current node */
|
||||
pbb;
|
||||
|
||||
/* Linear scan of nodes in reverse dfsLast order */
|
||||
for (curr = numBBs - 1; curr >= 0; curr--)
|
||||
for (curr = pProc->numBBs - 1; curr >= 0; curr--)
|
||||
{
|
||||
currNode = m_dfsLast[curr];
|
||||
currNode = pProc->dfsLast[curr];
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
|
||||
if ((currNode->nodeType == TWO_BRANCH) && (!currNode->back().ll()->testFlags(JX_LOOP)))
|
||||
if ((currNode->nodeType == TWO_BRANCH) &&
|
||||
(! (pProc->Icode.GetLlFlag(currNode->start + currNode->length - 1)
|
||||
& JX_LOOP)))
|
||||
{
|
||||
followInEdges = 0;
|
||||
follow = 0;
|
||||
|
||||
/* Find all nodes that have this node as immediate dominator */
|
||||
for (desc = curr+1; desc < numBBs; desc++)
|
||||
for (desc = curr+1; desc < pProc->numBBs; desc++)
|
||||
{
|
||||
if (m_dfsLast[desc]->immedDom == curr)
|
||||
{
|
||||
insertList (domDesc, desc);
|
||||
pbb = m_dfsLast[desc];
|
||||
if ((pbb->inEdges.size() - pbb->numBackEdges) >= followInEdges)
|
||||
if (pProc->dfsLast[desc]->immedDom == curr) {
|
||||
insertList (&domDesc, desc);
|
||||
pbb = pProc->dfsLast[desc];
|
||||
if ((pbb->numInEdges - pbb->numBackEdges) >= followInEdges)
|
||||
{
|
||||
follow = desc;
|
||||
followInEdges = pbb->inEdges.size() - pbb->numBackEdges;
|
||||
followInEdges = pbb->numInEdges - pbb->numBackEdges;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -473,195 +495,234 @@ void Function::structIfs ()
|
||||
if ((follow != 0) && (followInEdges > 1))
|
||||
{
|
||||
currNode->ifFollow = follow;
|
||||
if (!unresolved.empty())
|
||||
flagNodes (unresolved, follow, this);
|
||||
if (unresolved)
|
||||
flagNodes (&unresolved, follow, pProc);
|
||||
}
|
||||
else
|
||||
insertList (unresolved, curr);
|
||||
insertList (&unresolved, curr);
|
||||
}
|
||||
freeList (domDesc);
|
||||
freeList (&domDesc);
|
||||
}
|
||||
}
|
||||
bool Function::removeInEdge_Flag_and_ProcessLatch(BB *pbb,BB *a,BB *b)
|
||||
{
|
||||
/* Remove in-edge e to t */
|
||||
auto iter = std::find(b->inEdges.begin(),b->inEdges.end(),a);
|
||||
assert(iter!=b->inEdges.end());
|
||||
b->inEdges.erase(iter); /* looses 1 arc */
|
||||
a->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
this->m_dfsLast[a->dfsLastNum] = pbb;
|
||||
else
|
||||
return true; /* to repeat this analysis */
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Function::replaceInEdge(BB* where, BB* which,BB* with)
|
||||
{
|
||||
auto iter=std::find(where->inEdges.begin(),where->inEdges.end(),which);
|
||||
assert(iter!=where->inEdges.end());
|
||||
*iter=with;
|
||||
}
|
||||
bool Function::Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
void compoundCond (PPROC pproc)
|
||||
/* Checks for compound conditions of basic blocks that have only 1 high
|
||||
* level instruction. Whenever these blocks are found, they are merged
|
||||
* into one block with the appropriate condition */
|
||||
{ Int i, j, k, numOutEdges;
|
||||
PBB pbb, t, e, obb, pred;
|
||||
PICODE picode, ticode;
|
||||
COND_EXPR *exp;
|
||||
TYPEADR_TYPE *edges;
|
||||
boolT change;
|
||||
|
||||
BB* obb = elseBB->edges[THEN].BBptr;
|
||||
change = TRUE;
|
||||
while (change)
|
||||
{
|
||||
change = FALSE;
|
||||
|
||||
/* Traverse nodes in postorder, this way, the header node of a
|
||||
* compound condition is analysed first */
|
||||
for (i = 0; i < pproc->numBBs; i++)
|
||||
{
|
||||
pbb = pproc->dfsLast[i];
|
||||
if (pbb->flg & INVALID_BB)
|
||||
continue;
|
||||
|
||||
if (pbb->nodeType == TWO_BRANCH)
|
||||
{
|
||||
t = pbb->edges[THEN].BBptr;
|
||||
e = pbb->edges[ELSE].BBptr;
|
||||
|
||||
/* Check (X || Y) case */
|
||||
if ((t->nodeType == TWO_BRANCH) && (t->numHlIcodes == 1) &&
|
||||
(t->numInEdges == 1) && (t->edges[ELSE].BBptr == e))
|
||||
{
|
||||
obb = t->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
hl1.replaceExpr(hl1.expr()->inverse());
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR));
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
replaceInEdge(obb,elseBB,pbb);
|
||||
|
||||
/* New THEN and ELSE out-edges of pbb */
|
||||
pbb->edges[THEN].BBptr = obb;
|
||||
pbb->edges[ELSE].BBptr = thenBB;
|
||||
|
||||
/* Remove in-edge e to t */
|
||||
return removeInEdge_Flag_and_ProcessLatch(pbb,elseBB,thenBB);
|
||||
}
|
||||
bool Function::Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
BB* obb = elseBB->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(),hl2.expr(), DBL_AND));
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
replaceInEdge(obb,elseBB,pbb);
|
||||
/* New ELSE out-edge of pbb */
|
||||
pbb->edges[ELSE].BBptr = obb;
|
||||
|
||||
/* Remove in-edge e to t */
|
||||
return removeInEdge_Flag_and_ProcessLatch(pbb,elseBB,thenBB);
|
||||
}
|
||||
|
||||
|
||||
bool Function::Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
|
||||
BB* obb = thenBB->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
|
||||
hl1.replaceExpr(hl1.expr()->inverse());
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_AND));
|
||||
picode = pproc->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = pproc->Icode.GetIcode(t->start + t->length -1);
|
||||
exp = boolCondExp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_OR);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
replaceInEdge(obb,thenBB,pbb);
|
||||
|
||||
/* New THEN and ELSE out-edges of pbb */
|
||||
pbb->edges[THEN].BBptr = elseBB;
|
||||
pbb->edges[ELSE].BBptr = obb;
|
||||
|
||||
/* Remove in-edge t to e */
|
||||
return removeInEdge_Flag_and_ProcessLatch(pbb,thenBB,elseBB);
|
||||
}
|
||||
|
||||
bool Function::Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
|
||||
BB * obb = thenBB->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR));
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
|
||||
auto iter=find(obb->inEdges.begin(),obb->inEdges.end(),thenBB);
|
||||
if(iter!=obb->inEdges.end())
|
||||
*iter = pbb;
|
||||
for (j = 0; j < obb->numInEdges; j++)
|
||||
if (obb->inEdges[j] == t)
|
||||
{
|
||||
obb->inEdges[j] = pbb;
|
||||
break;
|
||||
}
|
||||
|
||||
/* New THEN out-edge of pbb */
|
||||
pbb->edges[THEN].BBptr = obb;
|
||||
|
||||
/* Remove in-edge t to e */
|
||||
return removeInEdge_Flag_and_ProcessLatch(pbb,thenBB,elseBB);
|
||||
}
|
||||
/** \brief Checks for compound conditions of basic blocks that have only 1 high
|
||||
* level instruction. Whenever these blocks are found, they are merged
|
||||
* into one block with the appropriate condition */
|
||||
void Function::compoundCond()
|
||||
{
|
||||
BB * pbb, * thenBB, * elseBB;
|
||||
bool change = true;
|
||||
while (change)
|
||||
for (j = 0; j < (e->numInEdges-1); j++)
|
||||
if (e->inEdges[j] == t)
|
||||
{
|
||||
change = false;
|
||||
memmove (&e->inEdges[j], &e->inEdges[j+1],
|
||||
(size_t)((e->numInEdges - j - 1) * sizeof(PBB)));
|
||||
break;
|
||||
}
|
||||
e->numInEdges--; /* looses 1 arc */
|
||||
t->flg |= INVALID_BB;
|
||||
|
||||
/* Traverse nodes in postorder, this way, the header node of a
|
||||
* compound condition is analysed first */
|
||||
for (int i = 0; i < this->numBBs; i++)
|
||||
{
|
||||
pbb = this->m_dfsLast[i];
|
||||
if (pbb->flg & INVALID_BB)
|
||||
continue;
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
pproc->dfsLast[t->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
if (pbb->nodeType != TWO_BRANCH)
|
||||
continue;
|
||||
|
||||
thenBB = pbb->edges[THEN].BBptr;
|
||||
elseBB = pbb->edges[ELSE].BBptr;
|
||||
|
||||
change = true; //assume change
|
||||
|
||||
/* Check (X || Y) case */
|
||||
if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
|
||||
(thenBB->inEdges.size() == 1) && (thenBB->edges[ELSE].BBptr == elseBB))
|
||||
{
|
||||
if(Case_X_or_Y(pbb, thenBB, elseBB))
|
||||
--i;
|
||||
change = TRUE;
|
||||
}
|
||||
|
||||
/* Check (!X && Y) case */
|
||||
else if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
|
||||
(thenBB->inEdges.size() == 1) && (thenBB->edges[THEN].BBptr == elseBB))
|
||||
else if ((t->nodeType == TWO_BRANCH) && (t->numHlIcodes == 1) &&
|
||||
(t->numInEdges == 1) && (t->edges[THEN].BBptr == e))
|
||||
{
|
||||
if(Case_notX_and_Y(pbb, thenBB, elseBB))
|
||||
--i;
|
||||
obb = t->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
picode = pproc->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = pproc->Icode.GetIcode(t->start + t->length -1);
|
||||
inverseCondOp (&picode->ic.hl.oper.exp);
|
||||
exp = boolCondExp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_AND);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
for (j = 0; j < obb->numInEdges; j++)
|
||||
if (obb->inEdges[j] == t)
|
||||
{
|
||||
obb->inEdges[j] = pbb;
|
||||
break;
|
||||
}
|
||||
|
||||
/* New THEN and ELSE out-edges of pbb */
|
||||
pbb->edges[THEN].BBptr = e;
|
||||
pbb->edges[ELSE].BBptr = obb;
|
||||
|
||||
/* Remove in-edge t to e */
|
||||
for (j = 0; j < (e->numInEdges-1); j++)
|
||||
if (e->inEdges[j] == t)
|
||||
{
|
||||
memmove (&e->inEdges[j], &e->inEdges[j+1],
|
||||
(size_t)((e->numInEdges - j - 1) * sizeof(PBB)));
|
||||
break;
|
||||
}
|
||||
e->numInEdges--; /* looses 1 arc */
|
||||
t->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
pproc->dfsLast[t->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
|
||||
/* Check (X && Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
|
||||
(elseBB->inEdges.size()==1) && (elseBB->edges[THEN].BBptr == thenBB))
|
||||
else if ((e->nodeType == TWO_BRANCH) && (e->numHlIcodes == 1) &&
|
||||
(e->numInEdges == 1) && (e->edges[THEN].BBptr == t))
|
||||
{
|
||||
if(Case_X_and_Y(pbb, thenBB, elseBB ))
|
||||
--i;
|
||||
obb = e->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
picode = pproc->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = pproc->Icode.GetIcode(t->start + t->length -1);
|
||||
exp = boolCondExp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_AND);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
for (j = 0; j < obb->numInEdges; j++)
|
||||
if (obb->inEdges[j] == e)
|
||||
{
|
||||
obb->inEdges[j] = pbb;
|
||||
break;
|
||||
}
|
||||
|
||||
/* New ELSE out-edge of pbb */
|
||||
pbb->edges[ELSE].BBptr = obb;
|
||||
|
||||
/* Remove in-edge e to t */
|
||||
for (j = 0; j < (t->numInEdges-1); j++)
|
||||
if (t->inEdges[j] == e)
|
||||
{
|
||||
memmove (&t->inEdges[j], &t->inEdges[j+1],
|
||||
(size_t)((t->numInEdges - j - 1) * sizeof(PBB)));
|
||||
break;
|
||||
}
|
||||
t->numInEdges--; /* looses 1 arc */
|
||||
e->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
pproc->dfsLast[e->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
|
||||
/* Check (!X || Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
|
||||
(elseBB->inEdges.size() == 1) && (elseBB->edges[ELSE].BBptr == thenBB))
|
||||
else if ((e->nodeType == TWO_BRANCH) && (e->numHlIcodes == 1) &&
|
||||
(e->numInEdges == 1) && (e->edges[ELSE].BBptr == t))
|
||||
{
|
||||
if(Case_notX_or_Y(pbb, thenBB, elseBB ))
|
||||
--i;
|
||||
obb = e->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
picode = pproc->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = pproc->Icode.GetIcode(t->start + t->length -1);
|
||||
inverseCondOp (&picode->ic.hl.oper.exp);
|
||||
exp = boolCondExp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_OR);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
for (j = 0; j < obb->numInEdges; j++)
|
||||
if (obb->inEdges[j] == e)
|
||||
{
|
||||
obb->inEdges[j] = pbb;
|
||||
break;
|
||||
}
|
||||
|
||||
/* New THEN and ELSE out-edges of pbb */
|
||||
pbb->edges[THEN].BBptr = obb;
|
||||
pbb->edges[ELSE].BBptr = t;
|
||||
|
||||
/* Remove in-edge e to t */
|
||||
for (j = 0; j < (t->numInEdges-1); j++)
|
||||
if (t->inEdges[j] == e)
|
||||
{
|
||||
memmove (&t->inEdges[j], &t->inEdges[j+1],
|
||||
(size_t)((t->numInEdges - j - 1) * sizeof(PBB)));
|
||||
break;
|
||||
}
|
||||
t->numInEdges--; /* looses 1 arc */
|
||||
e->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
pproc->dfsLast[e->dfsLastNum] = pbb;
|
||||
else
|
||||
change = false; // otherwise we changed nothing
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void structure(PPROC pProc, derSeq *derivedG)
|
||||
/* Structuring algorithm to find the structures of the graph pProc->cfg */
|
||||
void Function::structure(derSeq *derivedG)
|
||||
{
|
||||
/* Find immediate dominators of the graph */
|
||||
findImmedDom();
|
||||
if (hasCase)
|
||||
structCases();
|
||||
structLoops(derivedG);
|
||||
structIfs();
|
||||
findImmedDom(pProc);
|
||||
if (pProc->hasCase)
|
||||
structCases(pProc);
|
||||
structLoops(pProc, derivedG);
|
||||
structIfs(pProc);
|
||||
}
|
||||
|
||||
1368
src/dataflow.cpp
1368
src/dataflow.cpp
File diff suppressed because it is too large
Load Diff
74
src/dcc.cpp
74
src/dcc.cpp
@ -5,36 +5,37 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include <string.h>
|
||||
#ifdef __UNIX__
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <io.h> /* For unlink() */
|
||||
#endif
|
||||
|
||||
|
||||
/* Global variables - extern to other modules */
|
||||
char *progname; /* argv[0] - for error msgs */
|
||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
PROG prog; /* programs fields */
|
||||
OPTION option; /* Command line options */
|
||||
//Function * pProcList; /* List of procedures, topologically sort */
|
||||
//Function * pLastProc; /* Pointer to last node in procedure list */
|
||||
//FunctionListType pProcList;
|
||||
//CALL_GRAPH *callGraph; /* Call graph of the program */
|
||||
PPROC pProcList; /* List of procedures, topologically sort */
|
||||
PPROC pLastProc; /* Pointer to last node in procedure list */
|
||||
CALL_GRAPH *callGraph; /* Call graph of the program */
|
||||
|
||||
static char *initargs(int argc, char *argv[]);
|
||||
static void displayTotalStats(void);
|
||||
#include <llvm/Support/raw_os_ostream.h>
|
||||
static void displayTotalStats();
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* main
|
||||
***************************************************************************/
|
||||
#include <iostream>
|
||||
extern Project g_proj;
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// llvm::MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
// llvm::MCAsmInfo info;
|
||||
// llvm::raw_os_ostream wrap(std::cerr);
|
||||
// op.print(wrap,&info);
|
||||
// wrap.flush();
|
||||
/* Extract switches and filename */
|
||||
strcpy(option.filename, initargs(argc, argv));
|
||||
|
||||
@ -42,9 +43,7 @@ int main(int argc, char *argv[])
|
||||
* building the call graph and attaching appropriate bits of code for
|
||||
* each procedure.
|
||||
*/
|
||||
DccFrontend fe(option.filename);
|
||||
if(false==fe.FrontEnd ())
|
||||
return -1;
|
||||
FrontEnd (option.filename, &callGraph);
|
||||
|
||||
/* In the middle is a so called Universal Decompiling Machine.
|
||||
* It processes the procedure list and I-code and attaches where it can
|
||||
@ -56,14 +55,14 @@ int main(int argc, char *argv[])
|
||||
* analysis, data flow etc. and outputs it to output file ready for
|
||||
* re-compilation.
|
||||
*/
|
||||
BackEnd(option.filename, g_proj.callGraph);
|
||||
BackEnd(option.filename, callGraph);
|
||||
|
||||
g_proj.callGraph->write();
|
||||
writeCallGraph (callGraph);
|
||||
|
||||
if (option.Stats)
|
||||
displayTotalStats();
|
||||
|
||||
/*
|
||||
/*
|
||||
freeDataStructures(pProcList);
|
||||
*/
|
||||
return 0;
|
||||
@ -75,36 +74,35 @@ int main(int argc, char *argv[])
|
||||
static char *initargs(int argc, char *argv[])
|
||||
{
|
||||
char *pc;
|
||||
progname = *argv; /* Save invocation name for error messages */
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
{
|
||||
while (--argc > 0 && (*++argv)[0] == '-') {
|
||||
for (pc = argv[0]+1; *pc; pc++)
|
||||
switch (*pc)
|
||||
{
|
||||
switch (*pc) {
|
||||
case 'a': /* Print assembler listing */
|
||||
if (*(pc+1) == '2')
|
||||
option.asm2 = true;
|
||||
option.asm2 = TRUE;
|
||||
else
|
||||
option.asm1 = true;
|
||||
option.asm1 = TRUE;
|
||||
if (*(pc+1) == '1' || *(pc+1) == '2')
|
||||
pc++;
|
||||
break;
|
||||
case 'c':
|
||||
option.Calls = true;
|
||||
option.Calls = TRUE;
|
||||
break;
|
||||
case 'i':
|
||||
option.Interact = true;
|
||||
option.Interact = TRUE;
|
||||
break;
|
||||
case 'm': /* Print memory map */
|
||||
option.Map = true;
|
||||
option.Map = TRUE;
|
||||
break;
|
||||
case 's': /* Print Stats */
|
||||
option.Stats = true;
|
||||
option.Stats = TRUE;
|
||||
break;
|
||||
case 'V': /* Very verbose => verbose */
|
||||
option.VeryVerbose = true;
|
||||
case 'v':
|
||||
option.verbose = true; /* Make everything verbose */
|
||||
option.VeryVerbose = TRUE;
|
||||
case 'v': /* Make everything verbose */
|
||||
option.verbose = TRUE;
|
||||
break;
|
||||
case 'o': /* assembler output file */
|
||||
if (*(pc+1)) {
|
||||
@ -119,7 +117,7 @@ static char *initargs(int argc, char *argv[])
|
||||
fatalError(INVALID_ARG, *pc);
|
||||
return *argv;
|
||||
}
|
||||
NextArg:;
|
||||
NextArg:;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
@ -128,13 +126,13 @@ NextArg:;
|
||||
{
|
||||
if (! asm1_name)
|
||||
{
|
||||
asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
|
||||
asm1_name = strcpy((char*)allocMem(strlen(*argv)+4), *argv);
|
||||
pc = strrchr(asm1_name, '.');
|
||||
if (pc > strrchr(asm1_name, '/'))
|
||||
{
|
||||
*pc = '\0';
|
||||
}
|
||||
asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
|
||||
asm2_name = (char*)allocMem(strlen(asm1_name)+4) ;
|
||||
strcat(strcpy(asm2_name, asm1_name), ".a2");
|
||||
unlink(asm2_name);
|
||||
strcat(asm1_name, ".a1");
|
||||
@ -145,7 +143,7 @@ NextArg:;
|
||||
}
|
||||
|
||||
fatalError(USAGE);
|
||||
return *argv; // does not reach this.
|
||||
return *argv;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
1549
src/disassem.cpp
1549
src/disassem.cpp
File diff suppressed because it is too large
Load Diff
@ -3,47 +3,54 @@
|
||||
* (C) Cristina Cifuentes
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
static std::map<eErrorId,std::string> errorMessage =
|
||||
{
|
||||
{INVALID_ARG ,"Invalid option -%c\n"},
|
||||
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
|
||||
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
|
||||
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
|
||||
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
|
||||
{CANNOT_OPEN ,"Cannot open %s\n"},
|
||||
{CANNOT_READ ,"Error while reading %s\n"},
|
||||
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
|
||||
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
|
||||
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
|
||||
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
|
||||
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
|
||||
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
|
||||
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
|
||||
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
|
||||
{NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"},
|
||||
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
|
||||
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
|
||||
};
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
//#ifndef __UNIX__
|
||||
#if 1
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
static char *errorMessage[] = {
|
||||
"Invalid option -%c\n", /* INVALID_ARG */
|
||||
"Invalid instruction %02X at location %06lX\n", /* INVALID_OPCODE */
|
||||
"Don't understand 80386 instruction %02X at location %06lX\n",
|
||||
/* INVALID_386OP */
|
||||
"Segment override with no memory operand at location %06lX\n",
|
||||
/* FUNNY_SEGOVR */
|
||||
"REP prefix without a string instruction at location %06lX\n",/* FUNNY_REP */
|
||||
"Cannot open %s\n", /* CANNOT_OPEN */
|
||||
"Error while reading %s\n", /* CANNOT_READ */
|
||||
"malloc of %ld bytes failed\n", /* MALLOC_FAILED */
|
||||
"Don't understand new EXE format\n", /* NEWEXE_FORMAT */
|
||||
"Failed to find a BB for jump to %ld in proc %s\n", /* NO_BB */
|
||||
"Basic Block is a synthetic jump\n", /* INVALID_SYNTHETIC_BB */
|
||||
"Failed to find a BB for interval\n", /* INVALID_INT_BB */
|
||||
"Instruction at location %06lX goes beyond loaded image\n",
|
||||
/* IP_OUT_OF_RANGE*/
|
||||
"Definition not found for condition code usage at opcode %d\n",
|
||||
/* DEF_NOT_FOUND */
|
||||
"JX use, definition not supported at opcode #%d\n", /* JX_NOT_DEF */
|
||||
"Def - use not supported. Def op = %d, use op = %d.\n", /* NOT_DEF_USE */
|
||||
"Failed to construct repeat..until() condition.\n", /* REPEAT_FAIL */
|
||||
"Failed to construct while() condition.\n", /* WHILE_FAIL */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
fatalError: displays error message and exits the program.
|
||||
****************************************************************************/
|
||||
void fatalError(eErrorId errId, ...)
|
||||
void fatalError(Int errId, ...)
|
||||
{ va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
#if 0
|
||||
int errId;
|
||||
Int errId;
|
||||
|
||||
va_start(args);
|
||||
errId = va_arg(args, int);
|
||||
errId = va_arg(args, Int);
|
||||
#else
|
||||
va_start(args, errId);
|
||||
#endif
|
||||
@ -52,7 +59,7 @@ void fatalError(eErrorId errId, ...)
|
||||
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
|
||||
else {
|
||||
fprintf(stderr, "dcc: ");
|
||||
vfprintf(stderr, errorMessage[errId].c_str(), args);
|
||||
vfprintf(stderr, errorMessage[errId - 1], args);
|
||||
}
|
||||
va_end(args);
|
||||
exit((int)errId);
|
||||
@ -62,18 +69,18 @@ void fatalError(eErrorId errId, ...)
|
||||
/****************************************************************************
|
||||
reportError: reports the warning/error and continues with the program.
|
||||
****************************************************************************/
|
||||
void reportError(eErrorId errId, ...)
|
||||
void reportError(Int errId, ...)
|
||||
{ va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
#if 0
|
||||
int errId;
|
||||
Int errId;
|
||||
|
||||
va_start(args);
|
||||
errId = va_arg(args, int);
|
||||
errId = va_arg(args, Int);
|
||||
#else /* msdos or windows*/
|
||||
va_start(args, errId);
|
||||
#endif
|
||||
fprintf(stderr, "dcc: ");
|
||||
vfprintf(stderr, errorMessage[errId].c_str(), args);
|
||||
vfprintf(stderr, errorMessage[errId - 1], args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
138
src/fixwild.cpp
138
src/fixwild.cpp
@ -18,26 +18,29 @@
|
||||
|
||||
#ifndef bool
|
||||
#define bool unsigned char
|
||||
#define uint8_t unsigned char
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define byte unsigned char
|
||||
#endif
|
||||
|
||||
static int pc; /* Indexes into pat[] */
|
||||
|
||||
/* prototypes */
|
||||
static bool ModRM(uint8_t pat[]); /* Handle the mod/rm uint8_t */
|
||||
static bool TwoWild(uint8_t pat[]); /* Make the next 2 bytes wild */
|
||||
static bool FourWild(uint8_t pat[]); /* Make the next 4 bytes wild */
|
||||
void fixWildCards(uint8_t pat[]); /* Main routine */
|
||||
static bool ModRM(byte pat[]); /* Handle the mod/rm byte */
|
||||
static bool TwoWild(byte pat[]); /* Make the next 2 bytes wild */
|
||||
static bool FourWild(byte pat[]); /* Make the next 4 bytes wild */
|
||||
void fixWildCards(byte pat[]); /* Main routine */
|
||||
|
||||
|
||||
/* Handle the mod/rm case. Returns true if pattern exhausted */
|
||||
static bool ModRM(uint8_t pat[])
|
||||
static bool
|
||||
ModRM(byte pat[])
|
||||
{
|
||||
uint8_t op;
|
||||
byte op;
|
||||
|
||||
/* A standard mod/rm uint8_t follows opcode */
|
||||
op = pat[pc++]; /* The mod/rm uint8_t */
|
||||
if (pc >= PATLEN) return true; /* Skip Mod/RM */
|
||||
/* A standard mod/rm byte follows opcode */
|
||||
op = pat[pc++]; /* The mod/rm byte */
|
||||
if (pc >= PATLEN) return TRUE; /* Skip Mod/RM */
|
||||
switch (op & 0xC0)
|
||||
{
|
||||
case 0x00: /* [reg] or [nnnn] */
|
||||
@ -45,42 +48,42 @@ static bool ModRM(uint8_t pat[])
|
||||
{
|
||||
/* Uses [nnnn] address mode */
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return true;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return true;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
}
|
||||
break;
|
||||
case 0x40: /* [reg + nn] */
|
||||
if ((pc+=1) >= PATLEN) return true;
|
||||
if ((pc+=1) >= PATLEN) return TRUE;
|
||||
break;
|
||||
case 0x80: /* [reg + nnnn] */
|
||||
/* Possibly just a long constant offset from a register,
|
||||
but often will be an index from a variable */
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return true;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return true;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
break;
|
||||
case 0xC0: /* reg */
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Change the next two bytes to wild cards */
|
||||
static bool
|
||||
TwoWild(uint8_t pat[])
|
||||
TwoWild(byte pat[])
|
||||
{
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return true; /* Pattern exhausted */
|
||||
if (pc >= PATLEN) return TRUE; /* Pattern exhausted */
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return true;
|
||||
return false;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Change the next four bytes to wild cards */
|
||||
static bool
|
||||
FourWild(uint8_t pat[])
|
||||
FourWild(byte pat[])
|
||||
{
|
||||
TwoWild(pat);
|
||||
return TwoWild(pat);
|
||||
@ -89,21 +92,22 @@ FourWild(uint8_t pat[])
|
||||
/* Chop from the current point by wiping with zeroes. Can't rely on anything
|
||||
after this point */
|
||||
static void
|
||||
chop(uint8_t pat[])
|
||||
chop(byte pat[])
|
||||
{
|
||||
if (pc >= PATLEN) return; /* Could go negative otherwise */
|
||||
memset(&pat[pc], 0, PATLEN - pc);
|
||||
}
|
||||
|
||||
static bool op0F(uint8_t pat[])
|
||||
static bool
|
||||
op0F(byte pat[])
|
||||
{
|
||||
/* The two uint8_t opcodes */
|
||||
uint8_t op = pat[pc++];
|
||||
/* The two byte opcodes */
|
||||
byte op = pat[pc++];
|
||||
switch (op & 0xF0)
|
||||
{
|
||||
case 0x00: /* 00 - 0F */
|
||||
if (op >= 0x06) /* Clts, Invd, Wbinvd */
|
||||
return false;
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
/* Grp 6, Grp 7, LAR, LSL */
|
||||
@ -113,10 +117,10 @@ static bool op0F(uint8_t pat[])
|
||||
return ModRM(pat);
|
||||
|
||||
case 0x80:
|
||||
pc += 2; /* uint16_t displacement cond jumps */
|
||||
return false;
|
||||
pc += 2; /* Word displacement cond jumps */
|
||||
return FALSE;
|
||||
|
||||
case 0x90: /* uint8_t set on condition */
|
||||
case 0x90: /* Byte set on condition */
|
||||
return ModRM(pat);
|
||||
|
||||
case 0xA0:
|
||||
@ -126,7 +130,7 @@ static bool op0F(uint8_t pat[])
|
||||
case 0xA1: /* Pop FS */
|
||||
case 0xA8: /* Push GS */
|
||||
case 0xA9: /* Pop GS */
|
||||
return false;
|
||||
return FALSE;
|
||||
|
||||
case 0xA3: /* Bt Ev,Gv */
|
||||
case 0xAB: /* Bts Ev,Gv */
|
||||
@ -134,9 +138,9 @@ static bool op0F(uint8_t pat[])
|
||||
|
||||
case 0xA4: /* Shld EvGbIb */
|
||||
case 0xAC: /* Shrd EvGbIb */
|
||||
if (ModRM(pat)) return true;
|
||||
if (ModRM(pat)) return TRUE;
|
||||
pc++; /* The #num bits to shift */
|
||||
return false;
|
||||
return FALSE;
|
||||
|
||||
case 0xA5: /* Shld EvGb CL */
|
||||
case 0xAD: /* Shrd EvGb CL */
|
||||
@ -150,9 +154,9 @@ static bool op0F(uint8_t pat[])
|
||||
if (op == 0xBA)
|
||||
{
|
||||
/* Grp 8: bt/bts/btr/btc Ev,#nn */
|
||||
if (ModRM(pat)) return true;
|
||||
if (ModRM(pat)) return TRUE;
|
||||
pc++; /* The #num bits to shift */
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
return ModRM(pat);
|
||||
|
||||
@ -163,10 +167,10 @@ static bool op0F(uint8_t pat[])
|
||||
return ModRM(pat);
|
||||
}
|
||||
/* Else BSWAP */
|
||||
return false;
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return false; /* Treat as double uint8_t opcodes */
|
||||
return FALSE; /* Treat as double byte opcodes */
|
||||
|
||||
}
|
||||
|
||||
@ -181,10 +185,10 @@ static bool op0F(uint8_t pat[])
|
||||
PATLEN bytes are scanned.
|
||||
*/
|
||||
void
|
||||
fixWildCards(uint8_t pat[])
|
||||
fixWildCards(byte pat[])
|
||||
{
|
||||
|
||||
uint8_t op, quad, intArg;
|
||||
byte op, quad, intArg;
|
||||
|
||||
|
||||
pc=0;
|
||||
@ -193,17 +197,17 @@ fixWildCards(uint8_t pat[])
|
||||
op = pat[pc++];
|
||||
if (pc >= PATLEN) return;
|
||||
|
||||
quad = (uint8_t) (op & 0xC0); /* Quadrant of the opcode map */
|
||||
quad = (byte) (op & 0xC0); /* Quadrant of the opcode map */
|
||||
if (quad == 0)
|
||||
{
|
||||
/* Arithmetic group 00-3F */
|
||||
|
||||
if ((op & 0xE7) == 0x26) /* First check for the odds */
|
||||
{
|
||||
/* Segment prefix: treat as 1 uint8_t opcode */
|
||||
/* Segment prefix: treat as 1 byte opcode */
|
||||
continue;
|
||||
}
|
||||
if (op == 0x0F) /* 386 2 uint8_t opcodes */
|
||||
if (op == 0x0F) /* 386 2 byte opcodes */
|
||||
{
|
||||
if (op0F(pat)) return;
|
||||
continue;
|
||||
@ -214,20 +218,20 @@ fixWildCards(uint8_t pat[])
|
||||
/* All these are constant. Work out the instr length */
|
||||
if (op & 2)
|
||||
{
|
||||
/* Push, pop, other 1 uint8_t opcodes */
|
||||
/* Push, pop, other 1 byte opcodes */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op & 1)
|
||||
{
|
||||
/* uint16_t immediate operands */
|
||||
/* Word immediate operands */
|
||||
pc += 2;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uint8_t immediate operands */
|
||||
/* Byte immediate operands */
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
@ -253,7 +257,7 @@ fixWildCards(uint8_t pat[])
|
||||
/* 0x60 - 0x70 */
|
||||
if (op & 0x10)
|
||||
{
|
||||
/* 70-7F 2 uint8_t jump opcodes */
|
||||
/* 70-7F 2 byte jump opcodes */
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
@ -280,11 +284,11 @@ fixWildCards(uint8_t pat[])
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0x68: /* Push uint8_t */
|
||||
case 0x6A: /* Push uint8_t */
|
||||
case 0x68: /* Push byte */
|
||||
case 0x6A: /* Push byte */
|
||||
case 0x6D: /* insb port */
|
||||
case 0x6F: /* outsb port */
|
||||
/* 2 uint8_t instr, no wilds */
|
||||
/* 2 byte instr, no wilds */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
@ -298,14 +302,14 @@ fixWildCards(uint8_t pat[])
|
||||
switch (op & 0xF0)
|
||||
{
|
||||
case 0x80: /* 80 - 8F */
|
||||
/* All have a mod/rm uint8_t */
|
||||
/* All have a mod/rm byte */
|
||||
if (ModRM(pat)) return;
|
||||
/* These also have immediate values */
|
||||
switch (op)
|
||||
{
|
||||
case 0x80:
|
||||
case 0x83:
|
||||
/* One uint8_t immediate */
|
||||
/* One byte immediate */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
@ -324,7 +328,7 @@ fixWildCards(uint8_t pat[])
|
||||
if (FourWild(pat)) return;
|
||||
continue;
|
||||
}
|
||||
/* All others are 1 uint8_t opcodes */
|
||||
/* All others are 1 byte opcodes */
|
||||
continue;
|
||||
case 0xA0: /* A0 - AF */
|
||||
if ((op & 0x0C) == 0)
|
||||
@ -335,7 +339,7 @@ fixWildCards(uint8_t pat[])
|
||||
}
|
||||
else if ((op & 0xFE) == 0xA8)
|
||||
{
|
||||
/* test al,#uint8_t or test ax,#uint16_t */
|
||||
/* test al,#byte or test ax,#word */
|
||||
if (op & 1) pc += 2;
|
||||
else pc += 1;
|
||||
continue;
|
||||
@ -364,10 +368,10 @@ fixWildCards(uint8_t pat[])
|
||||
/* In the last quadrant of the op code table */
|
||||
switch (op)
|
||||
{
|
||||
case 0xC0: /* 386: Rotate group 2 ModRM, uint8_t, #uint8_t */
|
||||
case 0xC1: /* 386: Rotate group 2 ModRM, uint16_t, #uint8_t */
|
||||
case 0xC0: /* 386: Rotate group 2 ModRM, byte, #byte */
|
||||
case 0xC1: /* 386: Rotate group 2 ModRM, word, #byte */
|
||||
if (ModRM(pat)) return;
|
||||
/* uint8_t immediate value follows ModRM */
|
||||
/* Byte immediate value follows ModRM */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
@ -388,27 +392,27 @@ fixWildCards(uint8_t pat[])
|
||||
|
||||
case 0xC6: /* Mov ModRM, #nn */
|
||||
if (ModRM(pat)) return;
|
||||
/* uint8_t immediate value follows ModRM */
|
||||
/* Byte immediate value follows ModRM */
|
||||
pc++;
|
||||
continue;
|
||||
case 0xC7: /* Mov ModRM, #nnnn */
|
||||
if (ModRM(pat)) return;
|
||||
/* uint16_t immediate value follows ModRM */
|
||||
/* Word immediate value follows ModRM */
|
||||
/* Immediate 16 bit values might be constant, but also
|
||||
might be relocatable. For now, make them wild */
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0xC8: /* Enter Iw, Ib */
|
||||
pc += 3; /* Constant uint16_t, uint8_t */
|
||||
pc += 3; /* Constant word, byte */
|
||||
continue;
|
||||
case 0xC9: /* Leave */
|
||||
continue;
|
||||
|
||||
case 0xCC: /* int 3 */
|
||||
case 0xCC: /* Int 3 */
|
||||
continue;
|
||||
|
||||
case 0xCD: /* int nn */
|
||||
case 0xCD: /* Int nn */
|
||||
intArg = pat[pc++];
|
||||
if ((intArg >= 0x34) && (intArg <= 0x3B))
|
||||
{
|
||||
@ -423,10 +427,10 @@ fixWildCards(uint8_t pat[])
|
||||
case 0xCF: /* Iret */
|
||||
continue;
|
||||
|
||||
case 0xD0: /* Group 2 rotate, uint8_t, 1 bit */
|
||||
case 0xD1: /* Group 2 rotate, uint16_t, 1 bit */
|
||||
case 0xD2: /* Group 2 rotate, uint8_t, CL bits */
|
||||
case 0xD3: /* Group 2 rotate, uint16_t, CL bits */
|
||||
case 0xD0: /* Group 2 rotate, byte, 1 bit */
|
||||
case 0xD1: /* Group 2 rotate, word, 1 bit */
|
||||
case 0xD2: /* Group 2 rotate, byte, CL bits */
|
||||
case 0xD3: /* Group 2 rotate, word, CL bits */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
@ -498,8 +502,8 @@ fixWildCards(uint8_t pat[])
|
||||
case 0xFD: /* Std */
|
||||
continue;
|
||||
|
||||
case 0xF6: /* Group 3 uint8_t test/not/mul/div */
|
||||
case 0xF7: /* Group 3 uint16_t test/not/mul/div */
|
||||
case 0xF6: /* Group 3 byte test/not/mul/div */
|
||||
case 0xF7: /* Group 3 word test/not/mul/div */
|
||||
case 0xFE: /* Inc/Dec group 4 */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
@ -509,7 +513,7 @@ fixWildCards(uint8_t pat[])
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
default: /* Rest are single uint8_t opcodes */
|
||||
default: /* Rest are single byte opcodes */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
393
src/frontend.cpp
393
src/frontend.cpp
@ -1,51 +1,54 @@
|
||||
/*****************************************************************************
|
||||
* dcc project Front End module
|
||||
* Loads a program into simulated main memory and builds the procedure list.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
* dcc project Front End module
|
||||
* Loads a program into simulated main memory and builds the procedure list.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h> /* For malloc, free, realloc */
|
||||
#include "project.h"
|
||||
#endif
|
||||
|
||||
typedef struct { /* PSP structure */
|
||||
uint16_t int20h; /* interrupt 20h */
|
||||
uint16_t eof; /* segment, end of allocation block */
|
||||
uint8_t res1; /* reserved */
|
||||
uint8_t dosDisp[5]; /* far call to DOS function dispatcher */
|
||||
uint8_t int22h[4]; /* vector for terminate routine */
|
||||
uint8_t int23h[4]; /* vector for ctrl+break routine */
|
||||
uint8_t int24h[4]; /* vector for error routine */
|
||||
uint8_t res2[22]; /* reserved */
|
||||
uint16_t segEnv; /* segment address of environment block */
|
||||
uint8_t res3[34]; /* reserved */
|
||||
uint8_t int21h[6]; /* opcode for int21h and far return */
|
||||
uint8_t res4[6]; /* reserved */
|
||||
uint8_t fcb1[16]; /* default file control block 1 */
|
||||
uint8_t fcb2[16]; /* default file control block 2 */
|
||||
uint8_t res5[4]; /* reserved */
|
||||
uint8_t cmdTail[0x80]; /* command tail and disk transfer area */
|
||||
word int20h; /* interrupt 20h */
|
||||
word eof; /* segment, end of allocation block */
|
||||
byte res1; /* reserved */
|
||||
byte dosDisp[5]; /* far call to DOS function dispatcher */
|
||||
byte int22h[4]; /* vector for terminate routine */
|
||||
byte int23h[4]; /* vector for ctrl+break routine */
|
||||
byte int24h[4]; /* vector for error routine */
|
||||
byte res2[22]; /* reserved */
|
||||
word segEnv; /* segment address of environment block */
|
||||
byte res3[34]; /* reserved */
|
||||
byte int21h[6]; /* opcode for int21h and far return */
|
||||
byte res4[6]; /* reserved */
|
||||
byte fcb1[16]; /* default file control block 1 */
|
||||
byte fcb2[16]; /* default file control block 2 */
|
||||
byte res5[4]; /* reserved */
|
||||
byte cmdTail[0x80]; /* command tail and disk transfer area */
|
||||
} PSP;
|
||||
|
||||
static struct { /* EXE file header */
|
||||
uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */
|
||||
uint8_t sigHi;
|
||||
uint16_t lastPageSize; /* Size of the last page */
|
||||
uint16_t numPages; /* Number of pages in the file */
|
||||
uint16_t numReloc; /* Number of relocation items */
|
||||
uint16_t numParaHeader; /* # of paragraphs in the header */
|
||||
uint16_t minAlloc; /* Minimum number of paragraphs */
|
||||
uint16_t maxAlloc; /* Maximum number of paragraphs */
|
||||
uint16_t initSS; /* Segment displacement of stack */
|
||||
uint16_t initSP; /* Contents of SP at entry */
|
||||
uint16_t checkSum; /* Complemented checksum */
|
||||
uint16_t initIP; /* Contents of IP at entry */
|
||||
uint16_t initCS; /* Segment displacement of code */
|
||||
uint16_t relocTabOffset; /* Relocation table offset */
|
||||
uint16_t overlayNum; /* Overlay number */
|
||||
byte sigLo; /* .EXE signature: 0x4D 0x5A */
|
||||
byte sigHi;
|
||||
word lastPageSize; /* Size of the last page */
|
||||
word numPages; /* Number of pages in the file */
|
||||
word numReloc; /* Number of relocation items */
|
||||
word numParaHeader; /* # of paragraphs in the header */
|
||||
word minAlloc; /* Minimum number of paragraphs */
|
||||
word maxAlloc; /* Maximum number of paragraphs */
|
||||
word initSS; /* Segment displacement of stack */
|
||||
word initSP; /* Contents of SP at entry */
|
||||
word checkSum; /* Complemented checksum */
|
||||
word initIP; /* Contents of IP at entry */
|
||||
word initCS; /* Segment displacement of code */
|
||||
word relocTabOffset; /* Relocation table offset */
|
||||
word overlayNum; /* Overlay number */
|
||||
} header;
|
||||
|
||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||
@ -55,25 +58,26 @@ static void displayLoadInfo(void);
|
||||
static void displayMemMap(void);
|
||||
|
||||
/*****************************************************************************
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
extern Project g_proj;
|
||||
bool DccFrontend::FrontEnd ()
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
void FrontEnd (char *filename, PCALL_GRAPH *pcallGraph)
|
||||
{
|
||||
|
||||
g_proj.callGraph = 0;
|
||||
g_proj.m_fname = m_fname;
|
||||
PPROC pProc;
|
||||
PSYM psym;
|
||||
Int i, c;
|
||||
|
||||
/* Load program into memory */
|
||||
LoadImage(g_proj);
|
||||
LoadImage(filename);
|
||||
|
||||
if (option.verbose)
|
||||
{
|
||||
displayLoadInfo();
|
||||
}
|
||||
|
||||
/* Do depth first flow analysis building call graph and procedure list,
|
||||
* and attaching the I-code to each procedure */
|
||||
parse (g_proj);
|
||||
parse (pcallGraph);
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
@ -81,39 +85,50 @@ bool DccFrontend::FrontEnd ()
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
Disassembler ds(1);
|
||||
for(Function &f : g_proj.pProcList)
|
||||
for (pProc = pProcList; pProc; pProc = pProc->next)
|
||||
{
|
||||
f.markImpure();
|
||||
for (i = 0; i < pProc->Icode.GetNumIcodes(); i++)
|
||||
{
|
||||
if (pProc->Icode.GetLlFlag(i) & (SYM_USE | SYM_DEF))
|
||||
{
|
||||
psym = &symtab.sym[pProc->Icode.GetIcode(i)->ic.ll.caseTbl.numEntries];
|
||||
for (c = (Int)psym->label; c < (Int)psym->label+psym->size; c++)
|
||||
{
|
||||
if (BITMAP(c, BM_CODE))
|
||||
{
|
||||
pProc->Icode.SetLlFlag(i, IMPURE);
|
||||
pProc->flg |= IMPURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Print assembler listing */
|
||||
if (option.asm1)
|
||||
{
|
||||
ds.disassem(&f);
|
||||
}
|
||||
disassem(1, pProc);
|
||||
}
|
||||
|
||||
if (option.Interact)
|
||||
{
|
||||
interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */
|
||||
interactDis(pProcList, 0); /* Interactive disassembler */
|
||||
}
|
||||
|
||||
/* Converts jump target addresses to icode offsets */
|
||||
for(Function &f : g_proj.pProcList)
|
||||
{
|
||||
f.bindIcodeOff();
|
||||
}
|
||||
for (pProc = pProcList; pProc; pProc = pProc->next)
|
||||
bindIcodeOff (pProc);
|
||||
|
||||
/* Print memory bitmap */
|
||||
if (option.Map)
|
||||
displayMemMap();
|
||||
return(true); // we no longer own proj !
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* displayLoadInfo - Displays low level loader type info.
|
||||
***************************************************************************/
|
||||
* displayLoadInfo - Displays low level loader type info.
|
||||
***************************************************************************/
|
||||
static void displayLoadInfo(void)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
int i;
|
||||
Int i;
|
||||
|
||||
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
if (! prog.fCOM) {
|
||||
@ -134,7 +149,8 @@ static void displayLoadInfo(void)
|
||||
printf("\nRelocation Table\n");
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.Image + prog.relocTable[i]));
|
||||
printf("%06X -> [%04X]\n", prog.relocTable[i],
|
||||
LH(prog.Image + prog.relocTable[i]));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
@ -142,33 +158,31 @@ static void displayLoadInfo(void)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* fill - Fills line for displayMemMap()
|
||||
****************************************************************************/
|
||||
static void fill(int ip, char *bf)
|
||||
* fill - Fills line for displayMemMap()
|
||||
****************************************************************************/
|
||||
static void fill(Int ip, char *bf)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
static uint8_t type[4] = {'.', 'd', 'c', 'x'};
|
||||
uint8_t i;
|
||||
static byte type[4] = {'.', 'd', 'c', 'x'};
|
||||
byte i;
|
||||
|
||||
for (i = 0; i < 16; i++, ip++)
|
||||
{
|
||||
*bf++ = ' ';
|
||||
*bf++ = (ip < prog.cbImage)? type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
|
||||
*bf++ = (ip < prog.cbImage)?
|
||||
type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
|
||||
}
|
||||
*bf = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* displayMemMap - Displays the memory bitmap
|
||||
****************************************************************************/
|
||||
* displayMemMap - Displays the memory bitmap
|
||||
****************************************************************************/
|
||||
static void displayMemMap(void)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
|
||||
char c, b1[33], b2[33], b3[33];
|
||||
uint8_t i;
|
||||
int ip = 0;
|
||||
byte i;
|
||||
Int ip = 0;
|
||||
|
||||
printf("\nMemory Map\n");
|
||||
while (ip < prog.cbImage)
|
||||
@ -198,25 +212,24 @@ static void displayMemMap(void)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* LoadImage
|
||||
****************************************************************************/
|
||||
void DccFrontend::LoadImage(Project &proj)
|
||||
* LoadImage
|
||||
****************************************************************************/
|
||||
static void LoadImage(char *filename)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
FILE *fp;
|
||||
int i, cb;
|
||||
uint8_t buf[4];
|
||||
Int i, cb;
|
||||
byte buf[4];
|
||||
|
||||
/* Open the input file */
|
||||
if ((fp = fopen(proj.m_fname.c_str(), "rb")) == NULL)
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
fatalError(CANNOT_OPEN, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_OPEN, filename);
|
||||
}
|
||||
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (fread(&header, 1, 2, fp) != 2)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
|
||||
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
|
||||
@ -224,7 +237,7 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
if (fread(&header, sizeof(header), 1, fp) != 1)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
|
||||
/* This is a typical DOS kludge! */
|
||||
@ -238,30 +251,30 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
* less the length of the header and reloc table
|
||||
* less the number of bytes unused on last page
|
||||
*/
|
||||
cb = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16;
|
||||
cb = (dword)LH(&header.numPages) * 512 - (dword)LH(&header.numParaHeader) * 16;
|
||||
if (header.lastPageSize)
|
||||
{
|
||||
cb -= 512 - LH(&header.lastPageSize);
|
||||
}
|
||||
|
||||
/* We quietly ignore minAlloc and maxAlloc since for our
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
|
||||
prog.initIP = (int16_t)LH(&header.initIP);
|
||||
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
|
||||
prog.initSP = (int16_t)LH(&header.initSP);
|
||||
prog.cReloc = (int16_t)LH(&header.numReloc);
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
prog.initCS = (int16)LH(&header.initCS) + EXE_RELOCATION;
|
||||
prog.initIP = (int16)LH(&header.initIP);
|
||||
prog.initSS = (int16)LH(&header.initSS) + EXE_RELOCATION;
|
||||
prog.initSP = (int16)LH(&header.initSP);
|
||||
prog.cReloc = (int16)LH(&header.numReloc);
|
||||
|
||||
/* Allocate the relocation table */
|
||||
if (prog.cReloc)
|
||||
{
|
||||
prog.relocTable = new uint32_t [prog.cReloc];
|
||||
prog.relocTable = (dword*)allocMem(prog.cReloc * sizeof(Int));
|
||||
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
|
||||
|
||||
/* Read in seg:offset pairs and convert to Image ptrs */
|
||||
@ -269,12 +282,11 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
{
|
||||
fread(buf, 1, 4, fp);
|
||||
prog.relocTable[i] = LH(buf) +
|
||||
(((int)LH(buf+2) + EXE_RELOCATION)<<4);
|
||||
(((Int)LH(buf+2) + EXE_RELOCATION)<<4);
|
||||
}
|
||||
}
|
||||
/* Seek to start of image */
|
||||
uint32_t start_of_image= LH(&header.numParaHeader) * 16;
|
||||
fseek(fp, start_of_image, SEEK_SET);
|
||||
fseek(fp, (Int)LH(&header.numParaHeader) * 16, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{ /* COM file
|
||||
@ -298,30 +310,36 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = cb + sizeof(PSP);
|
||||
prog.Image = new uint8_t [prog.cbImage];
|
||||
prog.Image[0] = 0xCD; /* Fill in PSP int 20h location */
|
||||
prog.Image = (byte*)allocMem(prog.cbImage);
|
||||
prog.Image[0] = 0xCD; /* Fill in PSP Int 20h location */
|
||||
prog.Image[1] = 0x20; /* for termination checking */
|
||||
|
||||
/* Read in the image past where a PSP would go */
|
||||
if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
|
||||
#ifdef __DOSWIN__
|
||||
if (cb > 0xFFFF)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
printf("Image size of %ld bytes too large for fread!\n", cb);
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
#endif
|
||||
if (cb != (Int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
|
||||
{
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb);
|
||||
|
||||
/* Relocate segment constants */
|
||||
if (prog.cReloc)
|
||||
{
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
uint8_t *p = &prog.Image[prog.relocTable[i]];
|
||||
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
|
||||
*p++ = (uint8_t)(w & 0x00FF);
|
||||
*p = (uint8_t)((w & 0xFF00) >> 8);
|
||||
byte *p = &prog.Image[prog.relocTable[i]];
|
||||
word w = (word)LH(p) + EXE_RELOCATION;
|
||||
*p++ = (byte)(w & 0x00FF);
|
||||
*p = (byte)((w & 0xFF00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,19 +348,150 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* allocMem - malloc with failure test
|
||||
****************************************************************************/
|
||||
void *allocMem(int cb)
|
||||
* allocMem - malloc with failure test
|
||||
****************************************************************************/
|
||||
void *allocMem(Int cb)
|
||||
{
|
||||
uint8_t *p;
|
||||
byte *p;
|
||||
|
||||
//printf("Attempt to allocMem %5ld bytes\n", cb);
|
||||
//printf("Attempt to allocMem %5ld bytes\n", cb);
|
||||
|
||||
if (! (p = (uint8_t*)malloc((size_t)cb)))
|
||||
/* if (! (p = (uint8_t*)calloc((size_t)cb, 1))) */
|
||||
#if 0 /* Microsoft specific heap debugging code */
|
||||
switch (_heapset('Z'))
|
||||
{
|
||||
case _HEAPBADBEGIN: printf("aM: Bad heap begin\n"); break;
|
||||
case _HEAPBADNODE: printf("aM: Bad heap node\n");
|
||||
printf("Attempt to allocMem %5d bytes\n", cb);
|
||||
{
|
||||
_HEAPINFO hinfo;
|
||||
int heapstatus;
|
||||
boolT cont = TRUE;
|
||||
|
||||
hinfo._pentry = NULL;
|
||||
|
||||
while (cont)
|
||||
{
|
||||
switch (heapstatus = _heapwalk(&hinfo))
|
||||
{
|
||||
case _HEAPOK:
|
||||
printf("%6s block at %Fp of size %4.4X\n",
|
||||
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
|
||||
hinfo._pentry, hinfo._size);
|
||||
break;
|
||||
case _HEAPBADBEGIN:
|
||||
printf("Heap bad begin\n");
|
||||
break;
|
||||
case _HEAPBADNODE:
|
||||
printf("BAD NODE %6s block at %Fp of size %4.4X\n",
|
||||
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
|
||||
hinfo._pentry, hinfo._size);
|
||||
break;
|
||||
case _HEAPEND:
|
||||
cont = FALSE;
|
||||
break;
|
||||
case _HEAPBADPTR:
|
||||
printf("INFO BAD %6s block at %Fp of size %4.4X\n",
|
||||
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
|
||||
hinfo._pentry, hinfo._size);
|
||||
cont=FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
getchar();
|
||||
exit(1);
|
||||
|
||||
case _HEAPEMPTY: printf("aM: Heap empty\n"); getchar(); break;
|
||||
case _HEAPOK:putchar('.');break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! (p = (byte*)malloc((size_t)cb)))
|
||||
/* if (! (p = (byte*)calloc((size_t)cb, 1))) */
|
||||
{
|
||||
fatalError(MALLOC_FAILED, cb);
|
||||
}
|
||||
// printf("allocMem: %p\n", p);
|
||||
/*printf("allocMem: %p\n", p);/**/
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* reallocVar - reallocs extra variable space
|
||||
****************************************************************************/
|
||||
void *reallocVar(void *p, Int newsize)
|
||||
{
|
||||
/*printf("Attempt to reallocVar %5d bytes\n", newsize);/**/
|
||||
#if 0
|
||||
switch (_heapset('Z'))
|
||||
{
|
||||
case _HEAPBADBEGIN: printf("aV: Bad heap begin\n"); /*getchar()*/; break;
|
||||
case _HEAPBADNODE: printf("aV: Bad heap node\n");
|
||||
printf("Attempt to reallocVar %5d bytes at %p\n", newsize, p);/**/
|
||||
{
|
||||
_HEAPINFO hinfo;
|
||||
int heapstatus;
|
||||
boolT cont = TRUE;
|
||||
|
||||
hinfo._pentry = NULL;
|
||||
|
||||
while (cont)
|
||||
{
|
||||
switch (heapstatus = _heapwalk(&hinfo))
|
||||
{
|
||||
case _HEAPOK:
|
||||
printf("%6s block at %Fp of size %4.4X\n",
|
||||
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
|
||||
hinfo._pentry, hinfo._size);
|
||||
break;
|
||||
case _HEAPBADBEGIN:
|
||||
printf("Heap bad begin\n");
|
||||
break;
|
||||
case _HEAPBADNODE:
|
||||
printf("BAD NODE %6s block at %Fp of size %4.4X\n",
|
||||
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
|
||||
hinfo._pentry, hinfo._size);
|
||||
break;
|
||||
case _HEAPEND:
|
||||
cont = FALSE;
|
||||
break;
|
||||
case _HEAPBADPTR:
|
||||
printf("INFO BAD %6s block at %Fp of size %4.4X\n",
|
||||
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
|
||||
hinfo._pentry, hinfo._size);
|
||||
cont=FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
getchar();
|
||||
break;
|
||||
|
||||
case _HEAPEMPTY: printf("aV: Heap empty\n"); getchar(); break;
|
||||
case _HEAPOK:putchar('!');break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! (p = realloc((byte *)p, (size_t)newsize)))
|
||||
{
|
||||
fatalError(MALLOC_FAILED, newsize);
|
||||
}
|
||||
|
||||
/*printf("reallocVar: %p\n", p);/**/
|
||||
return p;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void free(void *p)
|
||||
{
|
||||
_ffree(p);
|
||||
switch (_heapset('Z'))
|
||||
{
|
||||
case _HEAPBADBEGIN: printf("f: Bad heap begin\n"); getchar(); break;
|
||||
case _HEAPBADNODE: printf("f: Bad heap node\n"); getchar(); break;
|
||||
case _HEAPEMPTY: printf("f: Heap empty\n"); getchar(); break;
|
||||
case _HEAPOK:putchar('!');break;
|
||||
}/**/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
414
src/graph.cpp
414
src/graph.cpp
@ -5,18 +5,20 @@
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#if __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h> /* For free() */
|
||||
#include "graph.h"
|
||||
#include "project.h"
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
#endif
|
||||
|
||||
static PBB rmJMP(PPROC pProc, Int marker, PBB pBB);
|
||||
static void mergeFallThrough(PPROC pProc, PBB pBB);
|
||||
static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last);
|
||||
|
||||
/*****************************************************************************
|
||||
* createCFG - Create the basic control flow graph
|
||||
****************************************************************************/
|
||||
void Function::createCFG()
|
||||
PBB createCFG(PPROC pProc)
|
||||
{
|
||||
/* Splits Icode associated with the procedure into Basic Blocks.
|
||||
* The links between BBs represent the control flow graph of the
|
||||
@ -29,185 +31,181 @@ void Function::createCFG()
|
||||
* 5) Repeated string instructions
|
||||
* 6) End of procedure
|
||||
*/
|
||||
int i;
|
||||
int ip;
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
iICODE pIcode = Icode.begin();
|
||||
iICODE iStart = Icode.begin();
|
||||
Int i;
|
||||
Int ip, start;
|
||||
BB cfg;
|
||||
PBB psBB;
|
||||
PBB pBB = &cfg;
|
||||
PICODE pIcode = pProc->Icode.GetFirstIcode();
|
||||
|
||||
cfg.next = NULL;
|
||||
stats.numBBbef = stats.numBBaft = 0;
|
||||
for (; pIcode!=Icode.end(); ++pIcode)
|
||||
for (ip = start = 0; pProc->Icode.IsValid(pIcode); ip++, pIcode++)
|
||||
{
|
||||
iICODE nextIcode = ++iICODE(pIcode);
|
||||
LLInst *ll = pIcode->ll();
|
||||
/* Stick a NOWHERE_NODE on the end if we terminate
|
||||
* with anything other than a ret, jump or terminate */
|
||||
if (nextIcode == Icode.end() and
|
||||
(not ll->testFlags(TERMINATES)) and
|
||||
(not ll->match(iJMP)) and (not ll->match(iJMPF)) and
|
||||
(not ll->match(iRET)) and (not ll->match(iRETF)))
|
||||
{
|
||||
//pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this);
|
||||
pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
|
||||
}
|
||||
if (ip + 1 == pProc->Icode.GetNumIcodes() &&
|
||||
! (pIcode->ic.ll.flg & TERMINATES) &&
|
||||
pIcode->ic.ll.opcode != iJMP && pIcode->ic.ll.opcode != iJMPF &&
|
||||
pIcode->ic.ll.opcode != iRET && pIcode->ic.ll.opcode != iRETF)
|
||||
newBB(pBB, start, ip, NOWHERE_NODE, 0, pProc);
|
||||
|
||||
/* Only process icodes that have valid instructions */
|
||||
else if (not ll->testFlags(NO_CODE) )
|
||||
else if ((pIcode->ic.ll.flg & NO_CODE) != NO_CODE)
|
||||
{
|
||||
switch (ll->getOpcode()) {
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
|
||||
CondJumps:
|
||||
//start = ip + 1;
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
|
||||
pBB = newBB(pBB, start, ip, TWO_BRANCH, 2, pProc);
|
||||
CondJumps:
|
||||
start = ip + 1;
|
||||
pBB->edges[0].ip = (dword)start;
|
||||
/* This is for jumps off into nowhere */
|
||||
if ( ll->testFlags(NO_LABEL) )
|
||||
{
|
||||
pBB->edges.pop_back();
|
||||
}
|
||||
if (pIcode->ic.ll.flg & NO_LABEL)
|
||||
pBB->numOutEdges--;
|
||||
else
|
||||
pBB->edges[1].ip = ll->src().getImm2();
|
||||
pBB->edges[1].ip = pIcode->ic.ll.immed.op;
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
|
||||
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
|
||||
pBB = newBB(pBB, start, ip, LOOP_NODE, 2, pProc);
|
||||
goto CondJumps;
|
||||
|
||||
case iJMPF: case iJMP:
|
||||
if (ll->testFlags(SWITCH))
|
||||
if (pIcode->ic.ll.flg & SWITCH)
|
||||
{
|
||||
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
|
||||
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
|
||||
for (i = 0; i < ll->caseTbl2.size(); i++)
|
||||
pBB->edges[i].ip = ll->caseTbl2[i];
|
||||
hasCase = true;
|
||||
pBB = newBB(pBB, start, ip, MULTI_BRANCH,
|
||||
pIcode->ic.ll.caseTbl.numEntries, pProc);
|
||||
for (i = 0; i < pIcode->ic.ll.caseTbl.numEntries; i++)
|
||||
pBB->edges[i].ip = pIcode->ic.ll.caseTbl.entries[i];
|
||||
pProc->hasCase = TRUE;
|
||||
}
|
||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
||||
{
|
||||
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
|
||||
|
||||
pBB->edges[0].ip = ll->src().getImm2();
|
||||
else if ((pIcode->ic.ll.flg & (I | NO_LABEL)) == I) {
|
||||
pBB = newBB(pBB, start, ip, ONE_BRANCH, 1, pProc);
|
||||
pBB->edges[0].ip = pIcode->ic.ll.immed.op;
|
||||
}
|
||||
else
|
||||
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
newBB(pBB, start, ip, NOWHERE_NODE, 0, pProc);
|
||||
start = ip + 1;
|
||||
break;
|
||||
|
||||
case iCALLF: case iCALL:
|
||||
{
|
||||
Function * p = ll->src().proc.proc;
|
||||
{ PPROC p = pIcode->ic.ll.immed.proc.proc;
|
||||
if (p)
|
||||
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
||||
else
|
||||
i = 1;
|
||||
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
|
||||
iStart = ++iICODE(pIcode);//start = ip + 1;
|
||||
pBB = newBB(pBB, start, ip, CALL_NODE, i, pProc);
|
||||
start = ip + 1;
|
||||
if (i)
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
pBB->edges[0].ip = (dword)start;
|
||||
}
|
||||
break;
|
||||
|
||||
case iRET: case iRETF:
|
||||
//BB::Create(start, ip, RETURN_NODE, 0, this);
|
||||
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
newBB(pBB, start, ip, RETURN_NODE, 0, pProc);
|
||||
start = ip + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for exit to DOS */
|
||||
iICODE next1=++iICODE(pIcode);
|
||||
if ( ll->testFlags(TERMINATES) )
|
||||
if (pIcode->ic.ll.flg & TERMINATES)
|
||||
{
|
||||
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
|
||||
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB = newBB(pBB, start, ip, TERMINATE_NODE, 0, pProc);
|
||||
start = ip + 1;
|
||||
}
|
||||
/* Check for a fall through */
|
||||
else if (next1 != Icode.end())
|
||||
else if (pProc->Icode.GetFirstIcode()[ip + 1].ic.ll.flg & (TARGET | CASE))
|
||||
{
|
||||
if (next1->ll()->testFlags(TARGET | CASE))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB->addOutEdge(iStart->loc_ip);
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
}
|
||||
pBB = newBB(pBB, start, ip, FALL_NODE, 1, pProc);
|
||||
start = ip + 1;
|
||||
pBB->edges[0].ip = (dword)start;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto iter=heldBBs.begin();
|
||||
|
||||
/* Convert list of BBs into a graph */
|
||||
for (; iter!=heldBBs.end(); ++iter)
|
||||
for (pBB = cfg.next; pBB; pBB = pBB->next)
|
||||
{
|
||||
pBB = *iter;
|
||||
for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++)
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
{
|
||||
uint32_t ip = pBB->edges[edeg_idx].ip;
|
||||
ip = pBB->edges[i].ip;
|
||||
if (ip >= SYNTHESIZED_MIN)
|
||||
{
|
||||
fatalError (INVALID_SYNTHETIC_BB);
|
||||
return;
|
||||
}
|
||||
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
|
||||
[ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;});
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
psBB = *iter2;
|
||||
pBB->edges[edeg_idx].BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Function::markImpure()
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
for(ICODE &icod : Icode)
|
||||
else
|
||||
{
|
||||
if ( not icod.ll()->testFlags(SYM_USE | SYM_DEF))
|
||||
continue;
|
||||
//assert that case tbl has less entries then symbol table ????
|
||||
//WARNING: Case entries are held in symbol table !
|
||||
assert(g_proj.validSymIdx(icod.ll()->caseEntry));
|
||||
const SYM &psym(g_proj.getSymByIdx(icod.ll()->caseEntry));
|
||||
for (int c = (int)psym.label; c < (int)psym.label+psym.size; c++)
|
||||
for (psBB = cfg.next; psBB; psBB = psBB->next)
|
||||
if (psBB->start == ip)
|
||||
{
|
||||
if (BITMAP(c, BM_CODE))
|
||||
{
|
||||
icod.ll()->setFlags(IMPURE);
|
||||
flg |= IMPURE;
|
||||
pBB->edges[i].BBptr = psBB;
|
||||
psBB->numInEdges++;
|
||||
break;
|
||||
}
|
||||
if (! psBB)
|
||||
fatalError(NO_BB, ip, pProc->name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return cfg.next;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* newBB - Allocate new BB and link to end of list
|
||||
*****************************************************************************/
|
||||
PBB newBB (PBB pBB, Int start, Int ip, byte nodeType, Int numOutEdges,
|
||||
PPROC pproc)
|
||||
{
|
||||
PBB pnewBB;
|
||||
|
||||
pnewBB = allocStruc(BB);
|
||||
memset (pnewBB, 0, sizeof(BB));
|
||||
pnewBB->nodeType = nodeType; /* Initialise */
|
||||
pnewBB->start = start;
|
||||
pnewBB->length = ip - start + 1;
|
||||
pnewBB->numOutEdges = (byte)numOutEdges;
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
|
||||
if (numOutEdges)
|
||||
pnewBB->edges = (TYPEADR_TYPE*)allocMem(numOutEdges * sizeof(TYPEADR_TYPE));
|
||||
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if (start >= 0)
|
||||
pproc->Icode.SetInBB(start, ip, pnewBB);
|
||||
|
||||
while (pBB->next) /* Link */
|
||||
pBB = pBB->next;
|
||||
pBB->next = pnewBB;
|
||||
|
||||
if (start != -1) { /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
}
|
||||
return pnewBB;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* freeCFG - Deallocates a cfg
|
||||
****************************************************************************/
|
||||
void Function::freeCFG()
|
||||
void freeCFG(PBB cfg)
|
||||
{
|
||||
for(BB *p : heldBBs)
|
||||
{
|
||||
delete p;
|
||||
PBB pBB;
|
||||
|
||||
for (pBB = cfg; pBB; pBB = cfg) {
|
||||
if (pBB->inEdges)
|
||||
free(pBB->inEdges);
|
||||
if (pBB->edges)
|
||||
free(pBB->edges);
|
||||
cfg = pBB->next;
|
||||
free(pBB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,114 +213,104 @@ void Function::freeCFG()
|
||||
/*****************************************************************************
|
||||
* compressCFG - Remove redundancies and add in-edge information
|
||||
****************************************************************************/
|
||||
void Function::compressCFG()
|
||||
{
|
||||
BB *pNxt;
|
||||
int ip, first=0, last;
|
||||
void compressCFG(PPROC pProc)
|
||||
{ PBB pBB, pNxt;
|
||||
Int ip, first=0, last, i;
|
||||
|
||||
/* First pass over BB list removes redundant jumps of the form
|
||||
* (Un)Conditional -> Unconditional jump */
|
||||
for (BB *pBB : m_cfg)
|
||||
for (pBB = pProc->cfg; pBB; pBB = pBB->next)
|
||||
if (pBB->numInEdges != 0 && (pBB->nodeType == ONE_BRANCH ||
|
||||
pBB->nodeType == TWO_BRANCH))
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
{
|
||||
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
|
||||
continue;
|
||||
for (TYPEADR_TYPE &edgeRef : pBB->edges)
|
||||
{
|
||||
ip = pBB->rbegin()->loc_ip;
|
||||
pNxt = edgeRef.BBptr->rmJMP(ip, edgeRef.BBptr);
|
||||
ip = pBB->start + pBB->length - 1;
|
||||
pNxt = rmJMP(pProc, ip, pBB->edges[i].BBptr);
|
||||
|
||||
if (not pBB->edges.empty()) /* Might have been clobbered */
|
||||
if (pBB->numOutEdges) /* Might have been clobbered */
|
||||
{
|
||||
edgeRef.BBptr = pNxt;
|
||||
assert(pBB->back().loc_ip==ip);
|
||||
pBB->back().ll()->SetImmediateOp((uint32_t)pNxt->begin()->loc_ip);
|
||||
//Icode[ip].SetImmediateOp((uint32_t)pNxt->begin());
|
||||
}
|
||||
pBB->edges[i].BBptr = pNxt;
|
||||
pProc->Icode.SetImmediateOp(ip, (dword)pNxt->start);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next is a depth-first traversal merging any FALL_NODE or
|
||||
* ONE_BRANCH that fall through to a node with that as their only
|
||||
* in-edge. */
|
||||
m_cfg.front()->mergeFallThrough(Icode);
|
||||
mergeFallThrough(pProc, pProc->cfg);
|
||||
|
||||
/* Remove redundant BBs created by the above compressions
|
||||
* and allocate in-edge arrays as required. */
|
||||
stats.numBBaft = stats.numBBbef;
|
||||
|
||||
for(auto iter=m_cfg.begin(); iter!=m_cfg.end(); ++iter)
|
||||
for (pBB = pProc->cfg; pBB; pBB = pNxt)
|
||||
{
|
||||
BB * pBB = *iter;
|
||||
if (pBB->inEdges.empty())
|
||||
pNxt = pBB->next;
|
||||
if (pBB->numInEdges == 0)
|
||||
{
|
||||
if (iter == m_cfg.begin()) /* Init it misses out on */
|
||||
if (pBB == pProc->cfg) /* Init it misses out on */
|
||||
pBB->index = UN_INIT;
|
||||
else
|
||||
{
|
||||
delete pBB;
|
||||
if (pBB->numOutEdges)
|
||||
free(pBB->edges);
|
||||
free(pBB);
|
||||
stats.numBBaft--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pBB->inEdgeCount = pBB->inEdges.size();
|
||||
pBB->inEdgeCount = pBB->numInEdges;
|
||||
pBB->inEdges = (PBB*)allocMem(pBB->numInEdges * sizeof(PBB));
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate storage for dfsLast[] array */
|
||||
numBBs = stats.numBBaft;
|
||||
m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *))
|
||||
pProc->numBBs = stats.numBBaft;
|
||||
pProc->dfsLast = (PBB*)allocMem(pProc->numBBs * sizeof(PBB));
|
||||
|
||||
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
|
||||
last = numBBs - 1;
|
||||
m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
|
||||
last = pProc->numBBs - 1;
|
||||
dfsNumbering(pProc->cfg, pProc->dfsLast, &first, &last);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* rmJMP - If BB addressed is just a JMP it is replaced with its target
|
||||
***************************************************************************/
|
||||
BB *BB::rmJMP(int marker, BB * pBB)
|
||||
static PBB rmJMP(PPROC pProc, Int marker, PBB pBB)
|
||||
{
|
||||
marker += (int)DFS_JMP;
|
||||
marker += DFS_JMP;
|
||||
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1)
|
||||
{
|
||||
if (pBB->traversed != marker)
|
||||
{
|
||||
pBB->traversed = (eDFS)marker;
|
||||
pBB->inEdges.pop_back();
|
||||
if (not pBB->inEdges.empty())
|
||||
{
|
||||
pBB->edges[0].BBptr->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->length == 1) {
|
||||
if (pBB->traversed != marker) {
|
||||
pBB->traversed = marker;
|
||||
if (--pBB->numInEdges)
|
||||
pBB->edges[0].BBptr->numInEdges++;
|
||||
else
|
||||
{
|
||||
pBB->front().ll()->setFlags(NO_CODE);
|
||||
pBB->front().invalidate(); //pProc->Icode.SetLlInvalid(pBB->begin(), true);
|
||||
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||
}
|
||||
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are going around in circles */
|
||||
else { /* We are going around in circles */
|
||||
pBB->nodeType = NOWHERE_NODE;
|
||||
pBB->front().ll()->replaceSrc(LLOperand::CreateImm2(pBB->front().loc_ip));
|
||||
//pBB->front().ll()->src.immed.op = pBB->front().loc_ip;
|
||||
pProc->Icode.GetIcode(pBB->start)->ic.ll.immed.op = (dword)pBB->start;
|
||||
pProc->Icode.SetImmediateOp(pBB->start, (dword)pBB->start);
|
||||
do {
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
pBB->inEdges.pop_back(); // was --numInedges
|
||||
if (! pBB->inEdges.empty())
|
||||
if (! --pBB->numInEdges)
|
||||
{
|
||||
pBB->front().ll()->setFlags(NO_CODE);
|
||||
pBB->front().invalidate();
|
||||
// pProc->Icode.setFlags(pBB->start, NO_CODE);
|
||||
// pProc->Icode.SetLlInvalid(pBB->start, true);
|
||||
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||
}
|
||||
} while (pBB->nodeType != NOWHERE_NODE);
|
||||
|
||||
pBB->edges.clear();
|
||||
free(pBB->edges);
|
||||
pBB->numOutEdges = 0;
|
||||
pBB->edges = NULL;
|
||||
}
|
||||
}
|
||||
return pBB;
|
||||
@ -332,52 +320,50 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
/*****************************************************************************
|
||||
* mergeFallThrough
|
||||
****************************************************************************/
|
||||
void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
static void mergeFallThrough(PPROC pProc, PBB pBB)
|
||||
{
|
||||
BB * pChild;
|
||||
int i;
|
||||
PBB pChild;
|
||||
Int i, ip;
|
||||
|
||||
if (!this)
|
||||
if (pBB) {
|
||||
while (pBB->nodeType == FALL_NODE || pBB->nodeType == ONE_BRANCH)
|
||||
{
|
||||
printf("mergeFallThrough on empty BB!\n");
|
||||
}
|
||||
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
|
||||
{
|
||||
pChild = edges[0].BBptr;
|
||||
pChild = pBB->edges[0].BBptr;
|
||||
/* Jump to next instruction can always be removed */
|
||||
if (nodeType == ONE_BRANCH)
|
||||
if (pBB->nodeType == ONE_BRANCH)
|
||||
{
|
||||
assert(Parent==pChild->Parent);
|
||||
if(back().loc_ip>pChild->front().loc_ip) // back edege
|
||||
ip = pBB->start + pBB->length;
|
||||
for (i = ip; i < pChild->start
|
||||
&& (pProc->Icode.GetLlFlag(i) & NO_CODE); i++);
|
||||
if (i != pChild->start)
|
||||
break;
|
||||
auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c)
|
||||
{return not c.ll()->testFlags(NO_CODE);});
|
||||
pProc->Icode.SetLlFlag(ip - 1, NO_CODE);
|
||||
pProc->Icode.SetLlInvalid(ip - 1, TRUE);
|
||||
pBB->nodeType = FALL_NODE;
|
||||
pBB->length--;
|
||||
|
||||
if (iter != pChild->begin())
|
||||
break;
|
||||
back().ll()->setFlags(NO_CODE);
|
||||
back().invalidate();
|
||||
nodeType = FALL_NODE;
|
||||
//instructions.advance_end(-1); //TODO: causes creation of empty BB
|
||||
}
|
||||
/* If there's no other edges into child can merge */
|
||||
if (pChild->inEdges.size() != 1)
|
||||
if (pChild->numInEdges != 1)
|
||||
break;
|
||||
|
||||
nodeType = pChild->nodeType;
|
||||
instructions = boost::make_iterator_range(begin(),pChild->end());
|
||||
pChild->front().ll()->clrFlags(TARGET);
|
||||
edges.swap(pChild->edges);
|
||||
pBB->nodeType = pChild->nodeType;
|
||||
pBB->length = pChild->start + pChild->length - pBB->start;
|
||||
pProc->Icode.ClearLlFlag(pChild->start, TARGET);
|
||||
pBB->numOutEdges = pChild->numOutEdges;
|
||||
free(pBB->edges);
|
||||
pBB->edges = pChild->edges;
|
||||
|
||||
pChild->inEdges.clear();
|
||||
pChild->edges.clear();
|
||||
pChild->numOutEdges = pChild->numInEdges = 0;
|
||||
pChild->edges = NULL;
|
||||
}
|
||||
traversed = DFS_MERGE;
|
||||
pBB->traversed = DFS_MERGE;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (i = 0; i < edges.size(); i++)
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
if (pBB->edges[i].BBptr->traversed != DFS_MERGE)
|
||||
mergeFallThrough(pProc, pBB->edges[i].BBptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -385,26 +371,30 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
* dfsNumbering - Numbers nodes during first and last visits and determine
|
||||
* in-edges
|
||||
****************************************************************************/
|
||||
void BB::dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last)
|
||||
static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last)
|
||||
{
|
||||
BB * pChild;
|
||||
traversed = DFS_NUM;
|
||||
dfsFirstNum = (*first)++;
|
||||
PBB pChild;
|
||||
byte i;
|
||||
|
||||
if (pBB)
|
||||
{
|
||||
pBB->traversed = DFS_NUM;
|
||||
pBB->dfsFirstNum = (*first)++;
|
||||
|
||||
/* index is being used as an index to inEdges[]. */
|
||||
// for (i = 0; i < edges.size(); i++)
|
||||
for(auto edge : edges)
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
{
|
||||
pChild = edge.BBptr;
|
||||
pChild->inEdges[pChild->index++] = this;
|
||||
pChild = pBB->edges[i].BBptr;
|
||||
pChild->inEdges[pChild->index++] = pBB;
|
||||
|
||||
/* Is this the last visit? */
|
||||
if (pChild->index == pChild->inEdges.size())
|
||||
if (pChild->index == pChild->numInEdges)
|
||||
pChild->index = UN_INIT;
|
||||
|
||||
if (pChild->traversed != DFS_NUM)
|
||||
pChild->dfsNumbering(dfsLast, first, last);
|
||||
dfsNumbering(pChild, dfsLast, first, last);
|
||||
}
|
||||
pBB->dfsLastNum = *last;
|
||||
dfsLast[(*last)--] = pBB;
|
||||
}
|
||||
dfsLastNum = *last;
|
||||
dfsLast[(*last)--] = this;
|
||||
}
|
||||
|
||||
688
src/hlicode.cpp
688
src/hlicode.cpp
@ -4,20 +4,18 @@
|
||||
* Date: September-October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include <cassert>
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "dcc.h"
|
||||
using namespace std;
|
||||
|
||||
#define ICODE_DELTA 25
|
||||
|
||||
/* Masks off bits set by duReg[] */
|
||||
std::bitset<32> maskDuReg[] = { 0x00,
|
||||
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
|
||||
dword maskDuReg[] = { 0x00,
|
||||
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* word regs */
|
||||
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
|
||||
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
|
||||
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
|
||||
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* byte regs */
|
||||
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
|
||||
0xEFFFFF, /* tmp reg */
|
||||
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
||||
@ -27,608 +25,462 @@ static char buf[lineSize]; /* Line buffer for hl icode output */
|
||||
|
||||
|
||||
|
||||
void newAsgnHlIcode (PICODE pIcode, COND_EXPR *lhs, COND_EXPR *rhs)
|
||||
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
|
||||
void HLTYPE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
|
||||
{
|
||||
set(lhs,rhs);
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->ic.hl.opcode = HLI_ASSIGN;
|
||||
pIcode->ic.hl.oper.asgn.lhs = lhs;
|
||||
pIcode->ic.hl.oper.asgn.rhs = rhs;
|
||||
}
|
||||
|
||||
}
|
||||
void ICODE::checkHlCall()
|
||||
{
|
||||
//assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
|
||||
}
|
||||
|
||||
void newCallHlIcode (PICODE pIcode)
|
||||
/* Places the new HLI_CALL high-level operand in the high-level icode array */
|
||||
void ICODE::newCallHl()
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
hl()->opcode = HLI_CALL;
|
||||
hl()->call.proc = ll()->src().proc.proc;
|
||||
hl()->call.args = new STKFRAME;
|
||||
|
||||
if (ll()->src().proc.cb != 0)
|
||||
hl()->call.args->cb = ll()->src().proc.cb;
|
||||
else if(hl()->call.proc)
|
||||
hl()->call.args->cb =hl()->call.proc->cbParam;
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->ic.hl.opcode = HLI_CALL;
|
||||
pIcode->ic.hl.oper.call.proc = pIcode->ic.ll.immed.proc.proc;
|
||||
pIcode->ic.hl.oper.call.args = (STKFRAME*)allocMem (sizeof(STKFRAME));
|
||||
memset (pIcode->ic.hl.oper.call.args, 0, sizeof(STKFRAME));
|
||||
if (pIcode->ic.ll.immed.proc.cb != 0)
|
||||
pIcode->ic.hl.oper.call.args->cb = pIcode->ic.ll.immed.proc.cb;
|
||||
else
|
||||
{
|
||||
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
|
||||
hl()->call.args->cb = 0;
|
||||
}
|
||||
pIcode->ic.hl.oper.call.args->cb =pIcode->ic.hl.oper.call.proc->cbParam;
|
||||
}
|
||||
|
||||
|
||||
void newUnaryHlIcode (PICODE pIcode, hlIcode op, COND_EXPR *exp)
|
||||
/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
|
||||
* array */
|
||||
void ICODE::setUnary(hlIcode op, COND_EXPR *_exp)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
hl()->set(op,_exp);
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->ic.hl.opcode = op;
|
||||
pIcode->ic.hl.oper.exp = exp;
|
||||
}
|
||||
|
||||
|
||||
void newJCondHlIcode (PICODE pIcode, COND_EXPR *cexp)
|
||||
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
|
||||
void ICODE::setJCond(COND_EXPR *cexp)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
hl()->set(HLI_JCOND,cexp);
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->ic.hl.opcode = HLI_JCOND;
|
||||
pIcode->ic.hl.oper.exp = cexp;
|
||||
}
|
||||
|
||||
|
||||
/* Sets the invalid field to true as this low-level icode is no longer valid,
|
||||
void invalidateIcode (PICODE pIcode)
|
||||
/* Sets the invalid field to TRUE as this low-level icode is no longer valid,
|
||||
* it has been replaced by a high-level icode. */
|
||||
void ICODE ::invalidate()
|
||||
{
|
||||
invalid = true;
|
||||
pIcode->invalid = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Removes the defined register regi from the lhs subtree.
|
||||
* If all registers
|
||||
* of this instruction are unused, the instruction is invalidated (ie. removed)
|
||||
*/
|
||||
bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
|
||||
{
|
||||
int numDefs;
|
||||
boolT removeDefRegi (byte regi, PICODE picode, Int thisDefIdx, LOCAL_ID *locId)
|
||||
/* Removes the defined register regi from the lhs subtree. If all registers
|
||||
* of this instruction are unused, the instruction is invalidated (ie.
|
||||
* removed) */
|
||||
{ Int numDefs;
|
||||
|
||||
numDefs = du1.numRegsDef;
|
||||
numDefs = picode->du1.numRegsDef;
|
||||
if (numDefs == thisDefIdx)
|
||||
{
|
||||
for ( ; numDefs > 0; numDefs--)
|
||||
{
|
||||
|
||||
if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
|
||||
if ((picode->du1.idx[numDefs-1][0] != 0)||(picode->du.lastDefRegi))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numDefs == 0)
|
||||
{
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
HlTypeSupport *p=hl()->get();
|
||||
if(p and p->removeRegFromLong(regi,locId))
|
||||
{
|
||||
du1.numRegsDef--;
|
||||
du.def &= maskDuReg[regi];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
HLTYPE LLInst::createCall()
|
||||
{
|
||||
HLTYPE res(HLI_CALL);
|
||||
res.call.proc = src().proc.proc;
|
||||
res.call.args = new STKFRAME;
|
||||
|
||||
if (src().proc.cb != 0)
|
||||
res.call.args->cb = src().proc.cb;
|
||||
else if(res.call.proc)
|
||||
res.call.args->cb =res.call.proc->cbParam;
|
||||
else
|
||||
{
|
||||
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
|
||||
res.call.args->cb = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#if 0
|
||||
HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
{
|
||||
HLTYPE res(HLI_INVALID);
|
||||
if ( testFlags(NOT_HLL) )
|
||||
return res;
|
||||
flg = getFlag();
|
||||
|
||||
switch (getOpcode())
|
||||
{
|
||||
case iADD:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iAND:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iCALL:
|
||||
case iCALLF:
|
||||
//TODO: this is noop pIcode->checkHlCall();
|
||||
res=createCall();
|
||||
break;
|
||||
|
||||
case iDEC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iDIV:
|
||||
case iIDIV:/* should be signed div */
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
|
||||
if ( ll->testFlags(B) )
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAL, 0, &localId);
|
||||
pIcode->setRegDU( rAL, eDEF);
|
||||
invalidateIcode (picode);
|
||||
return (TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
||||
pIcode->setRegDU( rAX, eDEF);
|
||||
}
|
||||
res.setAsgn(lhs, rhs);
|
||||
switch (picode->ic.hl.opcode) {
|
||||
case HLI_ASSIGN: removeRegFromLong (regi, locId,
|
||||
picode->ic.hl.oper.asgn.lhs);
|
||||
picode->du1.numRegsDef--;
|
||||
picode->du.def &= maskDuReg[regi];
|
||||
break;
|
||||
|
||||
case iIMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iINC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iLEA:
|
||||
rhs = COND_EXPR::unary (ADDRESSOF, rhs);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOD:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
|
||||
if ( ll->testFlags(B) )
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAH, 0, &localId);
|
||||
pIcode->setRegDU( rAH, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rDX, 0, &localId);
|
||||
pIcode->setRegDU( rDX, eDEF);
|
||||
}
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOV: res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNEG:
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNOT:
|
||||
rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iPOP: res.set(HLI_POP, lhs);
|
||||
break;
|
||||
|
||||
case iPUSH: res.set(HLI_PUSH, lhs);
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF:
|
||||
res.set(HLI_RET, NULL);
|
||||
break;
|
||||
|
||||
case iSHL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSAR: /* signed */
|
||||
case iSHR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSIGNEX:
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSUB:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iXCHG:
|
||||
break;
|
||||
|
||||
case iXOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
res.setAsgn(lhs, rhs);
|
||||
case HLI_POP:
|
||||
case HLI_PUSH: removeRegFromLong (regi, locId, picode->ic.hl.oper.exp);
|
||||
picode->du1.numRegsDef--;
|
||||
picode->du.def &= maskDuReg[regi];
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void highLevelGen (PPROC pProc)
|
||||
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
|
||||
* Note: this process should be done before data flow analysis, which
|
||||
* refines the HIGH_LEVEL icodes. */
|
||||
void Function::highLevelGen()
|
||||
{
|
||||
int numIcode; /* number of icode instructions */
|
||||
iICODE pIcode; /* ptr to current icode node */
|
||||
{ Int i, /* idx into icode array */
|
||||
numIcode; /* number of icode instructions */
|
||||
PICODE pIcode; /* ptr to current icode node */
|
||||
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
|
||||
uint32_t _flg; /* icode flags */
|
||||
numIcode = Icode.size();
|
||||
for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
|
||||
flags32 flg; /* icode flags */
|
||||
|
||||
numIcode = pProc->Icode.GetNumIcodes();
|
||||
for (i = 0; i < numIcode; i++)
|
||||
{
|
||||
assert(numIcode==Icode.size());
|
||||
pIcode = i; //Icode.GetIcode(i)
|
||||
LLInst *ll = pIcode->ll();
|
||||
if ( ll->testFlags(NOT_HLL) )
|
||||
pIcode->invalidate();
|
||||
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
|
||||
continue;
|
||||
_flg = ll->getFlag();
|
||||
if ((_flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
|
||||
if ((_flg & NO_OPS) != NO_OPS) /* if there are opers */
|
||||
pIcode = pProc->Icode.GetIcode(i);
|
||||
if ((pIcode->ic.ll.flg & NOT_HLL) == NOT_HLL)
|
||||
invalidateIcode (pIcode);
|
||||
if ((pIcode->type == LOW_LEVEL) && (pIcode->invalid == FALSE))
|
||||
{
|
||||
if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
|
||||
rhs = COND_EXPR::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
|
||||
lhs = COND_EXPR::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
|
||||
flg = pIcode->ic.ll.flg;
|
||||
if ((flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
|
||||
if ((flg & NO_OPS) != NO_OPS) /* if there are opers */
|
||||
{
|
||||
if ((flg & NO_SRC) != NO_SRC) /* if there is src op */
|
||||
rhs = idCondExp (pIcode, SRC, pProc, i, pIcode, NONE);
|
||||
lhs = idCondExp (pIcode, DST, pProc, i, pIcode, NONE);
|
||||
}
|
||||
switch (ll->getOpcode())
|
||||
{
|
||||
case iADD:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iADD: rhs = boolCondExp (lhs, rhs, ADD);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iAND:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iAND: rhs = boolCondExp (lhs, rhs, AND);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iCALL:
|
||||
case iCALLF:
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->hl( ll->createCall() );
|
||||
case iCALLF: newCallHlIcode (pIcode);
|
||||
break;
|
||||
|
||||
case iDEC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iDEC: rhs = idCondExpKte (1, 2);
|
||||
rhs = boolCondExp (lhs, rhs, SUB);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iDIV:
|
||||
case iIDIV:/* should be signed div */
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
|
||||
if ( ll->testFlags(B) )
|
||||
rhs = boolCondExp (lhs, rhs, DIV);
|
||||
if (pIcode->ic.ll.flg & B)
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAL, 0, &localId);
|
||||
pIcode->setRegDU( rAL, eDEF);
|
||||
lhs = idCondExpReg (rAL, 0, &pProc->localId);
|
||||
setRegDU (pIcode, rAL, E_DEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
||||
pIcode->setRegDU( rAX, eDEF);
|
||||
lhs = idCondExpReg (rAX, 0, &pProc->localId);
|
||||
setRegDU (pIcode, rAX, E_DEF);
|
||||
}
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iIMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iIMUL: rhs = boolCondExp (lhs, rhs, MUL);
|
||||
lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode,
|
||||
NONE);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iINC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iINC: rhs = idCondExpKte (1, 2);
|
||||
rhs = boolCondExp (lhs, rhs, ADD);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iLEA:
|
||||
rhs = COND_EXPR::unary (ADDRESSOF, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iLEA: rhs = unaryCondExp (ADDRESSOF, rhs);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOD:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
|
||||
if ( ll->testFlags(B) )
|
||||
case iMOD: rhs = boolCondExp (lhs, rhs, MOD);
|
||||
if (pIcode->ic.ll.flg & B)
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAH, 0, &localId);
|
||||
pIcode->setRegDU( rAH, eDEF);
|
||||
lhs = idCondExpReg (rAH, 0, &pProc->localId);
|
||||
setRegDU (pIcode, rAH, E_DEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rDX, 0, &localId);
|
||||
pIcode->setRegDU( rDX, eDEF);
|
||||
lhs = idCondExpReg (rDX, 0, &pProc->localId);
|
||||
setRegDU (pIcode, rDX, E_DEF);
|
||||
}
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
||||
case iMOV: newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iMUL: rhs = boolCondExp (lhs, rhs, MUL);
|
||||
lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode,
|
||||
NONE);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNEG:
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iNEG: rhs = unaryCondExp (NEGATION, lhs);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNOT:
|
||||
rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iNOT: rhs = boolCondExp (NULL, rhs, NOT);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iOR: rhs = boolCondExp (lhs, rhs, OR);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iPOP: pIcode->setUnary(HLI_POP, lhs);
|
||||
case iPOP: newUnaryHlIcode (pIcode, HLI_POP, lhs);
|
||||
break;
|
||||
|
||||
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
|
||||
case iPUSH: newUnaryHlIcode (pIcode, HLI_PUSH, lhs);
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF: pIcode->setUnary(HLI_RET, NULL);
|
||||
case iRETF: newUnaryHlIcode (pIcode, HLI_RET, NULL);
|
||||
break;
|
||||
|
||||
case iSHL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iSHL: rhs = boolCondExp (lhs, rhs, SHL);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSAR: /* signed */
|
||||
case iSHR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iSHR: rhs = boolCondExp (lhs, rhs, SHR); /* unsigned*/
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSIGNEX: pIcode->setAsgn(lhs, rhs);
|
||||
case iSIGNEX: newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSUB:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iSUB: rhs = boolCondExp (lhs, rhs, SUB);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
|
||||
case iXCHG:
|
||||
break;
|
||||
|
||||
case iXOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
case iXOR: rhs = boolCondExp (lhs, rhs, XOR);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void inverseCondOp (COND_EXPR **exp)
|
||||
/* Modifies the given conditional operator to its inverse. This is used
|
||||
* in if..then[..else] statements, to reflect the condition that takes the
|
||||
* then part. */
|
||||
COND_EXPR *COND_EXPR::inverse () const
|
||||
{
|
||||
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
|
||||
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
|
||||
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
|
||||
DUMMY, DBL_OR, DBL_AND};
|
||||
COND_EXPR *res=0;
|
||||
if (m_type == BOOLEAN_OP)
|
||||
{
|
||||
switch ( op() )
|
||||
if (*exp == NULL) return;
|
||||
|
||||
if ((*exp)->type == BOOLEAN_OP)
|
||||
{
|
||||
switch ((*exp)->expr.boolExpr.op) {
|
||||
case LESS_EQUAL: case LESS: case EQUAL:
|
||||
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
|
||||
res = this->clone();
|
||||
res->boolExpr.op = invCondOp[op()];
|
||||
return res;
|
||||
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
|
||||
break;
|
||||
|
||||
case AND: case OR: case XOR: case NOT: case ADD:
|
||||
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
||||
return COND_EXPR::unary (NEGATION, this->clone());
|
||||
*exp = unaryCondExp (NEGATION, *exp);
|
||||
break;
|
||||
|
||||
case DBL_AND: case DBL_OR:
|
||||
// Binary::Create(invertop,lhs->inverse(),rhs->inverse());
|
||||
res = this->clone();
|
||||
res->boolExpr.op = invCondOp[op()];
|
||||
res->boolExpr.lhs=lhs()->inverse ();
|
||||
res->boolExpr.rhs=rhs()->inverse ();
|
||||
return res;
|
||||
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
|
||||
inverseCondOp (&(*exp)->expr.boolExpr.lhs);
|
||||
inverseCondOp (&(*exp)->expr.boolExpr.rhs);
|
||||
break;
|
||||
} /* eos */
|
||||
|
||||
}
|
||||
else if (m_type == NEGATION) //TODO: memleak here
|
||||
{
|
||||
return expr.unaryExp->clone();
|
||||
}
|
||||
return this->clone();
|
||||
else if ((*exp)->type == NEGATION)
|
||||
*exp = (*exp)->expr.unaryExp;
|
||||
|
||||
/* other types are left unmodified */
|
||||
}
|
||||
|
||||
|
||||
char *writeCall (PPROC tproc, PSTKFRAME args, PPROC pproc, Int *numLoc)
|
||||
/* Returns the string that represents the procedure call of tproc (ie. with
|
||||
* actual parameters) */
|
||||
std::string writeCall (Function * tproc, STKFRAME & args, Function * pproc, int *numLoc)
|
||||
{
|
||||
int i; /* counter of # arguments */
|
||||
string condExp;
|
||||
ostringstream ostr;
|
||||
ostr<<tproc->name<<" (";
|
||||
for(const STKSYM &sym : args)
|
||||
{ Int i; /* counter of # arguments */
|
||||
char *s, *condExp;
|
||||
|
||||
s = (char*)allocMem (100 * sizeof(char));
|
||||
s[0] = '\0';
|
||||
sprintf (s, "%s (", tproc->name);
|
||||
for (i = 0; i < args->csym; i++)
|
||||
{
|
||||
ostr << walkCondExpr (sym.actual, pproc, numLoc);
|
||||
if((&sym)!=&(args.back()))
|
||||
ostr << ", ";
|
||||
condExp = walkCondExpr (args->sym[i].actual, pproc, numLoc);
|
||||
strcat (s, condExp);
|
||||
if (i < (args->csym - 1))
|
||||
strcat (s, ", ");
|
||||
}
|
||||
ostr << ")";
|
||||
return ostr.str();
|
||||
strcat (s, ")");
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
char *writeJcond (HLTYPE h, PPROC pProc, Int *numLoc)
|
||||
/* Displays the output of a HLI_JCOND icode. */
|
||||
char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
|
||||
{
|
||||
assert(h.expr());
|
||||
{ char *e;
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
COND_EXPR *inverted=h.expr()->inverse();
|
||||
//inverseCondOp (&h.exp);
|
||||
std::string e = walkCondExpr (inverted, pProc, numLoc);
|
||||
delete inverted;
|
||||
strcat (buf, e.c_str());
|
||||
inverseCondOp (&h.oper.exp);
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
char *writeJcondInv (HLTYPE h, PPROC pProc, Int *numLoc)
|
||||
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case
|
||||
* when the THEN clause of an if..then..else is empty. The clause is
|
||||
* negated and the ELSE clause is used instead. */
|
||||
char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc)
|
||||
{
|
||||
{ char *e;
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
std::string e = walkCondExpr (h.expr(), pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
string AssignType::writeOut(Function *pProc, int *numLoc)
|
||||
{
|
||||
ostringstream ostr;
|
||||
ostr << walkCondExpr (lhs, pProc, numLoc);
|
||||
ostr << " = ";
|
||||
ostr << walkCondExpr (rhs, pProc, numLoc);
|
||||
ostr << ";\n";
|
||||
return ostr.str();
|
||||
}
|
||||
string CallType::writeOut(Function *pProc, int *numLoc)
|
||||
{
|
||||
ostringstream ostr;
|
||||
ostr << writeCall (proc, *args, pProc,numLoc);
|
||||
ostr << ";\n";
|
||||
return ostr.str();
|
||||
}
|
||||
string ExpType::writeOut(Function *pProc, int *numLoc)
|
||||
{
|
||||
return walkCondExpr (v, pProc, numLoc);
|
||||
}
|
||||
|
||||
char *write1HlIcode (HLTYPE h, PPROC pProc, Int *numLoc)
|
||||
/* Returns a string with the contents of the current high-level icode.
|
||||
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
|
||||
* done in a separate routine to be able to support the removal of
|
||||
* empty THEN clauses on an if..then..else. */
|
||||
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
|
||||
{
|
||||
string e;
|
||||
ostringstream ostr;
|
||||
HlTypeSupport *p = get();
|
||||
switch (opcode)
|
||||
{ char *e;
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
switch (h.opcode) {
|
||||
case HLI_ASSIGN: e = walkCondExpr (h.oper.asgn.lhs, pProc, numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, " = ");
|
||||
e = walkCondExpr (h.oper.asgn.rhs, pProc, numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, ";\n");
|
||||
break;
|
||||
case HLI_CALL: e = writeCall (h.oper.call.proc, h.oper.call.args, pProc,
|
||||
numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, ";\n");
|
||||
break;
|
||||
case HLI_RET: e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
if (e[0] != '\0')
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_CALL:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_RET:
|
||||
e = p->writeOut(pProc,numLoc);
|
||||
if (! e.empty())
|
||||
ostr << "return (" << e << ");\n";
|
||||
strcat (buf, "return (");
|
||||
strcat (buf, e);
|
||||
strcat (buf, ");\n");
|
||||
}
|
||||
break;
|
||||
case HLI_POP:
|
||||
ostr << "HLI_POP ";
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
case HLI_POP: strcat (buf, "HLI_POP ");
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, "\n");
|
||||
break;
|
||||
case HLI_PUSH:
|
||||
ostr << "HLI_PUSH ";
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
case HLI_PUSH: strcat (buf, "HLI_PUSH ");
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e);
|
||||
strcat (buf, "\n");
|
||||
break;
|
||||
}
|
||||
return ostr.str();
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
//TODO: replace all "< (INDEX_BX_SI-1)" with machine_x86::lastReg
|
||||
|
||||
//TODO: replace all >= INDEX_BX_SI with machine_x86::isRegExpression
|
||||
Int power2 (Int i)
|
||||
/* Returns the value of 2 to the power of i */
|
||||
{
|
||||
if (i == 0)
|
||||
return (1);
|
||||
return (2 << (i-1));
|
||||
}
|
||||
|
||||
|
||||
void writeDU (PICODE pIcode, Int idx)
|
||||
/* Writes the registers/stack variables that are used and defined by this
|
||||
* instruction. */
|
||||
void ICODE::writeDU()
|
||||
{
|
||||
int my_idx = loc_ip;
|
||||
{ static char buf[100];
|
||||
Int i, j;
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < (INDEXBASE-1); i++)
|
||||
{
|
||||
ostringstream ostr;
|
||||
Machine_X86::writeRegVector(ostr,du.def);
|
||||
if (!ostr.str().empty())
|
||||
printf ("Def (reg) = %s\n", ostr.str().c_str());
|
||||
}
|
||||
if ((pIcode->du.def & power2(i)) != 0)
|
||||
{
|
||||
ostringstream ostr;
|
||||
Machine_X86::writeRegVector(ostr,du.use);
|
||||
if (!ostr.str().empty())
|
||||
printf ("Use (reg) = %s\n", ostr.str().c_str());
|
||||
strcat (buf, allRegs[i]);
|
||||
strcat (buf, " ");
|
||||
}
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
printf ("Def (reg) = %s\n", buf);
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < INDEXBASE; i++)
|
||||
{
|
||||
if ((pIcode->du.use & power2(i)) != 0)
|
||||
{
|
||||
strcat (buf, allRegs[i]);
|
||||
strcat (buf, " ");
|
||||
}
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
printf ("Use (reg) = %s\n", buf);
|
||||
|
||||
/* Print du1 chain */
|
||||
printf ("# regs defined = %d\n", du1.numRegsDef);
|
||||
for (int i = 0; i < MAX_REGS_DEF; i++)
|
||||
printf ("# regs defined = %d\n", pIcode->du1.numRegsDef);
|
||||
for (i = 0; i < MAX_REGS_DEF; i++)
|
||||
if (pIcode->du1.idx[i][0] != 0)
|
||||
{
|
||||
if (not du1.used(i))
|
||||
continue;
|
||||
printf ("%d: du1[%d][] = ", my_idx, i);
|
||||
for(auto j : du1.idx[i].uses)
|
||||
printf ("%d: du1[%d][] = ", idx, i);
|
||||
for (j = 0; j < MAX_USES; j++)
|
||||
{
|
||||
printf ("%d ", j->loc_ip);
|
||||
if (pIcode->du1.idx[i][j] == 0)
|
||||
break;
|
||||
printf ("%d ", pIcode->du1.idx[i][j]);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/* For HLI_CALL, print # parameter bytes */
|
||||
if (hl()->opcode == HLI_CALL)
|
||||
printf ("# param bytes = %d\n", hl()->call.args->cb);
|
||||
if (pIcode->ic.hl.opcode == HLI_CALL)
|
||||
printf ("# param bytes = %d\n", pIcode->ic.hl.oper.call.args->cb);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
void freeHlIcode (PICODE icode, Int numIcodes)
|
||||
/* Frees the storage allocated to h->hlIcode */
|
||||
{ Int i;
|
||||
HLTYPE h;
|
||||
|
||||
for (i = 0; i < numIcodes; i++)
|
||||
{
|
||||
h = icode[i].ic.hl;
|
||||
switch (h.opcode) {
|
||||
case HLI_ASSIGN: freeCondExpr (h.oper.asgn.lhs);
|
||||
freeCondExpr (h.oper.asgn.rhs);
|
||||
break;
|
||||
case HLI_POP: case HLI_PUSH:
|
||||
case HLI_JCOND: freeCondExpr (h.oper.exp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
175
src/icode.cpp
175
src/icode.cpp
@ -5,98 +5,139 @@
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "types.h" // Common types like uint8_t, etc
|
||||
#include "types.h" // Common types like byte, etc
|
||||
#include "ast.h" // Some icode types depend on these
|
||||
#include "icode.h"
|
||||
|
||||
void *reallocVar(void *p, Int newsize); /* frontend.c !? */
|
||||
#define ICODE_DELTA 25 // Amount to allocate for new chunk
|
||||
|
||||
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level;
|
||||
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level;
|
||||
|
||||
CIcodeRec::CIcodeRec()
|
||||
{
|
||||
numIcode = 0;
|
||||
alloc = 0;
|
||||
icode = 0; // Initialise the pointer to 0
|
||||
}
|
||||
|
||||
CIcodeRec::~CIcodeRec()
|
||||
{
|
||||
if (icode)
|
||||
{
|
||||
free(icode);
|
||||
}
|
||||
}
|
||||
|
||||
PICODE CIcodeRec::addIcode(PICODE pIcode)
|
||||
|
||||
/* Copies the icode that is pointed to by pIcode to the icode array.
|
||||
* If there is need to allocate extra memory, it is done so, and
|
||||
* the alloc variable is adjusted. */
|
||||
ICODE * CIcodeRec::addIcode(ICODE *pIcode)
|
||||
{
|
||||
push_back(*pIcode);
|
||||
back().loc_ip = size()-1;
|
||||
return &back();
|
||||
}
|
||||
PICODE resIcode;
|
||||
|
||||
void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB)
|
||||
{
|
||||
for(ICODE &ic : rang)
|
||||
if (numIcode == alloc)
|
||||
{
|
||||
ic.setParent(pnewBB);
|
||||
alloc += ICODE_DELTA;
|
||||
icode = (PICODE)reallocVar(icode, alloc * sizeof(ICODE));
|
||||
memset (&icode[numIcode], 0, ICODE_DELTA * sizeof(ICODE));
|
||||
|
||||
}
|
||||
resIcode = (PICODE)memcpy (&icode[numIcode], pIcode,
|
||||
sizeof(ICODE));
|
||||
numIcode++;
|
||||
return (resIcode);
|
||||
}
|
||||
|
||||
PICODE CIcodeRec::GetFirstIcode()
|
||||
{
|
||||
return icode;
|
||||
}
|
||||
|
||||
/* Don't need this; just pIcode++ since array is guaranteed to be contiguous
|
||||
PICODE CIcodeRec::GetNextIcode(PICODE pCurIcode)
|
||||
{
|
||||
int idx = pCurIcode - icode; // Current index
|
||||
ASSERT(idx+1 < numIcode);
|
||||
return &icode[idx+1];
|
||||
}
|
||||
*/
|
||||
|
||||
boolT CIcodeRec::IsValid(PICODE pCurIcode)
|
||||
{
|
||||
int idx = pCurIcode - icode; // Current index
|
||||
return idx < numIcode;
|
||||
}
|
||||
|
||||
int CIcodeRec::GetNumIcodes()
|
||||
{
|
||||
return numIcode;
|
||||
}
|
||||
|
||||
void CIcodeRec::SetInBB(int start, int end, struct _BB* pnewBB)
|
||||
{
|
||||
for (int i = start; i <= end; i++)
|
||||
icode[i].inBB = pnewBB;
|
||||
}
|
||||
|
||||
void CIcodeRec::SetImmediateOp(int ip, dword dw)
|
||||
{
|
||||
icode[ip].ic.ll.immed.op = dw;
|
||||
}
|
||||
|
||||
void CIcodeRec::SetLlFlag(int ip, dword flag)
|
||||
{
|
||||
icode[ip].ic.ll.flg |= flag;
|
||||
}
|
||||
|
||||
dword CIcodeRec::GetLlFlag(int ip)
|
||||
{
|
||||
return icode[ip].ic.ll.flg;
|
||||
}
|
||||
|
||||
void CIcodeRec::ClearLlFlag(int ip, dword flag)
|
||||
{
|
||||
icode[ip].ic.ll.flg &= (~flag);
|
||||
}
|
||||
|
||||
void CIcodeRec::SetLlInvalid(int ip, boolT fInv)
|
||||
{
|
||||
icode[ip].invalid = fInv;
|
||||
}
|
||||
|
||||
dword CIcodeRec::GetLlLabel(int ip)
|
||||
{
|
||||
return icode[ip].ic.ll.label;
|
||||
}
|
||||
|
||||
llIcode CIcodeRec::GetLlOpcode(int ip)
|
||||
{
|
||||
return icode[ip].ic.ll.opcode;
|
||||
}
|
||||
|
||||
|
||||
boolT CIcodeRec::labelSrch(dword target, Int *pIndex)
|
||||
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
|
||||
replaces *pIndex with an icode index */
|
||||
bool CIcodeRec::labelSrch(uint32_t target, uint32_t &pIndex)
|
||||
{
|
||||
iICODE location=labelSrch(target);
|
||||
if(end()==location)
|
||||
return false;
|
||||
pIndex=location->loc_ip;
|
||||
return true;
|
||||
}
|
||||
bool CIcodeRec::alreadyDecoded(uint32_t target)
|
||||
{
|
||||
iICODE location=labelSrch(target);
|
||||
if(end()==location)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target)
|
||||
{
|
||||
return find_if(begin(),end(),[target](ICODE &l) -> bool {return l.ll()->label==target;});
|
||||
}
|
||||
ICODE * CIcodeRec::GetIcode(int ip)
|
||||
{
|
||||
assert(ip>=0 && ip<size());
|
||||
iICODE res=begin();
|
||||
advance(res,ip);
|
||||
return &(*res);
|
||||
}
|
||||
Int i;
|
||||
|
||||
extern int getNextLabel();
|
||||
extern bundle cCode;
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be backpatched
|
||||
* onto code in cCode.code */
|
||||
void LLInst::emitGotoLabel (int indLevel)
|
||||
{
|
||||
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */
|
||||
for (i = 0; i < numIcode; i++)
|
||||
{
|
||||
/* Generate new label */
|
||||
hllLabNum = getNextLabel();
|
||||
setFlags(HLL_LABEL);
|
||||
|
||||
/* Node has been traversed already, so backpatch this label into
|
||||
* the code */
|
||||
cCode.code.addLabelBundle (codeIdx, hllLabNum);
|
||||
if (icode[i].ic.ll.label == target)
|
||||
{
|
||||
*pIndex = i;
|
||||
return TRUE;
|
||||
}
|
||||
cCode.appendCode( "%sgoto L%ld;\n", indentStr(indLevel), hllLabNum);
|
||||
stats.numHLIcode++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LLOperand::isReg() const
|
||||
PICODE CIcodeRec::GetIcode(int ip)
|
||||
{
|
||||
return (regi>=rAX) && (regi<=rTMP);
|
||||
}
|
||||
void LLOperand::addProcInformation(int param_count, uint32_t call_conv)
|
||||
{
|
||||
proc.proc->cbParam = (int16_t)param_count;
|
||||
proc.cb = param_count;
|
||||
proc.proc->flg |= call_conv;
|
||||
return &icode[ip];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1377
src/idioms.cpp
1377
src/idioms.cpp
File diff suppressed because it is too large
Load Diff
@ -1,314 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "arith_idioms.h"
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom5 - Long addition.
|
||||
* ADD reg/stackOff, reg/stackOff
|
||||
* ADC reg/stackOff, reg/stackOff
|
||||
* Eg: ADD ax, [bp-4]
|
||||
* ADC dx, [bp-2]
|
||||
* => dx:ax = dx:ax + [bp-2]:[bp-4]
|
||||
* Found in Borland Turbo C code.
|
||||
* Commonly used idiom for long addition.
|
||||
****************************************************************************/
|
||||
bool Idiom5::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[1]->ll()->match(iADC))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom5::action()
|
||||
{
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom6 - Long substraction.
|
||||
* SUB reg/stackOff, reg/stackOff
|
||||
* SBB reg/stackOff, reg/stackOff
|
||||
* Eg: SUB ax, [bp-4]
|
||||
* SBB dx, [bp-2]
|
||||
* => dx:ax = dx:ax - [bp-2]:[bp-4]
|
||||
* Found in Borland Turbo C code.
|
||||
* Commonly used idiom for long substraction.
|
||||
****************************************************************************/
|
||||
bool Idiom6::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[1]->ll()->match(iSBB))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom6::action()
|
||||
{
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 18: Post-increment or post-decrement in a conditional jump
|
||||
* Used
|
||||
* 0 MOV reg, var (including register variables)
|
||||
* 1 INC var or DEC var <------------------------- input point
|
||||
* 2 CMP var, Y
|
||||
* 3 JX label
|
||||
* => HLI_JCOND (var++ X Y)
|
||||
* Eg: MOV ax, si
|
||||
* INC si
|
||||
* CMP ax, 8
|
||||
* JL labX
|
||||
* => HLI_JCOND (si++ < 8)
|
||||
* Found in Borland Turbo C. Intrinsic to C languages.
|
||||
****************************************************************************/
|
||||
bool Idiom18::match(iICODE picode)
|
||||
{
|
||||
if(picode==m_func->Icode.begin())
|
||||
return false;
|
||||
if(std::distance(picode,m_end)<3)
|
||||
return false;
|
||||
--picode; //
|
||||
|
||||
for(int i=0; i<4; ++i)
|
||||
m_icodes[i] =picode++;
|
||||
|
||||
m_is_dec = m_icodes[1]->ll()->match(iDEC);
|
||||
int type = -1; /* type of variable: 1 = reg-var, 2 = local */
|
||||
uint8_t regi; /* register of the MOV */
|
||||
|
||||
/* Get variable */
|
||||
if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */
|
||||
{
|
||||
/* not supported yet */
|
||||
type = 0;
|
||||
}
|
||||
else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */
|
||||
{
|
||||
if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
|
||||
type = 1;
|
||||
else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
|
||||
type = 1;
|
||||
}
|
||||
else if (m_icodes[1]->ll()->dst.off) /* local variable */
|
||||
type = 2;
|
||||
else /* indexed */
|
||||
{
|
||||
type=3;
|
||||
/* not supported yet */
|
||||
printf("Unsupported idiom18 type: indexed");
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case 0: // global
|
||||
printf("Unsupported idiom18 type: global variable");
|
||||
break;
|
||||
case 1: /* register variable */
|
||||
/* Check previous instruction for a MOV */
|
||||
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi))
|
||||
{
|
||||
regi = m_icodes[0]->ll()->dst.regi;
|
||||
if ( m_icodes[0]->ll()->dst.isReg() )
|
||||
{
|
||||
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump() )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: /* local */
|
||||
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off))
|
||||
{
|
||||
regi = m_icodes[0]->ll()->dst.regi;
|
||||
if ( m_icodes[0]->ll()->dst.isReg() )
|
||||
{
|
||||
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump() )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: // indexed
|
||||
printf("Unsupported idiom18 type: indexed");
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom18::action() // action length
|
||||
{
|
||||
COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
|
||||
COND_EXPR *expr;
|
||||
lhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
|
||||
lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs);
|
||||
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
|
||||
m_icodes[3]->setJCond(expr);
|
||||
|
||||
m_icodes[0]->invalidate();
|
||||
m_icodes[1]->invalidate();
|
||||
m_icodes[2]->invalidate();
|
||||
return 3;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0.
|
||||
* [INC | DEC] var (including register vars)
|
||||
* JX lab JX lab
|
||||
* => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0)
|
||||
* Eg: INC [bp+4]
|
||||
* JG lab2
|
||||
* => HLI_JCOND (++[bp+4] > 0)
|
||||
* Found in Borland Turbo C. Intrinsic to C language.
|
||||
****************************************************************************/
|
||||
bool Idiom19::match(iICODE picode)
|
||||
{
|
||||
if(std::distance(picode,m_end)<2)
|
||||
return false;
|
||||
|
||||
for(int i=0; i<2; ++i)
|
||||
m_icodes[i] =picode++;
|
||||
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
||||
if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */
|
||||
/* not supported yet */ ;
|
||||
else if ( m_icodes[0]->ll()->dst.isReg() ) /* register */
|
||||
{
|
||||
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
|
||||
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
|
||||
if (m_icodes[1]->ll()->conditionalJump())
|
||||
return true;
|
||||
}
|
||||
else if (m_icodes[0]->ll()->dst.off) /* stack variable */
|
||||
{
|
||||
if ( m_icodes[1]->ll()->conditionalJump() )
|
||||
return true;
|
||||
}
|
||||
else /* indexed */
|
||||
/* not supported yet */ ;
|
||||
return false;
|
||||
}
|
||||
int Idiom19::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs,*expr;
|
||||
lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
|
||||
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
||||
rhs = COND_EXPR::idKte (0, 2);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
|
||||
m_icodes[1]->setJCond(expr);
|
||||
m_icodes[0]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom20: Pre increment/decrement in conditional expression (compares
|
||||
* against a register, variable or constant different than 0).
|
||||
* INC var or DEC var (including register vars)
|
||||
* MOV reg, var MOV reg, var
|
||||
* CMP reg, Y CMP reg, Y
|
||||
* JX lab JX lab
|
||||
* => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y)
|
||||
* Eg: INC si (si is a register variable)
|
||||
* MOV ax, si
|
||||
* CMP ax, 2
|
||||
* JL lab4
|
||||
* => HLI_JCOND (++si < 2)
|
||||
* Found in Turbo C. Intrinsic to C language.
|
||||
****************************************************************************/
|
||||
bool Idiom20::match(iICODE picode)
|
||||
{
|
||||
uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
uint8_t regi; /* register of the MOV */
|
||||
if(std::distance(picode,m_end)<4)
|
||||
return false;
|
||||
for(int i=0; i<4; ++i)
|
||||
m_icodes[i] =picode++;
|
||||
|
||||
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
||||
|
||||
LLOperand &ll_dest(m_icodes[0]->ll()->dst);
|
||||
/* Get variable */
|
||||
if (ll_dest.regi == 0) /* global variable */
|
||||
{
|
||||
/* not supported yet */ ;
|
||||
}
|
||||
else if ( ll_dest.isReg() ) /* register */
|
||||
{
|
||||
if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR))
|
||||
type = 1;
|
||||
else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR))
|
||||
type = 1;
|
||||
}
|
||||
else if (ll_dest.off) /* local variable */
|
||||
type = 2;
|
||||
else /* indexed */
|
||||
{
|
||||
printf("idiom20 : Unsupported type [indexed]\n");
|
||||
/* not supported yet */ ;
|
||||
}
|
||||
|
||||
/* Check previous instruction for a MOV */
|
||||
if (type == 1) /* register variable */
|
||||
{
|
||||
if (m_icodes[1]->ll()->match(iMOV) &&
|
||||
(m_icodes[1]->ll()->src().regi == ll_dest.regi))
|
||||
{
|
||||
regi = m_icodes[1]->ll()->dst.regi;
|
||||
if ( m_icodes[1]->ll()->dst.isReg() )
|
||||
{
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == 2) /* local */
|
||||
{
|
||||
if ( m_icodes[0]->ll()->match(iMOV) &&
|
||||
(m_icodes[1]->ll()->src().off == ll_dest.off))
|
||||
{
|
||||
regi = m_icodes[1]->ll()->dst.regi;
|
||||
if ( m_icodes[1]->ll()->dst.isReg() )
|
||||
{
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom20::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs,*expr;
|
||||
lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
|
||||
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
||||
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
|
||||
m_icodes[3]->setJCond(expr);
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]->invalidate();
|
||||
return 4;
|
||||
}
|
||||
@ -1,111 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "call_idioms.h"
|
||||
using namespace std;
|
||||
/*****************************************************************************
|
||||
* idiom3 - C calling convention.
|
||||
* CALL(F) proc_X
|
||||
* ADD SP, immed
|
||||
* Eg: CALL proc_X
|
||||
* ADD SP, 6
|
||||
* => pProc->cbParam = immed
|
||||
* Special case: when the call is at the end of the procedure,
|
||||
* sometimes the stack gets restored by a MOV sp, bp.
|
||||
* Need to flag the procedure in these cases.
|
||||
* Used by compilers to restore the stack when invoking a procedure using
|
||||
* the C calling convention.
|
||||
****************************************************************************/
|
||||
bool Idiom3::match(iICODE picode)
|
||||
{
|
||||
if(distance(picode,m_end)<2)
|
||||
return false;
|
||||
m_param_count=0;
|
||||
/* Match ADD SP, immed */
|
||||
for(int i=0; i<2; ++i)
|
||||
m_icodes[i] = picode++;
|
||||
if ( m_icodes[1]->ll()->testFlags(I) && m_icodes[1]->ll()->match(iADD,rSP))
|
||||
{
|
||||
m_param_count = m_icodes[1]->ll()->src().getImm2();
|
||||
return true;
|
||||
}
|
||||
else if (m_icodes[1]->ll()->match(iMOV,rSP,rBP))
|
||||
{
|
||||
m_icodes[0]->ll()->setFlags(REST_STK);
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int Idiom3::action()
|
||||
{
|
||||
if (m_icodes[0]->ll()->testFlags(I) )
|
||||
{
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Indirect call at idiom3\n");
|
||||
}
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 17 - C calling convention.
|
||||
* CALL(F) xxxx
|
||||
* POP reg
|
||||
* [POP reg] reg in {AX, BX, CX, DX}
|
||||
* Eg: CALL proc_X
|
||||
* POP cx
|
||||
* POP cx (4 bytes of arguments)
|
||||
* => pProc->cbParam = # pops * 2
|
||||
* Found in Turbo C when restoring the stack for a procedure that uses the
|
||||
* C calling convention. Used to restore the stack of 2 or 4 bytes args.
|
||||
****************************************************************************/
|
||||
bool Idiom17::match(iICODE picode)
|
||||
{
|
||||
if(distance(picode,m_end)<2)
|
||||
return false;
|
||||
m_param_count=0; /* Count on # pops */
|
||||
m_icodes.clear();
|
||||
|
||||
/* Match ADD SP, immed */
|
||||
for(int i=0; i<2; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
uint8_t regi;
|
||||
|
||||
/* Match POP reg */
|
||||
if (m_icodes[1]->ll()->match(iPOP))
|
||||
{
|
||||
int i=0;
|
||||
regi = m_icodes[1]->ll()->dst.regi;
|
||||
if ((regi >= rAX) && (regi <= rBX))
|
||||
i++;
|
||||
|
||||
while (picode != m_end && picode->ll()->match(iPOP))
|
||||
{
|
||||
if (picode->ll()->dst.regi != regi)
|
||||
break;
|
||||
i++;
|
||||
m_icodes.push_back(picode++);
|
||||
}
|
||||
m_param_count = i*2;
|
||||
}
|
||||
return m_param_count!=0;
|
||||
}
|
||||
int Idiom17::action()
|
||||
{
|
||||
if (m_icodes[0]->ll()->testFlags(I))
|
||||
{
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C);
|
||||
for(size_t idx=1; idx<m_icodes.size(); ++idx)
|
||||
{
|
||||
m_icodes[idx]->invalidate();
|
||||
}
|
||||
}
|
||||
// TODO : it's a calculated call
|
||||
else
|
||||
{
|
||||
printf("Indirect call at idiom17\n");
|
||||
}
|
||||
return m_icodes.size();
|
||||
}
|
||||
@ -1,153 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "epilogue_idioms.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* popStkVars - checks for
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* or [POP SI]
|
||||
* [POP DI]
|
||||
****************************************************************************/
|
||||
void EpilogIdiom::popStkVars(iICODE pIcode)
|
||||
{
|
||||
// TODO : only process SI-DI DI-SI pairings, no SI-SI, DI-DI like it's now
|
||||
/* Match [POP DI] */
|
||||
if (pIcode->ll()->match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
++pIcode;
|
||||
if(pIcode==m_end)
|
||||
return;
|
||||
/* Match [POP SI] */
|
||||
if (pIcode->ll()->match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom2 - HLL procedure epilogue; Returns number of instructions matched.
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* MOV SP, BP
|
||||
* POP BP
|
||||
* RET(F)
|
||||
*****************************************************************************/
|
||||
bool Idiom2::match(iICODE pIcode)
|
||||
{
|
||||
iICODE nicode;
|
||||
if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
|
||||
return false;
|
||||
if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) )
|
||||
return false;
|
||||
if(distance(pIcode,m_end)<3)
|
||||
return false;
|
||||
/* Matched MOV SP, BP */
|
||||
m_icodes.clear();
|
||||
m_icodes.push_back(pIcode);
|
||||
/* Get next icode, skip over holes in the icode array */
|
||||
nicode = ++iICODE(pIcode);
|
||||
while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end))
|
||||
{
|
||||
nicode++;
|
||||
}
|
||||
if(nicode == m_end)
|
||||
return false;
|
||||
|
||||
if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) )
|
||||
{
|
||||
m_icodes.push_back(nicode++); // Matched POP BP
|
||||
|
||||
/* Match RET(F) */
|
||||
if ( nicode != m_end &&
|
||||
!(nicode->ll()->testFlags(I | TARGET | CASE)) &&
|
||||
(nicode->ll()->match(iRET) || nicode->ll()->match(iRETF))
|
||||
)
|
||||
{
|
||||
m_icodes.push_back(nicode); // Matched RET
|
||||
advance(pIcode,-2); // move back before our start
|
||||
popStkVars (pIcode); // and add optional pop di/si to m_icodes
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom2::action()
|
||||
{
|
||||
for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
|
||||
m_icodes[idx]->invalidate();
|
||||
return 3;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom4 - Pascal calling convention.
|
||||
* RET(F) immed
|
||||
* ==> pProc->cbParam = immed
|
||||
* sets CALL_PASCAL flag
|
||||
* - Second version: check for optional pop of stack vars
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* POP BP
|
||||
* RET(F) [immed]
|
||||
* - Third version: pop stack vars
|
||||
* [POP DI]
|
||||
* [POP SI]
|
||||
* RET(F) [immed]
|
||||
****************************************************************************/
|
||||
bool Idiom4::match(iICODE pIcode)
|
||||
{
|
||||
m_param_count = 0;
|
||||
/* Check for [POP DI]
|
||||
* [POP SI] */
|
||||
if(distance(m_func->Icode.begin(),pIcode)>=3)
|
||||
{
|
||||
iICODE search_at(pIcode);
|
||||
advance(search_at,-3);
|
||||
popStkVars(search_at);
|
||||
}
|
||||
if(pIcode != m_func->Icode.begin())
|
||||
{
|
||||
iICODE prev1 = --iICODE(pIcode);
|
||||
/* Check for POP BP */
|
||||
if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) )
|
||||
m_icodes.push_back(prev1);
|
||||
else if(prev1!=m_func->Icode.begin())
|
||||
{
|
||||
iICODE search_at(pIcode);
|
||||
advance(search_at,-2);
|
||||
popStkVars (search_at);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for RET(F) immed */
|
||||
if (pIcode->ll()->testFlags(I) )
|
||||
{
|
||||
m_param_count = (int16_t)pIcode->ll()->src().getImm2();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom4::action()
|
||||
{
|
||||
if( ! m_icodes.empty()) // if not an empty RET[F] N
|
||||
{
|
||||
for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
|
||||
m_icodes[idx]->invalidate();
|
||||
}
|
||||
if(m_param_count)
|
||||
{
|
||||
m_func->cbParam = (int16_t)m_param_count;
|
||||
m_func->flg |= CALL_PASCAL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1,137 +0,0 @@
|
||||
#include "idiom1.h"
|
||||
#include "dcc.h"
|
||||
|
||||
/*****************************************************************************
|
||||
/* checkStkVars - Checks for PUSH SI
|
||||
* [PUSH DI]
|
||||
* or PUSH DI
|
||||
* [PUSH SI]
|
||||
* In which case, the stack variable flags are set
|
||||
****************************************************************************/
|
||||
int Idiom1::checkStkVars (iICODE pIcode)
|
||||
{
|
||||
/* Look for PUSH SI */
|
||||
int si_matched=0;
|
||||
int di_matched=0;
|
||||
if(pIcode==m_end)
|
||||
return 0;
|
||||
if (pIcode->ll()->match(iPUSH,rSI))
|
||||
{
|
||||
si_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
|
||||
di_matched = 1;
|
||||
}
|
||||
else if (pIcode->ll()->match(iPUSH,rDI))
|
||||
{
|
||||
di_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
|
||||
si_matched = 1;
|
||||
}
|
||||
m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0);
|
||||
return si_matched+di_matched;
|
||||
}
|
||||
/*****************************************************************************
|
||||
* idiom1 - HLL procedure prologue; Returns number of instructions matched.
|
||||
* PUSH BP ==> ENTER immed, 0
|
||||
* MOV BP, SP and sets PROC_HLL flag
|
||||
* [SUB SP, immed]
|
||||
* [PUSH SI]
|
||||
* [PUSH DI]
|
||||
* - Second version: Push stack variables and then save BP
|
||||
* PUSH BP
|
||||
* PUSH SI
|
||||
* [PUSH DI]
|
||||
* MOV BP, SP
|
||||
* - Third version: Stack variables
|
||||
* [PUSH SI]
|
||||
* [PUSH DI]
|
||||
****************************************************************************/
|
||||
bool Idiom1::match(iICODE picode)
|
||||
{
|
||||
//uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */
|
||||
//uint8_t regi; /* register of the MOV */
|
||||
if(m_func->flg & PROC_HLL)
|
||||
return false;
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
//int n;
|
||||
m_icodes.clear();
|
||||
m_min_off = 0;
|
||||
/* PUSH BP as first instruction of procedure */
|
||||
if ( (not picode->ll()->testFlags(I)) && picode->ll()->src().regi == rBP)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iPUSH
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
/* MOV BP, SP as next instruction */
|
||||
if ( !picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iMOV ,rBP,rSP) )
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iMOV
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
m_min_off = 2;
|
||||
|
||||
/* Look for SUB SP, immed */
|
||||
if (
|
||||
picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iSUB,rSP)
|
||||
)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iSUB
|
||||
int n = checkStkVars (picode); // find iPUSH si [iPUSH di]
|
||||
for(int i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++); // insert
|
||||
}
|
||||
}
|
||||
|
||||
/* PUSH SI
|
||||
* [PUSH DI]
|
||||
* MOV BP, SP */
|
||||
else
|
||||
{
|
||||
int n = checkStkVars (picode);
|
||||
if (n > 0)
|
||||
{
|
||||
for(int i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
if(picode == m_end)
|
||||
return false;
|
||||
/* Look for MOV BP, SP */
|
||||
if ( picode != m_end &&
|
||||
!picode->ll()->testFlags(I | TARGET | CASE) &&
|
||||
picode->ll()->match(iMOV,rBP,rSP))
|
||||
{
|
||||
m_icodes.push_back(picode);
|
||||
m_min_off = 2 + (n * 2);
|
||||
}
|
||||
else
|
||||
return false; // Cristina: check this please!
|
||||
}
|
||||
else
|
||||
return false; // Cristina: check this please!
|
||||
}
|
||||
}
|
||||
else // push di [push si] / push si [push di]
|
||||
{
|
||||
size_t n = checkStkVars (picode);
|
||||
for(int i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
|
||||
}
|
||||
return !m_icodes.empty();
|
||||
}
|
||||
int Idiom1::action()
|
||||
{
|
||||
for(iICODE ic : m_icodes)
|
||||
{
|
||||
ic->invalidate();
|
||||
}
|
||||
m_func->flg |= PROC_HLL;
|
||||
if(0!=m_min_off)
|
||||
{
|
||||
m_func->args.m_minOff = m_min_off;
|
||||
m_func->flg |= PROC_IS_HLL;
|
||||
}
|
||||
return m_icodes.size();
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "mov_idioms.h"
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 14 - Long uint16_t assign
|
||||
* MOV regL, mem/reg
|
||||
* XOR regH, regH
|
||||
* Eg: MOV ax, di
|
||||
* XOR dx, dx
|
||||
* => MOV dx:ax, di
|
||||
* Note: only the following combinations are allowed:
|
||||
* dx:ax
|
||||
* cx:bx
|
||||
* this is to remove the possibility of making errors in situations
|
||||
* like this:
|
||||
* MOV dx, offH
|
||||
* MOV ax, offL
|
||||
* XOR cx, cx
|
||||
* Found in Borland Turbo C, used for division of unsigned integer
|
||||
* operands.
|
||||
****************************************************************************/
|
||||
|
||||
bool Idiom14::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
/* Check for regL */
|
||||
m_regL = m_icodes[0]->ll()->dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
|
||||
{
|
||||
/* Check for XOR regH, regH */
|
||||
if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I))
|
||||
{
|
||||
m_regH = m_icodes[1]->ll()->dst.regi;
|
||||
if (m_regH == m_icodes[1]->ll()->src().getReg2())
|
||||
{
|
||||
if ((m_regL == rAX) && (m_regH == rDX))
|
||||
return true;
|
||||
if ((m_regL == rBX) && (m_regH == rCX))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom14::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *lhs,*rhs;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, m_regH, m_regL, m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
m_icodes[0]->setRegDU( m_regH, eDEF);
|
||||
rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 13 - uint16_t assign
|
||||
* MOV regL, mem
|
||||
* MOV regH, 0
|
||||
* Eg: MOV al, [bp-2]
|
||||
* MOV ah, 0
|
||||
* => MOV ax, [bp-2]
|
||||
* Found in Borland Turbo C, used for multiplication and division of
|
||||
* uint8_t operands (ie. they need to be extended to words).
|
||||
****************************************************************************/
|
||||
bool Idiom13::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
m_loaded_reg = rUNDEF;
|
||||
eReg regi;
|
||||
|
||||
/* Check for regL */
|
||||
regi = m_icodes[0]->ll()->dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH))
|
||||
{
|
||||
/* Check for MOV regH, 0 */
|
||||
if (m_icodes[1]->ll()->match(iMOV,I) && (m_icodes[1]->ll()->src().getImm2() == 0))
|
||||
{
|
||||
if (m_icodes[1]->ll()->dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
|
||||
{
|
||||
m_loaded_reg=(eReg)(regi - rAL + rAX);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom13::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idReg (m_loaded_reg, 0, &m_func->localId);
|
||||
m_icodes[0]->setRegDU( m_loaded_reg, eDEF);
|
||||
m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
|
||||
rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "neg_idioms.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom11 - Negate long integer
|
||||
* NEG regH
|
||||
* NEG regL
|
||||
* SBB regH, 0
|
||||
* Eg: NEG dx
|
||||
* NEG ax
|
||||
* SBB dx, 0
|
||||
* => dx:ax = - dx:ax
|
||||
* Found in Borland Turbo C.
|
||||
****************************************************************************/
|
||||
bool Idiom11::match (iICODE picode)
|
||||
{
|
||||
const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
|
||||
condId type; /* type of argument */
|
||||
if(distance(picode,m_end)<3)
|
||||
return false;
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]=picode++;
|
||||
type = m_icodes[0]->ll()->idType(DST);
|
||||
if(type==CONSTANT || type == OTHER)
|
||||
return false;
|
||||
/* Check NEG reg/mem
|
||||
* SBB reg/mem, 0*/
|
||||
if (not m_icodes[1]->ll()->match(iNEG) or not m_icodes[2]->ll()->match(iSBB))
|
||||
return false;
|
||||
switch (type)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) &&
|
||||
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off))
|
||||
return true;
|
||||
break;
|
||||
case REGISTER:
|
||||
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi)
|
||||
return true;
|
||||
break;
|
||||
case PARAM:
|
||||
case LOCAL_VAR:
|
||||
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom11::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
m_icodes[2]->invalidate();
|
||||
return 3;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 16: Bitwise negation
|
||||
* NEG reg
|
||||
* SBB reg, reg
|
||||
* INC reg
|
||||
* => ASGN reg, !reg
|
||||
* Eg: NEG ax
|
||||
* SBB ax, ax
|
||||
* INC ax
|
||||
* => ax = !ax
|
||||
* Found in Borland Turbo C when negating bitwise.
|
||||
****************************************************************************/
|
||||
bool Idiom16::match (iICODE picode)
|
||||
{
|
||||
const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
|
||||
if(distance(picode,m_end)<3)
|
||||
return false;
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]=picode++;
|
||||
|
||||
uint8_t regi = m_icodes[0]->ll()->dst.regi;
|
||||
if ((regi >= rAX) && (regi < INDEX_BX_SI))
|
||||
{
|
||||
if (m_icodes[1]->ll()->match(iSBB) && m_icodes[2]->ll()->match(iINC))
|
||||
if ((m_icodes[1]->ll()->dst.regi == (m_icodes[1]->ll()->src().getReg2())) &&
|
||||
m_icodes[1]->ll()->match((eReg)regi) &&
|
||||
m_icodes[2]->ll()->match((eReg)regi))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom16::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId);
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs->clone());
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
m_icodes[2]->invalidate();
|
||||
return 3;
|
||||
}
|
||||
@ -1,170 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "shift_idioms.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom8 - Shift right by 1 (signed long ops)
|
||||
* SAR reg, 1
|
||||
* RCR reg, 1
|
||||
* Eg: SAR dx, 1
|
||||
* RCR ax, 1
|
||||
* => dx:ax = dx:ax >> 1 (dx:ax are signed long)
|
||||
* Found in Microsoft C code for long signed variable shift right.
|
||||
****************************************************************************/
|
||||
bool Idiom8::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if ( m_icodes[1]->ll()->match(iRCR,I) &&
|
||||
(m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom8::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
eReg regH,regL;
|
||||
regH=m_icodes[0]->ll()->dst.regi;
|
||||
regL=m_icodes[1]->ll()->dst.regi;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
m_icodes[0]->setRegDU( regL, USE_DEF);
|
||||
|
||||
rhs = COND_EXPR::idKte(1,2);
|
||||
expr = COND_EXPR::boolOp(lhs, rhs, SHR);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom 15 - Shift left by n
|
||||
* SHL reg, 1
|
||||
* SHL reg, 1
|
||||
* [...]
|
||||
* [SHL reg, 1]
|
||||
* Eg: SHL ax, 1
|
||||
* SHL ax, 1
|
||||
* => ax = ax << 2
|
||||
* Found in Borland Turbo C code to index an array (array multiplication)
|
||||
****************************************************************************/
|
||||
bool Idiom15::match(iICODE pIcode)
|
||||
{
|
||||
uint8_t regi;
|
||||
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
/* Match SHL reg, 1 */
|
||||
if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1))
|
||||
return false;
|
||||
m_icodes.clear();
|
||||
regi = pIcode->ll()->dst.regi;
|
||||
m_icodes.push_back(pIcode++);
|
||||
while( (pIcode!=m_end) and
|
||||
pIcode->ll()->match(iSHL,(eReg)regi,I) and
|
||||
(pIcode->ll()->src().getImm2() == 1) )
|
||||
{
|
||||
m_icodes.push_back(pIcode++);
|
||||
}
|
||||
return m_icodes.size()>1;
|
||||
}
|
||||
|
||||
int Idiom15::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs,*_exp;
|
||||
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi,
|
||||
m_icodes[0]->ll()->getFlag() & NO_SRC_B,
|
||||
&m_func->localId);
|
||||
rhs = COND_EXPR::idKte (m_icodes.size(), 2);
|
||||
_exp = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
m_icodes[0]->setAsgn(lhs, _exp);
|
||||
for (size_t i=1; i<m_icodes.size()-1; ++i)
|
||||
{
|
||||
m_icodes[i]->invalidate();
|
||||
}
|
||||
return m_icodes.size();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom12 - Shift left long by 1
|
||||
* SHL reg, 1
|
||||
* RCL reg, 1
|
||||
* Eg: SHL ax, 1
|
||||
* RCL dx, 1
|
||||
* => dx:ax = dx:ax << 1
|
||||
* Found in Borland Turbo C code for long variable shift left.
|
||||
****************************************************************************/
|
||||
bool Idiom12::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCL,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom12::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
eReg regH,regL;
|
||||
regL=m_icodes[0]->ll()->dst.regi;
|
||||
regH=m_icodes[1]->ll()->dst.regi;
|
||||
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
m_icodes[0]->setRegDU( regH, USE_DEF);
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom9 - Shift right by 1 (unsigned long ops)
|
||||
* SHR reg, 1
|
||||
* RCR reg, 1
|
||||
* Eg: SHR dx, 1
|
||||
* RCR ax, 1
|
||||
* => dx:ax = dx:ax >> 1 (dx:ax are unsigned long)
|
||||
* Found in Microsoft C code for long unsigned variable shift right.
|
||||
****************************************************************************/
|
||||
bool Idiom9::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCR,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom9::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
eReg regH,regL;
|
||||
regL=m_icodes[1]->ll()->dst.regi;
|
||||
regH=m_icodes[0]->ll()->dst.regi;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
m_icodes[0]->setRegDU(regL, USE_DEF);
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, SHR);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include "xor_idioms.h"
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom21 - Assign long kte with high part zero
|
||||
* XOR regH, regH
|
||||
* MOV regL, kte
|
||||
* => regH:regL = kte
|
||||
* Eg: XOR dx, dx
|
||||
* MOV ax, 3
|
||||
* => dx:ax = 3
|
||||
* Note: only the following valid combinations are available:
|
||||
* dx:ax
|
||||
* cx:bx
|
||||
* Found in Borland Turbo C code.
|
||||
****************************************************************************/
|
||||
bool Idiom21::match (iICODE picode)
|
||||
{
|
||||
LLOperand *dst, *src;
|
||||
if(distance(picode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=picode++;
|
||||
m_icodes[1]=picode++;
|
||||
|
||||
if (not m_icodes[1]->ll()->testFlags(I))
|
||||
return false;
|
||||
|
||||
dst = &m_icodes[0]->ll()->dst;
|
||||
src = &m_icodes[0]->ll()->src();
|
||||
if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI))
|
||||
{
|
||||
if ((dst->getReg2() == rDX) && m_icodes[1]->ll()->match(rAX))
|
||||
return true;
|
||||
if ((dst->getReg2() == rCX) && m_icodes[1]->ll()->match(rBX))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom21::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::idKte (m_icodes[1]->ll()->src().getImm2() , 4);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[0]->du.use = 0; /* clear register used in iXOR */
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom7 - Assign zero
|
||||
* XOR reg/stackOff, reg/stackOff
|
||||
* Eg: XOR ax, ax
|
||||
* => ax = 0
|
||||
* Found in Borland Turbo C and Microsoft C code.
|
||||
****************************************************************************/
|
||||
bool Idiom7::match(iICODE picode)
|
||||
{
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
const LLOperand *dst, *src;
|
||||
m_icode=picode;
|
||||
dst = &picode->ll()->dst;
|
||||
src = &picode->ll()->src();
|
||||
if (dst->regi == 0) /* global variable */
|
||||
{
|
||||
if ((dst->segValue == src->segValue) && (dst->off == src->off))
|
||||
return true;
|
||||
}
|
||||
else if (dst->regi < INDEX_BX_SI) /* register */
|
||||
{
|
||||
if (dst->regi == src->regi)
|
||||
return true;
|
||||
}
|
||||
else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEX_BP)) /* offset from BP */
|
||||
{
|
||||
if ((dst->off == src->off) && (dst->seg == src->seg) && (dst->regi == src->regi))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom7::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
|
||||
rhs = COND_EXPR::idKte (0, 2);
|
||||
m_icode->setAsgn(lhs, rhs);
|
||||
m_icode->du.use = 0; /* clear register used in iXOR */
|
||||
m_icode->ll()->setFlags(I);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* idiom10 - Jump if not equal to 0
|
||||
* OR reg, reg
|
||||
* JNE labX
|
||||
* Eg: OR ax, ax
|
||||
* JNE labX
|
||||
* => CMP reg 0
|
||||
* JNE labX
|
||||
* This instruction is NOT converted into the equivalent high-level
|
||||
* instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if
|
||||
* it forms part of a long register conditional test. It is therefore
|
||||
* modified to simplify the analysis.
|
||||
* Found in Borland Turbo C.
|
||||
****************************************************************************/
|
||||
bool Idiom10::match(iICODE pIcode)
|
||||
{
|
||||
if(distance(pIcode,m_end)<2)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
/* Check OR reg, reg */
|
||||
if (not m_icodes[0]->ll()->testFlags(I) &&
|
||||
m_icodes[0]->ll()->src().isReg() &&
|
||||
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->dst.getReg2()))
|
||||
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom10::action()
|
||||
{
|
||||
m_icodes[0]->ll()->set(iCMP,I);
|
||||
m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0));
|
||||
m_icodes[0]->du.def = 0;
|
||||
m_icodes[0]->du1.numRegsDef = 0;
|
||||
return 2;
|
||||
|
||||
}
|
||||
431
src/locident.cpp
431
src/locident.cpp
@ -5,113 +5,127 @@
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include "locident.h"
|
||||
#include "dcc.h"
|
||||
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
|
||||
{
|
||||
return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h);
|
||||
}
|
||||
|
||||
|
||||
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
|
||||
{
|
||||
name[0]=0;
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
}
|
||||
ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
|
||||
{
|
||||
name[0]=0;
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=f;
|
||||
}
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define LOCAL_ID_DELTA 25
|
||||
#define IDX_ARRAY_DELTA 5
|
||||
|
||||
|
||||
void insertIdx (IDX_ARRAY *list, Int idx)
|
||||
/* Inserts the new index at the end of the list. If there is need to
|
||||
* allocate extra storage, it does so. */
|
||||
{
|
||||
if (list->csym == list->alloc)
|
||||
{
|
||||
list->alloc += IDX_ARRAY_DELTA;
|
||||
list->idx = (Int*)reallocVar(list->idx, list->alloc * sizeof(Int));
|
||||
memset (&list->idx[list->csym], 0, IDX_ARRAY_DELTA * sizeof(Int));
|
||||
}
|
||||
list->idx[list->csym] = idx;
|
||||
list->csym++;
|
||||
}
|
||||
|
||||
|
||||
static boolT inList (IDX_ARRAY *list, Int idx)
|
||||
/* Returns whether idx is in the list array or not */
|
||||
{ Int i;
|
||||
|
||||
for (i = 0; i < list->csym; i++)
|
||||
if (list->idx[i] == idx)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void newIdent (LOCAL_ID *locSym, hlType t, frameType f)
|
||||
/* Creates a new identifier node of type t and returns it.
|
||||
* Arguments: locSym : local long symbol table
|
||||
* t : type of LONG identifier
|
||||
* f : frame where this variable is located
|
||||
* ix : index into icode array where this var is used */
|
||||
void LOCAL_ID::newIdent(hlType t, frameType f)
|
||||
{
|
||||
ID newid(t,f);
|
||||
id_arr.push_back(newid);
|
||||
if (locSym->csym == locSym->alloc)
|
||||
{
|
||||
locSym->alloc += LOCAL_ID_DELTA;
|
||||
locSym->id = (ID*)reallocVar(locSym->id, locSym->alloc * sizeof(ID));
|
||||
memset (&locSym->id[locSym->csym], 0, LOCAL_ID_DELTA * sizeof(ID));
|
||||
}
|
||||
locSym->id[locSym->csym].type = t;
|
||||
locSym->id[locSym->csym].loc = f;
|
||||
locSym->csym++;
|
||||
}
|
||||
|
||||
|
||||
Int newByteWordRegId (LOCAL_ID *locSym, hlType t, byte regi)
|
||||
/* Creates a new register identifier node of TYPE_BYTE_(UN)SIGN or
|
||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
||||
int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
|
||||
{
|
||||
int idx;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
|
||||
return ((el.type == t) && (el.id.regi == regi));
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin();
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
if ((locSym->id[idx].type == t) &&
|
||||
(locSym->id[idx].id.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in table, create new identifier */
|
||||
newIdent (t, REG_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.regi = regi;
|
||||
newIdent (locSym, t, REG_FRAME);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
static void flagByteWordId (LOCAL_ID *locsym, Int off)
|
||||
/* Flags the entry associated with the offset off to illegal, as this
|
||||
* offset is part of a long stack variable.
|
||||
* Note: it is easier enough to remove this entry by moving the rest of
|
||||
* the array 1 position. The problem is that indexes into this
|
||||
* array have already been saved in several positions; therefore,
|
||||
* flagging this entry as illegal is all that can be done. */
|
||||
void LOCAL_ID::flagByteWordId (int off)
|
||||
{
|
||||
int idx;
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
|
||||
//if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
|
||||
if ((en.typeBitsize()<=16) &&
|
||||
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if(found==id_arr.end())
|
||||
{ Int idx;
|
||||
|
||||
for (idx = 0; idx < locsym->csym; idx++)
|
||||
{
|
||||
printf("No entry to flag as invalid in LOCAL_ID::flagByteWordId \n");
|
||||
return;
|
||||
if (((locsym->id[idx].type == TYPE_WORD_SIGN) ||
|
||||
(locsym->id[idx].type == TYPE_BYTE_SIGN)) &&
|
||||
(locsym->id[idx].id.bwId.off == off) &&
|
||||
(locsym->id[idx].id.bwId.regOff == 0))
|
||||
{
|
||||
locsym->id[idx].illegal = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
found->illegal = true;
|
||||
}
|
||||
|
||||
|
||||
Int newByteWordStkId (LOCAL_ID *locSym, hlType t, Int off, byte regOff)
|
||||
/* Creates a new stack identifier node of TYPE_BYTE_(UN)SIGN or
|
||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
||||
int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
|
||||
{
|
||||
int idx;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
|
||||
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin(); //return Index to found element
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
if ((locSym->id[idx].id.bwId.off == off) &&
|
||||
(locSym->id[idx].id.bwId.regOff == regOff))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in table, create new identifier */
|
||||
newIdent (t, STK_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwId.regOff = regOff;
|
||||
id_arr[idx].id.bwId.off = off;
|
||||
newIdent (locSym, t, STK_FRAME);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.bwId.regOff = regOff;
|
||||
locSym->id[idx].id.bwId.off = off;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
Int newIntIdxId (LOCAL_ID *locSym, int16 seg, int16 off, byte regi,
|
||||
Int ix, hlType t)
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new global identifier node of type
|
||||
* TYPE_WORD_(UN)SIGN and returns the index to this new entry.
|
||||
@ -121,196 +135,186 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
|
||||
* regi: indexed register into global variable
|
||||
* ix: index into icode array
|
||||
* t: HIGH_LEVEL type */
|
||||
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t)
|
||||
{
|
||||
int idx;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) &&
|
||||
(id_arr[idx].id.bwGlb.off == off) &&
|
||||
(id_arr[idx].id.bwGlb.regi == regi))
|
||||
(locSym->id[idx].id.bwGlb.seg == seg) &&
|
||||
(locSym->id[idx].id.bwGlb.off == off) &&
|
||||
(locSym->id[idx].id.bwGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwGlb.seg = seg;
|
||||
id_arr[idx].id.bwGlb.off = off;
|
||||
id_arr[idx].id.bwGlb.regi = regi;
|
||||
newIdent (locSym, t, GLB_FRAME);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.bwGlb.seg = seg;
|
||||
locSym->id[idx].id.bwGlb.off = off;
|
||||
locSym->id[idx].id.bwGlb.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
Int newLongRegId (LOCAL_ID *locSym, hlType t, byte regH, byte regL, Int ix)
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new register identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
|
||||
{
|
||||
size_t idx;
|
||||
//iICODE ix_;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
ID &entry(id_arr[idx]);
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(entry.id.longId.h == regH) &&
|
||||
(entry.id.longId.l == regL))
|
||||
(locSym->id[idx].id.longId.h == regH) &&
|
||||
(locSym->id[idx].id.longId.l == regL))
|
||||
{
|
||||
/* Check for occurrence in the list */
|
||||
if (entry.idx.inList(ix_))
|
||||
if (inList (&locSym->id[idx].idx, ix))
|
||||
return (idx);
|
||||
else
|
||||
{
|
||||
/* Insert icode index in list */
|
||||
entry.idx.push_back(ix_);
|
||||
//entry.idx.insert(ix_);
|
||||
insertIdx (&locSym->id[idx].idx, ix);
|
||||
return (idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, REG_FRAME);
|
||||
id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longId.h = regH;
|
||||
id_arr[idx].id.longId.l = regL;
|
||||
newIdent (locSym, t, REG_FRAME);
|
||||
insertIdx (&locSym->id[locSym->csym-1].idx, ix);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.longId.h = regH;
|
||||
locSym->id[idx].id.longId.l = regL;
|
||||
return (idx);
|
||||
}
|
||||
/* Returns an identifier conditional expression node of type TYPE_LONG or
|
||||
* TYPE_WORD_SIGN */
|
||||
COND_EXPR * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
|
||||
{
|
||||
return COND_EXPR::idID(retVal,this,ix_);
|
||||
}
|
||||
|
||||
|
||||
static Int newLongGlbId (LOCAL_ID *locSym, int16 seg, int16 offH, int16 offL,
|
||||
Int ix, hlType t)
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new global identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
|
||||
{
|
||||
size_t idx;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL))
|
||||
(locSym->id[idx].id.longGlb.seg == seg) &&
|
||||
(locSym->id[idx].id.longGlb.offH == offH) &&
|
||||
(locSym->id[idx].id.longGlb.offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
newIdent (locSym, t, GLB_FRAME);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.longGlb.seg = seg;
|
||||
locSym->id[idx].id.longGlb.offH = offH;
|
||||
locSym->id[idx].id.longGlb.offL = offL;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
static Int newLongIdxId (LOCAL_ID *locSym, int16 seg, int16 offH, int16 offL,
|
||||
byte regi, Int ix, hlType t)
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new global identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
int LOCAL_ID::newLongIdx( int16_t seg, int16_t offH, int16_t offL,uint8_t regi, hlType t)
|
||||
{
|
||||
size_t idx;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL) &&
|
||||
(id_arr[idx].id.longGlb.regi == regi))
|
||||
(locSym->id[idx].id.longGlb.seg == seg) &&
|
||||
(locSym->id[idx].id.longGlb.offH == offH) &&
|
||||
(locSym->id[idx].id.longGlb.offL == offL) &&
|
||||
(locSym->id[idx].id.longGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
id_arr[idx].id.longGlb.regi = regi;
|
||||
newIdent (locSym, t, GLB_FRAME);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.longGlb.seg = seg;
|
||||
locSym->id[idx].id.longGlb.offH = offH;
|
||||
locSym->id[idx].id.longGlb.offL = offL;
|
||||
locSym->id[idx].id.longGlb.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
Int newLongStkId (LOCAL_ID *locSym, hlType t, Int offH, Int offL)
|
||||
/* Creates a new stack identifier node of type TYPE_LONG_(UN)SIGN.
|
||||
* Returns the index to this entry. */
|
||||
int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
|
||||
{
|
||||
size_t idx;
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (idx = 0; idx < locSym->csym; idx++)
|
||||
{
|
||||
if ((id_arr[idx].type == t) &&
|
||||
(id_arr[idx].id.longStkId.offH == offH) &&
|
||||
(id_arr[idx].id.longStkId.offL == offL))
|
||||
if ((locSym->id[idx].type == t) &&
|
||||
(locSym->id[idx].id.longStkId.offH == offH) &&
|
||||
(locSym->id[idx].id.longStkId.offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table; flag as invalid offH and offL */
|
||||
flagByteWordId (offH);
|
||||
flagByteWordId (offL);
|
||||
flagByteWordId (locSym, offH);
|
||||
flagByteWordId (locSym, offL);
|
||||
|
||||
/* Create new identifier */
|
||||
newIdent (t, STK_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longStkId.offH = offH;
|
||||
id_arr[idx].id.longStkId.offL = offL;
|
||||
newIdent (locSym, t, STK_FRAME);
|
||||
idx = locSym->csym - 1;
|
||||
locSym->id[idx].id.longStkId.offH = offH;
|
||||
locSym->id[idx].id.longStkId.offL = offL;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
Int newLongId (LOCAL_ID *locSym, opLoc sd, PICODE pIcode, hlFirst f, Int ix,
|
||||
operDu du, Int off)
|
||||
/* Returns the index to an appropriate long identifier.
|
||||
* Note: long constants should be checked first and stored as a long integer
|
||||
* number in an expression record. */
|
||||
int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset)
|
||||
{
|
||||
size_t idx;
|
||||
const LLOperand *pmH, *pmL;
|
||||
LLInst &p_ll(*pIcode->ll());
|
||||
{ Int idx;
|
||||
PMEM pmH, pmL;
|
||||
|
||||
if (f == LOW_FIRST)
|
||||
{
|
||||
pmL = p_ll.get(sd);
|
||||
pmH = atOffset.get(sd);
|
||||
pmL = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||
pmH = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
|
||||
}
|
||||
else /* HIGH_FIRST */
|
||||
{
|
||||
pmL = atOffset.get(sd);
|
||||
pmH = p_ll.get(sd);
|
||||
pmH = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||
pmL = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
|
||||
}
|
||||
|
||||
if (pmL->regi == 0) /* global variable */
|
||||
idx = newLongGlb(pmH->segValue, pmH->off, pmL->off, TYPE_LONG_SIGN);
|
||||
idx = newLongGlbId (locSym, pmH->segValue, pmH->off, pmL->off, ix,
|
||||
TYPE_LONG_SIGN);
|
||||
|
||||
else if (pmL->regi < INDEX_BX_SI) /* register */
|
||||
else if (pmL->regi < INDEXBASE) /* register */
|
||||
{
|
||||
idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
|
||||
idx = newLongRegId (locSym, TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
|
||||
if (f == HIGH_FIRST)
|
||||
pIcode->setRegDU( pmL->regi, du); /* low part */
|
||||
setRegDU (pIcode, pmL->regi, du); /* low part */
|
||||
else
|
||||
pIcode->setRegDU( pmH->regi, du); /* high part */
|
||||
setRegDU (pIcode, pmH->regi, du); /* high part */
|
||||
}
|
||||
|
||||
else if (pmL->off) { /* offset */
|
||||
if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */
|
||||
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
|
||||
else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */
|
||||
if ((pmL->seg == rSS) && (pmL->regi == INDEXBASE + 6)) /* idx on bp */
|
||||
idx = newLongStkId (locSym, TYPE_LONG_SIGN, pmH->off, pmL->off);
|
||||
else if ((pmL->seg == rDS) && (pmL->regi == INDEXBASE + 7)) /* bx */
|
||||
{ /* glb var indexed on bx */
|
||||
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
|
||||
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
|
||||
pIcode->setRegDU( rBX, eUSE);
|
||||
idx = newLongIdxId (locSym, pmH->segValue, pmH->off, pmL->off,
|
||||
rBX, ix, TYPE_LONG_SIGN);
|
||||
setRegDU (pIcode, rBX, E_USE);
|
||||
}
|
||||
else /* idx <> bp, bx */
|
||||
printf ("long not supported, idx <> bp\n");
|
||||
@ -323,6 +327,8 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
}
|
||||
|
||||
|
||||
boolT checkLongEq (LONG_STKID_TYPE longId, PICODE pIcode, Int i, Int idx,
|
||||
PPROC pProc, COND_EXPR **rhs, COND_EXPR **lhs, Int off)
|
||||
/* Checks whether the long stack identifier is equivalent to the source or
|
||||
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
|
||||
* icodes at present). If so, returns the rhs and lhs of this instruction.
|
||||
@ -332,36 +338,34 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
* idx : idx into icode array
|
||||
* pProc : ptr to current procedure record
|
||||
* rhs, lhs : return expressions if successful. */
|
||||
boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
|
||||
{
|
||||
/* pointers to LOW_LEVEL icodes */
|
||||
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
|
||||
{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */
|
||||
|
||||
pmHdst = &pIcode->ll()->dst;
|
||||
pmLdst = &atOffset.dst;
|
||||
pmHsrc = &pIcode->ll()->src();
|
||||
pmLsrc = &atOffset.src();
|
||||
pmHdst = &pIcode->ic.ll.dst;
|
||||
pmLdst = &(pIcode+off)->ic.ll.dst;
|
||||
pmHsrc = &pIcode->ic.ll.src;
|
||||
pmLsrc = &(pIcode+off)->ic.ll.src;
|
||||
|
||||
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (i);
|
||||
|
||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
||||
{
|
||||
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
}
|
||||
return true;
|
||||
*lhs = idCondExpLongIdx (i);
|
||||
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
|
||||
*rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
|
||||
idx, E_USE, off);
|
||||
return (TRUE);
|
||||
}
|
||||
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
||||
asgn.rhs = COND_EXPR::idLongIdx (i);
|
||||
return true;
|
||||
*lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
|
||||
E_DEF, off);
|
||||
*rhs = idCondExpLongIdx (i);
|
||||
return (TRUE);
|
||||
}
|
||||
return false;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
boolT checkLongRegEq (LONGID_TYPE longId, PICODE pIcode, Int i, Int idx,
|
||||
PPROC pProc, COND_EXPR **rhs, COND_EXPR **lhs, Int off)
|
||||
/* Checks whether the long stack identifier is equivalent to the source or
|
||||
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
|
||||
* icodes at present). If so, returns the rhs and lhs of this instruction.
|
||||
@ -371,45 +375,40 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro
|
||||
* idx : idx into icode array
|
||||
* pProc : ptr to current procedure record
|
||||
* rhs, lhs : return expressions if successful. */
|
||||
boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
|
||||
Function * pProc, Assignment &asgn, LLInst &atOffset)
|
||||
{
|
||||
/* pointers to LOW_LEVEL icodes */
|
||||
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
|
||||
{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */
|
||||
|
||||
pmHdst = &pIcode->ll()->dst;
|
||||
pmLdst = &atOffset.dst;
|
||||
pmHsrc = &pIcode->ll()->src();
|
||||
pmLsrc = &atOffset.src();
|
||||
pmHdst = &pIcode->ic.ll.dst;
|
||||
pmLdst = &(pIcode+off)->ic.ll.dst;
|
||||
pmHsrc = &pIcode->ic.ll.src;
|
||||
pmLsrc = &(pIcode+off)->ic.ll.src;
|
||||
|
||||
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (i);
|
||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
||||
{
|
||||
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
}
|
||||
return true;
|
||||
*lhs = idCondExpLongIdx (i);
|
||||
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
|
||||
*rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
|
||||
idx, E_USE, off);
|
||||
return (TRUE);
|
||||
}
|
||||
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
|
||||
asgn.rhs = COND_EXPR::idLongIdx (i);
|
||||
return true;
|
||||
*lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
|
||||
E_DEF, off);
|
||||
*rhs = idCondExpLongIdx (i);
|
||||
return (TRUE);
|
||||
}
|
||||
return false;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
byte otherLongRegi (byte regi, Int idx, LOCAL_ID *locTbl)
|
||||
/* Given an index into the local identifier table for a long register
|
||||
* variable, determines whether regi is the high or low part, and returns
|
||||
* the other part */
|
||||
eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
{
|
||||
ID *id;
|
||||
{ ID *id;
|
||||
|
||||
id = &locTbl->id_arr[idx];
|
||||
id = &locTbl->id[idx];
|
||||
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
|
||||
(id->type == TYPE_LONG_UNSIGN)))
|
||||
{
|
||||
@ -418,33 +417,37 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
else if (id->id.longId.l == regi)
|
||||
return (id->id.longId.h);
|
||||
}
|
||||
return rUNDEF; // Cristina: please check this!
|
||||
return 0; // Cristina: please check this!
|
||||
}
|
||||
|
||||
|
||||
void propLongId (LOCAL_ID *locid, byte regL, byte regH, char *name)
|
||||
/* Checks if the registers regL and regH have been used independently in
|
||||
* the local identifier table. If so, macros for these registers are
|
||||
* placed in the local identifier table, as these registers belong to a
|
||||
* long register identifier. */
|
||||
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
|
||||
{
|
||||
for (ID &rid : id_arr)
|
||||
{ Int i;
|
||||
ID *id;
|
||||
|
||||
for (i = 0; i < locid->csym; i++)
|
||||
{
|
||||
if (rid.typeBitsize()!=16)
|
||||
continue;
|
||||
if ( (rid.id.regi != regL) and (rid.id.regi != regH) )
|
||||
continue;
|
||||
// otherwise at least 1 is ok
|
||||
rid.name = name;
|
||||
rid.hasMacro = true;
|
||||
rid.illegal = true;
|
||||
if (rid.id.regi == regL)
|
||||
id = &locid->id[i];
|
||||
if ((id->type == TYPE_WORD_SIGN) || (id->type == TYPE_WORD_UNSIGN))
|
||||
{
|
||||
strcpy (rid.macro, "LO");
|
||||
if (id->id.regi == regL)
|
||||
{
|
||||
strcpy (id->name, name);
|
||||
strcpy (id->macro, "LO");
|
||||
id->hasMacro = TRUE;
|
||||
id->illegal = TRUE;
|
||||
}
|
||||
else // if (rid.id.regi == regH)
|
||||
else if (id->id.regi == regH)
|
||||
{
|
||||
strcpy (rid.macro, "HI");
|
||||
strcpy (id->name, name);
|
||||
strcpy (id->macro, "HI");
|
||||
id->hasMacro = TRUE;
|
||||
id->illegal = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,111 +0,0 @@
|
||||
#include <cassert>
|
||||
#include "machine_x86.h"
|
||||
// Index registers **** temp solution
|
||||
static const std::string regNames[] = {
|
||||
"undef",
|
||||
"ax", "cx", "dx", "bx",
|
||||
"sp", "bp", "si", "di",
|
||||
"es", "cs", "ss", "ds",
|
||||
"al", "cl", "dl", "bl",
|
||||
"ah", "ch", "dh", "bh",
|
||||
"tmp",
|
||||
"bx+si", "bx+di", "bp+si", "bp+di",
|
||||
"si", "di", "bp", "bx"
|
||||
};
|
||||
|
||||
/* uint8_t and uint16_t registers */
|
||||
Machine_X86::Machine_X86()
|
||||
{
|
||||
static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG,
|
||||
"Reg count not equal number of strings");
|
||||
}
|
||||
|
||||
const std::string &Machine_X86::regName(eReg r)
|
||||
{
|
||||
assert(r<(sizeof(regNames)/sizeof(std::string)));
|
||||
return regNames[r];
|
||||
}
|
||||
|
||||
static const std::string szOps[] =
|
||||
{
|
||||
"CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND",
|
||||
"BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP",
|
||||
"CMPS", "REPNE CMPS","REPE CMPS","DAA", "DAS", "DEC", "DIV", "ENTER",
|
||||
"ESC", "HLT", "IDIV", "IMUL", "IN", "INC", "INS", "REP INS",
|
||||
"INT", "IRET", "JB", "JBE", "JAE", "JA", "JE", "JNE",
|
||||
"JL", "JGE", "JLE", "JG", "JS", "JNS", "JO", "JNO",
|
||||
"JP", "JNP", "JCXZ", "JMP", "JMP", "LAHF", "LDS", "LEA",
|
||||
"LEAVE","LES", "LOCK", "LODS", "REP LODS", "LOOP", "LOOPE","LOOPNE",
|
||||
"MOV", "MOVS", "REP MOVS", "MUL", "NEG", "NOT", "OR", "OUT",
|
||||
"OUTS", "REP OUTS", "POP", "POPA", "POPF", "PUSH", "PUSHA","PUSHF",
|
||||
"RCL", "RCR", "ROL", "ROR", "RET", "RETF", "SAHF", "SAR",
|
||||
"SHL", "SHR", "SBB", "SCAS", "REPNE SCAS","REPE SCAS", "CWD", "STC",
|
||||
"STD", "STI", "STOS", "REP STOS", "SUB", "TEST", "WAIT", "XCHG",
|
||||
"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
|
||||
};
|
||||
/* The following opcodes are for mod != 3 */
|
||||
static std::string szFlops1[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
|
||||
"FLD", "???", "FST", "???", "FLDENV","FLDCW", "FSTENV","FSTSW", /* 08 */
|
||||
"FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 10 */
|
||||
"FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */
|
||||
"FLD", "FLD", "FST", "FSTP", "FRESTOR","???", "FSAVE", "FSTSW", /* 28 */
|
||||
"FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 30 */
|
||||
"FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
|
||||
};
|
||||
/* The following opcodes are for mod == 3 */
|
||||
static std::string szFlops2[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
|
||||
"FLD", "FXCH", "FNOP", "???", "", "", "", "", /* 08 */
|
||||
"FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "", "FIDIV", "FIDIVR", /* 10 */
|
||||
"FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */
|
||||
"FFREE", "FSTP", "FST", "???", "FUCOM", "FUCOMP","???", "???", /* 28 */
|
||||
"FADDP", "FMULP", "FICOM","", "FSUBRP","FISUBR","FDIVRP","FDIVP", /* 30 */
|
||||
"FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */
|
||||
};
|
||||
|
||||
const std::string &Machine_X86::opcodeName(unsigned r)
|
||||
{
|
||||
assert(r<(sizeof(szOps)/sizeof(std::string)));
|
||||
return szOps[r];
|
||||
}
|
||||
const std::string &Machine_X86::floatOpName(unsigned r)
|
||||
{
|
||||
if(r>=(sizeof(szFlops1)/sizeof(std::string)))
|
||||
{
|
||||
r-= (sizeof(szFlops1)/sizeof(std::string));
|
||||
assert(r<(sizeof(szFlops2)/sizeof(std::string)));
|
||||
return szFlops2[r];
|
||||
}
|
||||
return szFlops1[r];
|
||||
}
|
||||
|
||||
bool Machine_X86::physicalReg(eReg r)
|
||||
{
|
||||
return (r>=rAX) && (r<rTMP);
|
||||
}
|
||||
bool Machine_X86::isMemOff(eReg r)
|
||||
{
|
||||
return r == 0 || r >= INDEX_BX_SI;
|
||||
}
|
||||
//TODO: Move these to Machine_X86
|
||||
eReg Machine_X86::subRegH(eReg reg)
|
||||
{
|
||||
return eReg((int)reg + (int)rAH-(int)rAX);
|
||||
}
|
||||
eReg Machine_X86::subRegL(eReg reg)
|
||||
{
|
||||
return eReg((int)reg + (int)rAL-(int)rAX);
|
||||
}
|
||||
bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent)
|
||||
{
|
||||
if ((parent < rAX) || (parent > rBX))
|
||||
return false; // only AX -> BX are coverede by subregisters
|
||||
return ((reg==subRegH(parent)) || (reg == subRegL(parent)));
|
||||
}
|
||||
1177
src/parser.cpp
1177
src/parser.cpp
File diff suppressed because it is too large
Load Diff
395
src/perfhlib.cpp
395
src/perfhlib.cpp
@ -11,21 +11,32 @@
|
||||
|
||||
/* Private data structures */
|
||||
|
||||
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
static int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
static int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
static int SetSize; /* Size of the char set */
|
||||
static char SetMin; /* First char in the set */
|
||||
static int NumVert; /* c times NumEntry */
|
||||
|
||||
static word *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static word *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
|
||||
static int *graphNode; /* The array of edges */
|
||||
static int *graphNext; /* Linked list of edges */
|
||||
static int *graphFirst;/* First edge at a vertex */
|
||||
|
||||
static short *g; /* g[] */
|
||||
|
||||
static int numEdges; /* An edge counter */
|
||||
//static bool *visited; /* Array of bools: whether visited */
|
||||
static bool *visited; /* Array of bools: whether visited */
|
||||
|
||||
/* Private prototypes */
|
||||
static void initGraph(void);
|
||||
static void addToGraph(int e, int v1, int v2);
|
||||
static bool isCycle(void);
|
||||
static void duplicateKeys(int v1, int v2);
|
||||
PatternHasher g_pattern_hasher;
|
||||
|
||||
void
|
||||
PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
int _NumVert)
|
||||
{
|
||||
/* These parameters are stored in statics so as to obviate the need for
|
||||
@ -39,32 +50,316 @@ PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
NumVert = _NumVert;
|
||||
|
||||
/* Allocate the variable sized tables etc */
|
||||
T1base = new uint16_t [EntryLen * SetSize];
|
||||
T2base = new uint16_t [EntryLen * SetSize];
|
||||
graphNode = new int [NumEntry*2 + 1];
|
||||
graphNext = new int [NumEntry*2 + 1];
|
||||
graphFirst = new int [NumVert + 1];
|
||||
g = new short [NumVert + 1];
|
||||
// visited = new bool [NumVert + 1];
|
||||
if ((T1base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((T2base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((graphNode = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphNext = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphFirst = (int *)malloc((NumVert + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((g = (short *)malloc((NumVert+1) * sizeof(short))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((visited = (bool *)malloc((NumVert+1) * sizeof(bool))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
return;
|
||||
|
||||
BadAlloc:
|
||||
printf("Could not allocate memory\n");
|
||||
hashCleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void PatternHasher::cleanup(void)
|
||||
void
|
||||
hashCleanup(void)
|
||||
{
|
||||
/* Free the storage for variable sized tables etc */
|
||||
delete [] T1base;
|
||||
delete [] T2base;
|
||||
delete [] graphNode;
|
||||
delete [] graphNext;
|
||||
delete [] graphFirst;
|
||||
delete [] g;
|
||||
// delete [] visited;
|
||||
if (T1base) free(T1base);
|
||||
if (T2base) free(T2base);
|
||||
if (graphNode) free(graphNode);
|
||||
if (graphNext) free(graphNext);
|
||||
if (graphFirst) free(graphFirst);
|
||||
if (g) free(g);
|
||||
}
|
||||
|
||||
int PatternHasher::hash(uint8_t *string)
|
||||
void
|
||||
map(void)
|
||||
{
|
||||
uint16_t u, v;
|
||||
int i, j, c;
|
||||
word f1, f2;
|
||||
bool cycle;
|
||||
byte *keys;
|
||||
|
||||
c = 0;
|
||||
|
||||
do
|
||||
{
|
||||
initGraph();
|
||||
cycle = FALSE;
|
||||
|
||||
/* Randomly generate T1 and T2 */
|
||||
for (i=0; i < SetSize*EntryLen; i++)
|
||||
{
|
||||
T1base[i] = rand() % NumVert;
|
||||
T2base[i] = rand() % NumVert;
|
||||
}
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
f1 = 0; f2 = 0;
|
||||
getKey(i, &keys);
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
T2 = T2base + j * SetSize;
|
||||
f1 += T1[keys[j] - SetMin];
|
||||
f2 += T2[keys[j] - SetMin];
|
||||
}
|
||||
f1 %= (word)NumVert;
|
||||
f2 %= (word)NumVert;
|
||||
if (f1 == f2)
|
||||
{
|
||||
/* A self loop. Reject! */
|
||||
printf("Self loop on vertex %d!\n", f1);
|
||||
cycle = TRUE;
|
||||
break;
|
||||
}
|
||||
addToGraph(numEdges++, f1, f2);
|
||||
}
|
||||
if (cycle || (cycle = isCycle())) /* OK - is there a cycle? */
|
||||
{
|
||||
printf("Iteration %d\n", ++c);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (/* there is a cycle */ 1);
|
||||
|
||||
}
|
||||
|
||||
/* Initialise the graph */
|
||||
static void
|
||||
initGraph(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i <= NumVert; i++)
|
||||
{
|
||||
graphFirst[i] = 0;
|
||||
}
|
||||
|
||||
for (i= -NumEntry; i <= NumEntry; i++)
|
||||
{
|
||||
/* No need to init graphNode[] as they will all be filled by successive
|
||||
calls to addToGraph() */
|
||||
graphNext[NumEntry+i] = 0;
|
||||
}
|
||||
|
||||
numEdges = 0;
|
||||
}
|
||||
|
||||
/* Add an edge e between vertices v1 and v2 */
|
||||
/* e, v1, v2 are 0 based */
|
||||
static void
|
||||
addToGraph(int e, int v1, int v2)
|
||||
{
|
||||
e++; v1++; v2++; /* So much more convenient */
|
||||
|
||||
graphNode[NumEntry+e] = v2; /* Insert the edge information */
|
||||
graphNode[NumEntry-e] = v1;
|
||||
|
||||
graphNext[NumEntry+e] = graphFirst[v1]; /* Insert v1 to list of alphas */
|
||||
graphFirst[v1]= e;
|
||||
graphNext[NumEntry-e] = graphFirst[v2]; /* Insert v2 to list of omegas */
|
||||
graphFirst[v2]= -e;
|
||||
|
||||
}
|
||||
|
||||
bool DFS(int parentE, int v)
|
||||
{
|
||||
int e, w;
|
||||
|
||||
/* Depth first search of the graph, starting at vertex v, looking for
|
||||
cycles. parent and v are origin 1. Note parent is an EDGE,
|
||||
not a vertex */
|
||||
|
||||
visited[v] = TRUE;
|
||||
|
||||
/* For each e incident with v .. */
|
||||
for (e = graphFirst[v]; e; e = graphNext[NumEntry+e])
|
||||
{
|
||||
byte *key1;
|
||||
|
||||
getKey(abs(e)-1, &key1);
|
||||
if (*(long *)key1 == 0)
|
||||
{
|
||||
/* A deleted key. Just ignore it */
|
||||
continue;
|
||||
}
|
||||
w = graphNode[NumEntry+e];
|
||||
if (visited[w])
|
||||
{
|
||||
/* Did we just come through this edge? If so, ignore it. */
|
||||
if (abs(e) != abs(parentE))
|
||||
{
|
||||
/* There is a cycle in the graph. There is some subtle code here
|
||||
to work around the distinct possibility that there may be
|
||||
duplicate keys. Duplicate keys will always cause unit
|
||||
cycles, since f1 and f2 (used to select v and w) will be the
|
||||
same for both. The edges (representing an index into the
|
||||
array of keys) are distinct, but the key values are not.
|
||||
The logic is as follows: for the candidate edge e, check to
|
||||
see if it terminates in the parent vertex. If so, we test
|
||||
the keys associated with e and the parent, and if they are
|
||||
the same, we can safely ignore e for the purposes of cycle
|
||||
detection, since edge e adds nothing to the cycle. Cycles
|
||||
involving v, w, and e0 will still be found. The parent
|
||||
edge was not similarly eliminated because at the time when
|
||||
it was a candidate, v was not yet visited.
|
||||
We still have to remove the key from further consideration,
|
||||
since each edge is visited twice, but with a different
|
||||
parent edge each time.
|
||||
*/
|
||||
/* We save some stack space by calculating the parent vertex
|
||||
for these relatively few cases where it is needed */
|
||||
int parentV = graphNode[NumEntry-parentE];
|
||||
|
||||
if (w == parentV)
|
||||
{
|
||||
byte *key2;
|
||||
|
||||
getKey(abs(parentE)-1, &key2);
|
||||
if (memcmp(key1, key2, EntryLen) == 0)
|
||||
{
|
||||
printf("Duplicate keys with edges %d and %d (",
|
||||
e, parentE);
|
||||
dispKey(abs(e)-1);
|
||||
printf(" & ");
|
||||
dispKey(abs(parentE)-1);
|
||||
printf(")\n");
|
||||
/* *(long *)key1 = 0; /* Wipe the key */
|
||||
memset(key1, 0, EntryLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A genuine (unit) cycle. */
|
||||
printf("There is a unit cycle involving vertex %d and edge %d\n", v, e);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have reached a previously visited vertex not the
|
||||
parent. Therefore, we have uncovered a genuine cycle */
|
||||
printf("There is a cycle involving vertex %d and edge %d\n", v, e);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not yet seen. Traverse it */
|
||||
{
|
||||
if (DFS(e, w))
|
||||
{
|
||||
/* Cycle found deeper down. Exit */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool
|
||||
isCycle(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
visited[v] = FALSE;
|
||||
}
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
if (!visited[v])
|
||||
{
|
||||
if (DFS(-32767, v))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
traverse(int u)
|
||||
{
|
||||
int w, e;
|
||||
|
||||
visited[u] = TRUE;
|
||||
/* Find w, the neighbours of u, by searching the edges e associated with u */
|
||||
e = graphFirst[1+u];
|
||||
while (e)
|
||||
{
|
||||
w = graphNode[NumEntry+e]-1;
|
||||
if (!visited[w])
|
||||
{
|
||||
g[w] = (abs(e)-1 - g[u]) % NumEntry;
|
||||
if (g[w] < 0) g[w] += NumEntry; /* Keep these positive */
|
||||
traverse(w);
|
||||
}
|
||||
e = graphNext[NumEntry+e];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
assign(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
g[v] = 0; /* g is sparse; leave the gaps 0 */
|
||||
visited[v] = FALSE;
|
||||
}
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
if (!visited[v])
|
||||
{
|
||||
g[v] = 0;
|
||||
traverse(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hash(byte *string)
|
||||
{
|
||||
word u, v;
|
||||
int j;
|
||||
|
||||
u = 0;
|
||||
@ -86,18 +381,68 @@ int PatternHasher::hash(uint8_t *string)
|
||||
return (g[u] + g[v]) % NumEntry;
|
||||
}
|
||||
|
||||
uint16_t * PatternHasher::readT1(void)
|
||||
word *
|
||||
readT1(void)
|
||||
{
|
||||
return T1base;
|
||||
}
|
||||
|
||||
uint16_t *PatternHasher::readT2(void)
|
||||
word *
|
||||
readT2(void)
|
||||
{
|
||||
return T2base;
|
||||
}
|
||||
|
||||
uint16_t * PatternHasher::readG(void)
|
||||
word *
|
||||
readG(void)
|
||||
{
|
||||
return (uint16_t *)g;
|
||||
return (word *)g;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dispRecord(int i);
|
||||
|
||||
void
|
||||
duplicateKeys(int v1, int v2)
|
||||
{
|
||||
int i, j;
|
||||
byte *keys;
|
||||
int u, v;
|
||||
|
||||
v1--; v2--; /* These guys are origin 1 */
|
||||
|
||||
printf("Duplicate keys:\n");
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
getKey(i, &keys);
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[keys[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
if ((u != v1) && (u != v2)) continue;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[keys[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
if ((v == v2) || (v == v1))
|
||||
{
|
||||
printf("Entry #%d key: ", i+1);
|
||||
for (j=0; j < EntryLen; j++) printf("%02X ", keys[j]);
|
||||
printf("\n");
|
||||
dispRecord(i+1);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
353
src/procs.cpp
353
src/procs.cpp
@ -5,83 +5,87 @@
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
extern Project g_proj;
|
||||
/* Static indentation buffer */
|
||||
static constexpr int indSize=81; /* size of indentation buffer; max 20 */
|
||||
#define indSize 61 /* size of indentation buffer; max 20 */
|
||||
static char indentBuf[indSize] =
|
||||
" ";
|
||||
// not static, used in icode.cpp at emitGotoLabel
|
||||
const char *indentStr(int indLevel) // Indentation according to the depth of the statement
|
||||
|
||||
static char *indent (Int indLevel)
|
||||
/* Indentation according to the depth of the statement */
|
||||
{
|
||||
return (&indentBuf[indSize-(indLevel*4)-1]);
|
||||
return (&indentBuf[indSize-(indLevel*3)-1]);
|
||||
}
|
||||
|
||||
|
||||
static void insertArc (PCALL_GRAPH pcallGraph, PPROC newProc)
|
||||
/* Inserts an outEdge at the current callGraph pointer if the newProc does
|
||||
* not exist. */
|
||||
void CALL_GRAPH::insertArc (ilFunction newProc)
|
||||
{
|
||||
CALL_GRAPH *pcg;
|
||||
|
||||
{ CALL_GRAPH *pcg;
|
||||
Int i;
|
||||
|
||||
/* Check if procedure already exists */
|
||||
auto res=std::find_if(outEdges.begin(),outEdges.end(),[newProc](CALL_GRAPH *e) {return e->proc==newProc;});
|
||||
if(res!=outEdges.end())
|
||||
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||
if (pcallGraph->outEdges[i]->proc == newProc)
|
||||
return;
|
||||
|
||||
/* Check if need to allocate more space */
|
||||
if (pcallGraph->numOutEdges == pcallGraph->numAlloc)
|
||||
{
|
||||
pcallGraph->numAlloc += NUM_PROCS_DELTA;
|
||||
pcallGraph->outEdges = (PCALL_GRAPH*)reallocVar(pcallGraph->outEdges,
|
||||
pcallGraph->numAlloc * sizeof(PCALL_GRAPH));
|
||||
memset (&pcallGraph->outEdges[pcallGraph->numOutEdges], 0,
|
||||
NUM_PROCS_DELTA * sizeof(PCALL_GRAPH));
|
||||
}
|
||||
|
||||
/* Include new arc */
|
||||
pcg = new CALL_GRAPH;
|
||||
pcg = allocStruc(CALL_GRAPH);
|
||||
memset (pcg, 0, sizeof(CALL_GRAPH));
|
||||
pcg->proc = newProc;
|
||||
outEdges.push_back(pcg);
|
||||
pcallGraph->outEdges[pcallGraph->numOutEdges] = pcg;
|
||||
pcallGraph->numOutEdges++;
|
||||
}
|
||||
|
||||
|
||||
boolT insertCallGraph (PCALL_GRAPH pcallGraph, PPROC caller, PPROC callee)
|
||||
/* Inserts a (caller, callee) arc in the call graph tree. */
|
||||
bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
|
||||
{
|
||||
int i;
|
||||
{ Int i;
|
||||
|
||||
if (proc == caller)
|
||||
if (pcallGraph->proc == caller)
|
||||
{
|
||||
insertArc (callee);
|
||||
return true;
|
||||
insertArc (pcallGraph, callee);
|
||||
return (TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
if (outEdges[i]->insertCallGraph (caller, callee))
|
||||
return true;
|
||||
return (false);
|
||||
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||
if (insertCallGraph (pcallGraph->outEdges[i], caller, callee))
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
|
||||
{
|
||||
return insertCallGraph(g_proj.funcIter(caller),callee);
|
||||
}
|
||||
|
||||
|
||||
static void writeNodeCallGraph (PCALL_GRAPH pcallGraph, Int indIdx)
|
||||
/* Displays the current node of the call graph, and invokes recursively on
|
||||
* the nodes the procedure invokes. */
|
||||
void CALL_GRAPH::writeNodeCallGraph(int indIdx)
|
||||
{
|
||||
int i;
|
||||
{ Int i;
|
||||
|
||||
printf ("%s%s\n", indentStr(indIdx), proc->name.c_str());
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
outEdges[i]->writeNodeCallGraph (indIdx + 1);
|
||||
printf ("%s%s\n", indent(indIdx), pcallGraph->proc->name);
|
||||
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||
writeNodeCallGraph (pcallGraph->outEdges[i], indIdx + 1);
|
||||
}
|
||||
|
||||
|
||||
void writeCallGraph (PCALL_GRAPH pcallGraph)
|
||||
/* Writes the header and invokes recursive procedure */
|
||||
void CALL_GRAPH::write()
|
||||
{
|
||||
printf ("\nCall Graph:\n");
|
||||
writeNodeCallGraph (0);
|
||||
writeNodeCallGraph (pcallGraph, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -89,192 +93,217 @@ void CALL_GRAPH::write()
|
||||
* Routines to support arguments
|
||||
*************************************************************************/
|
||||
|
||||
void newRegArg (PPROC pproc, PICODE picode, PICODE ticode)
|
||||
/* Updates the argument table by including the register(s) (ie. lhs of
|
||||
* picode) and the actual expression (ie. rhs of picode).
|
||||
* Note: register(s) are only included once in the table. */
|
||||
void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
|
||||
{
|
||||
COND_EXPR *lhs;
|
||||
STKFRAME * call_args_stackframe, *target_stackframe;
|
||||
const ID *id;
|
||||
int tidx;
|
||||
{ COND_EXPR *lhs;
|
||||
PSTKFRAME ps, ts;
|
||||
ID *id;
|
||||
Int i, tidx;
|
||||
boolT regExist;
|
||||
condId type;
|
||||
Function * tproc;
|
||||
eReg regL, regH; /* Registers involved in arguments */
|
||||
PPROC tproc;
|
||||
byte regL, regH; /* Registers involved in arguments */
|
||||
|
||||
/* Flag ticode as having register arguments */
|
||||
tproc = ticode->hl()->call.proc;
|
||||
tproc = ticode->ic.hl.oper.call.proc;
|
||||
tproc->flg |= REG_ARGS;
|
||||
|
||||
/* Get registers and index into target procedure's local list */
|
||||
call_args_stackframe = ticode->hl()->call.args;
|
||||
target_stackframe = &tproc->args;
|
||||
lhs = picode->hl()->asgn.lhs;
|
||||
ps = ticode->ic.hl.oper.call.args;
|
||||
ts = &tproc->args;
|
||||
lhs = picode->ic.hl.oper.asgn.lhs;
|
||||
type = lhs->expr.ident.idType;
|
||||
if (type == REGISTER)
|
||||
{
|
||||
regL = id_arr[lhs->expr.ident.idNode.regiIdx].id.regi;
|
||||
regL = pproc->localId.id[lhs->expr.ident.idNode.regiIdx].id.regi;
|
||||
if (regL < rAL)
|
||||
tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL);
|
||||
tidx = newByteWordRegId (&tproc->localId, TYPE_WORD_SIGN, regL);
|
||||
else
|
||||
tidx = tproc->localId.newByteWordReg(TYPE_BYTE_SIGN, regL);
|
||||
tidx = newByteWordRegId (&tproc->localId, TYPE_BYTE_SIGN, regL);
|
||||
}
|
||||
else if (type == LONG_VAR)
|
||||
{
|
||||
int longIdx = lhs->expr.ident.idNode.longIdx;
|
||||
regL = id_arr[longIdx].id.longId.l;
|
||||
regH = id_arr[longIdx].id.longId.h;
|
||||
tidx = tproc->localId.newLongReg(TYPE_LONG_SIGN, regH, regL, tproc->Icode.begin() /*0*/);
|
||||
regL = pproc->localId.id[lhs->expr.ident.idNode.longIdx].id.longId.l;
|
||||
regH = pproc->localId.id[lhs->expr.ident.idNode.longIdx].id.longId.h;
|
||||
tidx = newLongRegId (&tproc->localId, TYPE_LONG_SIGN, regH, regL, 0);
|
||||
}
|
||||
|
||||
/* Check if register argument already on the formal argument list */
|
||||
regExist = false;
|
||||
for(STKSYM &tgt_sym : *target_stackframe)
|
||||
regExist = FALSE;
|
||||
for (i = 0; i < ts->csym; i++)
|
||||
{
|
||||
if( tgt_sym.regs == NULL ) // both REGISTER and LONG_VAR require this precondition
|
||||
continue;
|
||||
if (type == REGISTER)
|
||||
{
|
||||
if ( tgt_sym.regs->expr.ident.idNode.regiIdx == tidx )
|
||||
if ((ts->sym[i].regs != NULL) &&
|
||||
(ts->sym[i].regs->expr.ident.idNode.regiIdx == tidx))
|
||||
{
|
||||
regExist = true;
|
||||
regExist = TRUE;
|
||||
i = ts->csym;
|
||||
}
|
||||
}
|
||||
else if (type == LONG_VAR)
|
||||
{
|
||||
if ( tgt_sym.regs->expr.ident.idNode.longIdx == tidx )
|
||||
if ((ts->sym[i].regs != NULL) &&
|
||||
(ts->sym[i].regs->expr.ident.idNode.longIdx == tidx))
|
||||
{
|
||||
regExist = true;
|
||||
regExist = TRUE;
|
||||
i = ts->csym;
|
||||
}
|
||||
}
|
||||
if(regExist == true)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do ts (formal arguments) */
|
||||
if (regExist == false)
|
||||
if (regExist == FALSE)
|
||||
{
|
||||
STKSYM newsym;
|
||||
|
||||
newsym.setArgName(target_stackframe->size());
|
||||
|
||||
if (ts->csym == ts->alloc)
|
||||
{
|
||||
ts->alloc += 5;
|
||||
ts->sym = (STKSYM*)reallocVar(ts->sym, ts->alloc * sizeof(STKSYM));
|
||||
memset (&ts->sym[ts->csym], 0, 5 * sizeof(STKSYM));
|
||||
}
|
||||
sprintf (ts->sym[ts->csym].name, "arg%ld", ts->csym);
|
||||
if (type == REGISTER)
|
||||
{
|
||||
if (regL < rAL)
|
||||
{
|
||||
newsym.type = TYPE_WORD_SIGN;
|
||||
newsym.regs = COND_EXPR::idRegIdx(tidx, WORD_REG);
|
||||
ts->sym[ts->csym].type = TYPE_WORD_SIGN;
|
||||
ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, WORD_REG);
|
||||
}
|
||||
else
|
||||
{
|
||||
newsym.type = TYPE_BYTE_SIGN;
|
||||
newsym.regs = COND_EXPR::idRegIdx(tidx, BYTE_REG);
|
||||
ts->sym[ts->csym].type = TYPE_BYTE_SIGN;
|
||||
ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, BYTE_REG);
|
||||
}
|
||||
tproc->localId.id_arr[tidx].name = newsym.name;
|
||||
sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym);
|
||||
}
|
||||
else if (type == LONG_VAR)
|
||||
{
|
||||
newsym.regs = COND_EXPR::idLongIdx (tidx);
|
||||
newsym.type = TYPE_LONG_SIGN;
|
||||
tproc->localId.id_arr[tidx].name = newsym.name;
|
||||
tproc->localId.propLongId (regL, regH, tproc->localId.id_arr[tidx].name.c_str());
|
||||
ts->sym[ts->csym].regs = idCondExpLongIdx (tidx);
|
||||
ts->sym[ts->csym].type = TYPE_LONG_SIGN;
|
||||
sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym);
|
||||
propLongId (&tproc->localId, regL, regH,
|
||||
tproc->localId.id[tidx].name);
|
||||
}
|
||||
target_stackframe->push_back(newsym);
|
||||
target_stackframe->numArgs++;
|
||||
|
||||
ts->csym++;
|
||||
ts->numArgs++;
|
||||
}
|
||||
|
||||
/* Do ps (actual arguments) */
|
||||
STKSYM newsym;
|
||||
newsym.setArgName(call_args_stackframe->size());
|
||||
newsym.actual = picode->hl()->asgn.rhs;
|
||||
newsym.regs = lhs;
|
||||
if (ps->csym == ps->alloc)
|
||||
{
|
||||
ps->alloc += 5;
|
||||
ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
|
||||
memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM));
|
||||
}
|
||||
sprintf (ps->sym[ps->csym].name, "arg%ld", ps->csym);
|
||||
ps->sym[ps->csym].actual = picode->ic.hl.oper.asgn.rhs;
|
||||
ps->sym[ps->csym].regs = lhs;
|
||||
|
||||
/* Mask off high and low register(s) in picode */
|
||||
switch (type) {
|
||||
case REGISTER:
|
||||
id = &id_arr[lhs->expr.ident.idNode.regiIdx];
|
||||
id = &pproc->localId.id[lhs->expr.ident.idNode.regiIdx];
|
||||
picode->du.def &= maskDuReg[id->id.regi];
|
||||
if (id->id.regi < rAL)
|
||||
newsym.type = TYPE_WORD_SIGN;
|
||||
ps->sym[ps->csym].type = TYPE_WORD_SIGN;
|
||||
else
|
||||
newsym.type = TYPE_BYTE_SIGN;
|
||||
ps->sym[ps->csym].type = TYPE_BYTE_SIGN;
|
||||
break;
|
||||
case LONG_VAR:
|
||||
id = &id_arr[lhs->expr.ident.idNode.longIdx];
|
||||
id = &pproc->localId.id[lhs->expr.ident.idNode.longIdx];
|
||||
picode->du.def &= maskDuReg[id->id.longId.h];
|
||||
picode->du.def &= maskDuReg[id->id.longId.l];
|
||||
newsym.type = TYPE_LONG_SIGN;
|
||||
ps->sym[ps->csym].type = TYPE_LONG_SIGN;
|
||||
break;
|
||||
}
|
||||
call_args_stackframe->push_back(newsym);
|
||||
call_args_stackframe->numArgs++;
|
||||
|
||||
ps->csym++;
|
||||
ps->numArgs++;
|
||||
}
|
||||
|
||||
|
||||
/** Inserts the new expression (ie. the actual parameter) on the argument
|
||||
void allocStkArgs (PICODE picode, Int num)
|
||||
/* Allocates num arguments in the actual argument list of the current
|
||||
* icode picode. */
|
||||
/** NOTE: this function is not used ****/
|
||||
{ PSTKFRAME ps;
|
||||
|
||||
ps = picode->ic.hl.oper.call.args;
|
||||
ps->alloc = num;
|
||||
ps->csym = num;
|
||||
ps->numArgs = num;
|
||||
ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
|
||||
/**** memset here??? *****/
|
||||
}
|
||||
|
||||
|
||||
boolT newStkArg (PICODE picode, COND_EXPR *exp, llIcode opcode, PPROC pproc)
|
||||
/* Inserts the new expression (ie. the actual parameter) on the argument
|
||||
* list.
|
||||
* @return true if it was a near call that made use of a segment register.
|
||||
* false elsewhere
|
||||
*/
|
||||
bool CallType::newStkArg(COND_EXPR *exp, llIcode opcode, Function * pproc)
|
||||
{
|
||||
uint8_t regi;
|
||||
* Returns: TRUE if it was a near call that made use of a segment register.
|
||||
* FALSE elsewhere */
|
||||
{ PSTKFRAME ps;
|
||||
byte regi;
|
||||
|
||||
/* Check for far procedure call, in which case, references to segment
|
||||
* registers are not be considered another parameter (i.e. they are
|
||||
* long references to another segment) */
|
||||
if (exp)
|
||||
{
|
||||
if ((exp->m_type == IDENTIFIER) && (exp->expr.ident.idType == REGISTER))
|
||||
if ((exp->type == IDENTIFIER) && (exp->expr.ident.idType == REGISTER))
|
||||
{
|
||||
regi = pproc->localId.id_arr[exp->expr.ident.idNode.regiIdx].id.regi;
|
||||
regi = pproc->localId.id[exp->expr.ident.idNode.regiIdx].id.regi;
|
||||
if ((regi >= rES) && (regi <= rDS))
|
||||
if (opcode == iCALLF)
|
||||
return false;
|
||||
return (FALSE);
|
||||
else
|
||||
return true;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Place register argument on the argument list */
|
||||
STKSYM newsym;
|
||||
newsym.actual = exp;
|
||||
args->push_back(newsym);
|
||||
args->numArgs++;
|
||||
return false;
|
||||
ps = picode->ic.hl.oper.call.args;
|
||||
if (ps->csym == ps->alloc)
|
||||
{
|
||||
ps->alloc += 5;
|
||||
ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
|
||||
memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM));
|
||||
}
|
||||
ps->sym[ps->csym].actual = exp;
|
||||
ps->csym++;
|
||||
ps->numArgs++;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
void placeStkArg (PICODE picode, COND_EXPR *exp, Int pos)
|
||||
/* Places the actual argument exp in the position given by pos in the
|
||||
* argument list of picode. */
|
||||
void CallType::placeStkArg (COND_EXPR *exp, int pos)
|
||||
{
|
||||
(*args)[pos].actual = exp;
|
||||
(*args)[pos].setArgName(pos);
|
||||
}
|
||||
{ PSTKFRAME ps;
|
||||
|
||||
COND_EXPR *CallType::toId()
|
||||
{
|
||||
return COND_EXPR::idFunc( proc, args);
|
||||
ps = picode->ic.hl.oper.call.args;
|
||||
ps->sym[pos].actual = exp;
|
||||
sprintf (ps->sym[pos].name, "arg%ld", pos);
|
||||
}
|
||||
|
||||
|
||||
void adjustActArgType (COND_EXPR *exp, hlType forType, PPROC pproc)
|
||||
/* Checks to determine whether the expression (actual argument) has the
|
||||
* same type as the given type (from the procedure's formal list). If not,
|
||||
* the actual argument gets modified */
|
||||
void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
hlType actType;
|
||||
int offset, offL;
|
||||
{ hlType actType;
|
||||
Int offset, offL;
|
||||
|
||||
if (exp == NULL)
|
||||
return;
|
||||
|
||||
actType = exp-> expType (pproc);
|
||||
if (((actType == forType) || (exp->m_type != IDENTIFIER)))
|
||||
return;
|
||||
switch (forType)
|
||||
actType = expType (exp, pproc);
|
||||
if ((actType != forType) && (exp->type == IDENTIFIER))
|
||||
{
|
||||
switch (forType) {
|
||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
|
||||
@ -311,47 +340,45 @@ void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
|
||||
} /* eos */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void adjustForArgType (PSTKFRAME pstkFrame, Int numArg, hlType actType)
|
||||
/* Determines whether the formal argument has the same type as the given
|
||||
* type (type of the actual argument). If not, the formal argument is
|
||||
* changed its type */
|
||||
void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
||||
{
|
||||
hlType forType;
|
||||
STKSYM * psym, * nsym;
|
||||
int off, i;
|
||||
/* If formal argument does not exist, do not create new ones, just
|
||||
* ignore actual argument
|
||||
*/
|
||||
if(numArg_>size())
|
||||
return;
|
||||
{ hlType forType;
|
||||
PSTKSYM psym, nsym;
|
||||
Int off, i;
|
||||
|
||||
/* Find stack offset for this argument */
|
||||
off = m_minOff;
|
||||
i=0;
|
||||
for(STKSYM &s : *this) // walk formal arguments upto numArg_
|
||||
{
|
||||
if(i>=numArg_)
|
||||
break;
|
||||
off+=s.size;
|
||||
i++;
|
||||
}
|
||||
off = pstkFrame->minOff;
|
||||
for (i = 0; i < numArg; i++)
|
||||
off += pstkFrame->sym[i].size;
|
||||
|
||||
/* Find formal argument */
|
||||
//psym = &at(numArg_);
|
||||
//i = numArg_;
|
||||
//auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;});
|
||||
auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {s.label==off;});
|
||||
if(iter==end()) // symbol not found
|
||||
if (numArg < pstkFrame->csym)
|
||||
{
|
||||
psym = &pstkFrame->sym[numArg];
|
||||
i = numArg;
|
||||
while ((i < pstkFrame->csym) && (psym->off != off))
|
||||
{
|
||||
psym++;
|
||||
i++;
|
||||
}
|
||||
if (numArg == pstkFrame->csym)
|
||||
return;
|
||||
}
|
||||
/* If formal argument does not exist, do not create new ones, just
|
||||
* ignore actual argument */
|
||||
else
|
||||
return;
|
||||
psym = &(*iter);
|
||||
|
||||
forType = psym->type;
|
||||
if (forType != actType_)
|
||||
if (forType != actType)
|
||||
{
|
||||
switch (actType_) {
|
||||
switch (actType) {
|
||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
|
||||
@ -363,16 +390,16 @@ void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
||||
(forType == TYPE_UNKNOWN))
|
||||
{
|
||||
/* Merge low and high */
|
||||
psym->type = actType_;
|
||||
psym->type = actType;
|
||||
psym->size = 4;
|
||||
nsym = psym + 1;
|
||||
nsym->macro = "HI";
|
||||
psym->macro = "LO";
|
||||
nsym->hasMacro = true;
|
||||
psym->hasMacro = true;
|
||||
nsym->name = psym->name;
|
||||
nsym->invalid = true;
|
||||
numArgs--;
|
||||
sprintf (nsym->macro, "HI");
|
||||
sprintf (psym->macro, "LO");
|
||||
nsym->hasMacro = TRUE;
|
||||
psym->hasMacro = TRUE;
|
||||
sprintf (nsym->name, "%s", psym->name);
|
||||
nsym->invalid = TRUE;
|
||||
pstkFrame->numArgs--;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
#include <utility>
|
||||
#include "project.h"
|
||||
#include "Procedure.h"
|
||||
Project g_proj;
|
||||
bool Project::valid(ilFunction iter)
|
||||
{
|
||||
return iter!=pProcList.end();
|
||||
}
|
||||
ilFunction Project::funcIter(Function *to_find)
|
||||
{
|
||||
auto iter=std::find_if(pProcList.begin(),pProcList.end(),
|
||||
[to_find](const Function &f)->bool {return to_find==&f;});
|
||||
assert(iter!=pProcList.end());
|
||||
return iter;
|
||||
}
|
||||
|
||||
ilFunction Project::findByEntry(uint32_t entry)
|
||||
{
|
||||
/* Search procedure list for one with appropriate entry point */
|
||||
ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(),
|
||||
[entry](const Function &f) ->
|
||||
bool { return f.procEntry==entry; });
|
||||
return iter;
|
||||
}
|
||||
|
||||
ilFunction Project::createFunction()
|
||||
{
|
||||
pProcList.push_back(Function::Create());
|
||||
return (++pProcList.rbegin()).base();
|
||||
}
|
||||
|
||||
int Project::getSymIdxByAdd(uint32_t adr)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < symtab.size(); i++)
|
||||
if (symtab[i].label == adr)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
bool Project::validSymIdx(size_t idx)
|
||||
{
|
||||
return idx<symtab.size();
|
||||
}
|
||||
const SYM &Project::getSymByIdx(size_t idx) const
|
||||
{
|
||||
return symtab[idx];
|
||||
}
|
||||
size_t Project::symbolSize(size_t idx)
|
||||
{
|
||||
assert(validSymIdx(idx));
|
||||
return symtab[idx].size;
|
||||
}
|
||||
hlType Project::symbolType(size_t idx)
|
||||
{
|
||||
assert(validSymIdx(idx));
|
||||
return symtab[idx].type;
|
||||
}
|
||||
|
||||
const std::string &Project::symbolName(size_t idx)
|
||||
{
|
||||
assert(validSymIdx(idx));
|
||||
return symtab[idx].name;
|
||||
}
|
||||
Project *Project::get()
|
||||
{
|
||||
return &g_proj;
|
||||
}
|
||||
|
||||
|
||||
SourceMachine *Project::machine()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
653
src/proplong.cpp
653
src/proplong.cpp
@ -4,93 +4,91 @@
|
||||
* registers) along the graph. Structure the graph in this way.
|
||||
* (C) Cristina Cifuentes
|
||||
**************************************************************************/
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "string.h"
|
||||
#ifdef __BORLAND__
|
||||
#include <mem.h>
|
||||
#else
|
||||
#include <memory.h>
|
||||
#endif
|
||||
|
||||
|
||||
static boolT isJCond (llIcode opcode)
|
||||
/* Returns whether the given icode opcode is within the range of valid
|
||||
* high-level conditional jump icodes (iJB..iJG) */
|
||||
static boolT isJCond (llIcode opcode)
|
||||
{
|
||||
if ((opcode >= iJB) && (opcode <= iJG))
|
||||
return true;
|
||||
return false;
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static boolT isLong23 (Int i, PBB pbb, PICODE icode, Int *off, Int *arc)
|
||||
/* Returns whether the conditions for a 2-3 long variable are satisfied */
|
||||
static bool isLong23 (BB * pbb, iICODE &off, int *arc)
|
||||
{
|
||||
BB * t, * e, * obb2;
|
||||
{ PBB t, e, obb2;
|
||||
|
||||
if (pbb->nodeType != TWO_BRANCH)
|
||||
return false;
|
||||
return (FALSE);
|
||||
t = pbb->edges[THEN].BBptr;
|
||||
e = pbb->edges[ELSE].BBptr;
|
||||
|
||||
/* Check along the THEN path */
|
||||
if ((t->size() == 1) && (t->nodeType == TWO_BRANCH) && (t->inEdges.size() == 1))
|
||||
if ((t->length == 1) && (t->nodeType == TWO_BRANCH) && (t->numInEdges == 1))
|
||||
{
|
||||
obb2 = t->edges[THEN].BBptr;
|
||||
if ((obb2->size() == 2) && (obb2->nodeType == TWO_BRANCH) && (obb2->front().ll()->getOpcode() == iCMP))
|
||||
if ((obb2->length == 2) && (obb2->nodeType == TWO_BRANCH) &&
|
||||
(icode[obb2->start].ic.ll.opcode == iCMP))
|
||||
{
|
||||
off = obb2->begin();//std::distance(iter,obb2->begin2());
|
||||
*off = obb2->start - i;
|
||||
*arc = THEN;
|
||||
return true;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check along the ELSE path */
|
||||
else if ((e->size() == 1) && (e->nodeType == TWO_BRANCH) && (e->inEdges.size() == 1))
|
||||
else if ((e->length == 1) && (e->nodeType == TWO_BRANCH) &&
|
||||
(e->numInEdges == 1))
|
||||
{
|
||||
obb2 = e->edges[THEN].BBptr;
|
||||
if ((obb2->size() == 2) && (obb2->nodeType == TWO_BRANCH) && (obb2->front().ll()->getOpcode() == iCMP))
|
||||
if ((obb2->length == 2) && (obb2->nodeType == TWO_BRANCH) &&
|
||||
(icode[obb2->start].ic.ll.opcode == iCMP))
|
||||
{
|
||||
off = obb2->begin();//std::distance(iter,obb2->begin2());//obb2->front().loc_ip - i;
|
||||
*off = obb2->start - i;
|
||||
*arc = ELSE;
|
||||
return true;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static boolT isLong22 (PICODE pIcode, PICODE pEnd, Int *off)
|
||||
/* Returns whether the conditions for a 2-2 long variable are satisfied */
|
||||
static boolT isLong22 (iICODE pIcode, iICODE pEnd, iICODE &off)
|
||||
{
|
||||
iICODE initial_icode=pIcode;
|
||||
if(distance(pIcode,pEnd)<4)
|
||||
return false;
|
||||
// preincrement because pIcode is not checked here
|
||||
iICODE icodes[] = { ++pIcode,++pIcode,++pIcode };
|
||||
if ( icodes[1]->ll()->match(iCMP) &&
|
||||
(isJCond ((llIcode)icodes[0]->ll()->getOpcode())) &&
|
||||
(isJCond ((llIcode)icodes[2]->ll()->getOpcode())))
|
||||
if (((pIcode+2) < pEnd) && ((pIcode+2)->ic.ll.opcode == iCMP) &&
|
||||
(isJCond ((pIcode+1)->ic.ll.opcode)) &&
|
||||
(isJCond ((pIcode+3)->ic.ll.opcode)))
|
||||
{
|
||||
off = initial_icode;
|
||||
advance(off,2);
|
||||
return true;
|
||||
*off = 2;
|
||||
return (TRUE);
|
||||
}
|
||||
return false;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/** Creates a long conditional <=, >=, <, or > at (pIcode+1).
|
||||
* Removes excess nodes from the graph by flagging them, and updates
|
||||
* the new edges for the remaining nodes.
|
||||
* @return number of ICODEs to skip
|
||||
|
||||
*/
|
||||
static int longJCond23 (Assignment &asgn, iICODE pIcode, int arc, iICODE atOffset)
|
||||
{
|
||||
BB * pbb, * obb1, * obb2, * tbb;
|
||||
int skipped_insn=0;
|
||||
static void longJCond23 (COND_EXPR *rhs, COND_EXPR *lhs, PICODE pIcode,
|
||||
Int *idx, PPROC pProc, Int arc, Int off)
|
||||
/* Creates a long conditional <=, >=, <, or > at (pIcode+1).
|
||||
* Removes excess nodes from the graph by flagging them, and updates
|
||||
* the new edges for the remaining nodes. */
|
||||
{ Int j;
|
||||
PBB pbb, obb1, obb2, tbb;
|
||||
|
||||
if (arc == THEN)
|
||||
{
|
||||
/* Find intermediate basic blocks and target block */
|
||||
pbb = pIcode->getParent();
|
||||
pbb = pIcode->inBB;
|
||||
obb1 = pbb->edges[THEN].BBptr;
|
||||
obb2 = obb1->edges[THEN].BBptr;
|
||||
tbb = obb2->edges[THEN].BBptr;
|
||||
@ -99,92 +97,113 @@ static int longJCond23 (Assignment &asgn, iICODE pIcode, int arc, iICODE atOffse
|
||||
pbb->edges[THEN].BBptr = tbb;
|
||||
|
||||
/* Modify in edges of target basic block */
|
||||
auto newlast=std::remove_if(tbb->inEdges.begin(),tbb->inEdges.end(),
|
||||
[obb1,obb2](BB *b) -> bool {
|
||||
return (b==obb1) || (b==obb2); });
|
||||
tbb->inEdges.erase(newlast,tbb->inEdges.end());
|
||||
tbb->inEdges.push_back(pbb); /* looses 2 arcs, gains 1 arc */
|
||||
for (j = 0; j < (tbb->numInEdges-1); j++)
|
||||
{
|
||||
if ((tbb->inEdges[j] == obb1) || (tbb->inEdges[j] == obb2))
|
||||
{
|
||||
memmove (&tbb->inEdges[j], &tbb->inEdges[j+1],
|
||||
(tbb->numInEdges - j-1) * sizeof(PBB));
|
||||
memset (&tbb->inEdges[tbb->numInEdges-1], ' ',sizeof (PBB));
|
||||
j--;
|
||||
}
|
||||
}
|
||||
tbb->numInEdges--; /* looses 2 arcs, gains 1 arc */
|
||||
tbb->inEdges[tbb->numInEdges-1] = pbb;
|
||||
|
||||
/* Modify in edges of the ELSE basic block */
|
||||
tbb = pbb->edges[ELSE].BBptr;
|
||||
auto iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb2);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter); /* looses 1 arc */
|
||||
/* Update icode index */
|
||||
skipped_insn = 5;
|
||||
for (j = 0; j < (tbb->numInEdges-1); j++)
|
||||
{
|
||||
if (tbb->inEdges[j] == obb2)
|
||||
{
|
||||
memmove (&tbb->inEdges[j], &tbb->inEdges[j+1],
|
||||
(tbb->numInEdges - j-1) * sizeof(PBB));
|
||||
break;
|
||||
}
|
||||
}
|
||||
tbb->numInEdges--; /* looses 1 arc */
|
||||
|
||||
/* Update icode index */
|
||||
(*idx) += 5;
|
||||
}
|
||||
|
||||
else /* ELSE arc */
|
||||
{
|
||||
/* Find intermediate basic blocks and target block */
|
||||
pbb = pIcode->getParent();
|
||||
pbb = pIcode->inBB;
|
||||
obb1 = pbb->edges[ELSE].BBptr;
|
||||
obb2 = obb1->edges[THEN].BBptr;
|
||||
tbb = obb2->edges[THEN].BBptr;
|
||||
|
||||
/* Modify in edges of target basic block */
|
||||
auto iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb2);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter); /* looses 1 arc */
|
||||
for (j = 0; j < (tbb->numInEdges-1); j++)
|
||||
{
|
||||
if (tbb->inEdges[j] == obb2)
|
||||
{
|
||||
memmove (&tbb->inEdges[j], &tbb->inEdges[j+1],
|
||||
(tbb->numInEdges - j-1) * sizeof(PBB));
|
||||
break;
|
||||
}
|
||||
}
|
||||
tbb->numInEdges--; /* looses 1 arc */
|
||||
|
||||
/* Modify in edges of the ELSE basic block */
|
||||
tbb = obb2->edges[ELSE].BBptr;
|
||||
auto newlast=std::remove_if(tbb->inEdges.begin(),tbb->inEdges.end(),
|
||||
[obb1,obb2](BB *b) -> bool { return (b==obb1) || (b==obb2); });
|
||||
tbb->inEdges.erase(newlast,tbb->inEdges.end());
|
||||
tbb->inEdges.push_back(pbb); /* looses 2 arcs, gains 1 arc */
|
||||
for (j = 0; j < (tbb->numInEdges-1); j++)
|
||||
{
|
||||
if ((tbb->inEdges[j] == obb2) || (tbb->inEdges[j] == obb1))
|
||||
{
|
||||
memmove (&tbb->inEdges[j], &tbb->inEdges[j+1],
|
||||
(tbb->numInEdges - j-1) * sizeof(PBB));
|
||||
memset (&tbb->inEdges[tbb->numInEdges-1], ' ',sizeof (PBB));
|
||||
j--;
|
||||
}
|
||||
}
|
||||
tbb->numInEdges--; /* looses 2 arcs, gains 1 arc */
|
||||
tbb->inEdges[tbb->numInEdges - 1] = pbb;
|
||||
|
||||
/* Modify out edge of header basic block */
|
||||
pbb->edges[ELSE].BBptr = tbb;
|
||||
|
||||
/* Update icode index */
|
||||
skipped_insn = 2;
|
||||
(*idx) += 2;
|
||||
}
|
||||
iICODE atOffset1(atOffset),next1(++iICODE(pIcode));
|
||||
advance(atOffset1,1);
|
||||
|
||||
/* Create new HLI_JCOND and condition */
|
||||
asgn.lhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, condOpJCond[atOffset1->ll()->getOpcode()-iJB]);
|
||||
next1->setJCond(asgn.lhs);
|
||||
next1->copyDU(*pIcode, eUSE, eUSE);
|
||||
next1->du.use |= atOffset->du.use;
|
||||
lhs = boolCondExp (lhs, rhs, condOpJCond[(pIcode+off+1)->ic.ll.opcode-iJB]);
|
||||
newJCondHlIcode (pIcode+1, lhs);
|
||||
copyDU (pIcode+1, pIcode, E_USE, E_USE);
|
||||
(pIcode+1)->du.use |= (pIcode+off)->du.use;
|
||||
|
||||
/* Update statistics */
|
||||
obb1->flg |= INVALID_BB;
|
||||
obb2->flg |= INVALID_BB;
|
||||
stats.numBBaft -= 2;
|
||||
|
||||
pIcode->invalidate();
|
||||
obb1->front().invalidate();
|
||||
// invalidate 2 first instructions of BB 2
|
||||
iICODE ibb2 = obb2->begin();
|
||||
(ibb2++)->invalidate();
|
||||
(ibb2++)->invalidate();
|
||||
return skipped_insn;
|
||||
invalidateIcode (pIcode);
|
||||
invalidateIcode (pProc->Icode.GetIcode(obb1->start));
|
||||
invalidateIcode (pProc->Icode.GetIcode(obb2->start));
|
||||
invalidateIcode (pProc->Icode.GetIcode(obb2->start+1));
|
||||
}
|
||||
|
||||
|
||||
/** Creates a long conditional equality or inequality at (pIcode+1).
|
||||
static void longJCond22 (COND_EXPR *rhs, COND_EXPR *lhs, PICODE pIcode,
|
||||
Int *idx)
|
||||
/* Creates a long conditional equality or inequality at (pIcode+1).
|
||||
* Removes excess nodes from the graph by flagging them, and updates
|
||||
* the new edges for the remaining nodes.
|
||||
* @return number of ICODE's to skip
|
||||
*/
|
||||
static int longJCond22 (Assignment &asgn, iICODE pIcode,iICODE pEnd)
|
||||
{
|
||||
|
||||
BB * pbb, * obb1, * tbb;
|
||||
if(distance(pIcode,pEnd)<4)
|
||||
return false;
|
||||
// preincrement because pIcode is not checked here
|
||||
iICODE icodes[] = { pIcode++,pIcode++,pIcode++,pIcode++ };
|
||||
* the new edges for the remaining nodes. */
|
||||
{ Int j;
|
||||
PBB pbb, obb1, tbb;
|
||||
|
||||
/* Form conditional expression */
|
||||
asgn.lhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, condOpJCond[icodes[3]->ll()->getOpcode() - iJB]);
|
||||
icodes[1]->setJCond(asgn.lhs);
|
||||
icodes[1]->copyDU (*icodes[0], eUSE, eUSE);
|
||||
icodes[1]->du.use |= icodes[2]->du.use;
|
||||
lhs = boolCondExp (lhs, rhs, condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]);
|
||||
newJCondHlIcode (pIcode+1, lhs);
|
||||
copyDU (pIcode+1, pIcode, E_USE, E_USE);
|
||||
(pIcode+1)->du.use |= (pIcode+2)->du.use;
|
||||
|
||||
/* Adjust outEdges[0] to the new target basic block */
|
||||
pbb = icodes[0]->getParent();
|
||||
if (pbb->back().loc_ip == icodes[1]->loc_ip)
|
||||
pbb = pIcode->inBB;
|
||||
if ((pbb->start + pbb->length - 1) == (*idx + 1))
|
||||
{
|
||||
/* Find intermediate and target basic blocks */
|
||||
obb1 = pbb->edges[THEN].BBptr;
|
||||
@ -194,364 +213,352 @@ static int longJCond22 (Assignment &asgn, iICODE pIcode,iICODE pEnd)
|
||||
pbb->edges[THEN].BBptr = tbb;
|
||||
|
||||
/* Modify in edges of target basic block */
|
||||
auto iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb1);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter);
|
||||
|
||||
if (icodes[3]->ll()->getOpcode() != iJE)
|
||||
tbb->inEdges.push_back(pbb); /* iJNE => replace arc */
|
||||
for (j = 0; j < (tbb->numInEdges-1); j++)
|
||||
{
|
||||
if (tbb->inEdges[j] == obb1)
|
||||
{
|
||||
memmove (&tbb->inEdges[j], &tbb->inEdges[j+1],
|
||||
(tbb->numInEdges - j-1) * sizeof(PBB));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((pIcode+3)->ic.ll.opcode == iJE)
|
||||
tbb->numInEdges--; /* looses 1 arc */
|
||||
else /* iJNE => replace arc */
|
||||
tbb->inEdges[tbb->numInEdges-1] = pbb;
|
||||
|
||||
/* Modify ELSE out edge of header basic block */
|
||||
tbb = obb1->edges[ELSE].BBptr;
|
||||
pbb->edges[ELSE].BBptr = tbb;
|
||||
|
||||
iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb1);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter);
|
||||
if (icodes[3]->ll()->getOpcode() == iJE) /* replace */
|
||||
tbb->inEdges.push_back(pbb);
|
||||
/* Modify in edges of the ELSE basic block */
|
||||
for (j = 0; j < (tbb->numInEdges-1); j++)
|
||||
{
|
||||
if (tbb->inEdges[j] == obb1)
|
||||
{
|
||||
memmove (&tbb->inEdges[j], &tbb->inEdges[j+1],
|
||||
(tbb->numInEdges - j-1) * sizeof(PBB));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((pIcode+3)->ic.ll.opcode == iJE) /* replace */
|
||||
tbb->inEdges[tbb->numInEdges-1] = pbb;
|
||||
else
|
||||
tbb->numInEdges--; /* iJNE => looses 1 arc */
|
||||
|
||||
|
||||
/* Update statistics */
|
||||
obb1->flg |= INVALID_BB;
|
||||
stats.numBBaft--;
|
||||
}
|
||||
|
||||
icodes[0]->invalidate();
|
||||
icodes[2]->invalidate();
|
||||
icodes[3]->invalidate();
|
||||
return 4;
|
||||
invalidateIcode (pIcode);
|
||||
invalidateIcode (pIcode+2);
|
||||
invalidateIcode (pIcode+3);
|
||||
(*idx) += 4;
|
||||
}
|
||||
|
||||
|
||||
static void propLongStk (Int i, ID *pLocId, PPROC pProc)
|
||||
/* Propagates TYPE_LONG_(UN)SIGN icode information to the current pIcode
|
||||
* Pointer.
|
||||
* Arguments: i : index into the local identifier table
|
||||
* pLocId: ptr to the long local identifier
|
||||
* pProc : ptr to current procedure's record. */
|
||||
void Function::propLongStk (int i, const ID &pLocId)
|
||||
{
|
||||
int arc;
|
||||
Assignment asgn;
|
||||
//COND_EXPR *lhs, *rhs; /* Pointers to left and right hand expression */
|
||||
iICODE next1, pEnd;
|
||||
iICODE l23;
|
||||
{ Int idx, off, arc;
|
||||
COND_EXPR *lhs, *rhs; /* Pointers to left and right hand expression */
|
||||
PICODE pIcode, pEnd;
|
||||
|
||||
/* Check all icodes for offHi:offLo */
|
||||
pEnd = Icode.end();
|
||||
int stat_size=Icode.size();
|
||||
// for (idx = 0; idx < (Icode.size() - 1); idx++)
|
||||
for(auto pIcode = Icode.begin(); ;++pIcode)
|
||||
pEnd = pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() -1);
|
||||
for (idx = 0; idx < (pProc->Icode.GetNumIcodes() - 1); idx++)
|
||||
{
|
||||
assert(Icode.size()==stat_size);
|
||||
next1 = ++iICODE(pIcode);
|
||||
if(next1==pEnd)
|
||||
break;
|
||||
if ((pIcode->type == HIGH_LEVEL) || ( not pIcode->valid() ))
|
||||
pIcode = pProc->Icode.GetIcode(idx);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
if (pIcode->ll()->getOpcode() == next1->ll()->getOpcode())
|
||||
{
|
||||
if (checkLongEq (pLocId.id.longStkId, pIcode, i, this, asgn, *next1->ll()) == true)
|
||||
{
|
||||
switch (pIcode->ll()->getOpcode())
|
||||
|
||||
if (pIcode->ic.ll.opcode == (pIcode+1)->ic.ll.opcode)
|
||||
{
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iMOV:
|
||||
pIcode->setAsgn(asgn.lhs, asgn.rhs);
|
||||
next1->invalidate();
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
switch (pIcode->ll()->getOpcode())
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
case iAND: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, AND); break;
|
||||
case iOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, OR); break;
|
||||
case iXOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, XOR); break;
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = boolCondExp (lhs, rhs, AND);
|
||||
break;
|
||||
case iOR: rhs = boolCondExp (lhs, rhs, OR);
|
||||
break;
|
||||
case iXOR: rhs = boolCondExp (lhs, rhs, XOR);
|
||||
break;
|
||||
}
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx++;
|
||||
}
|
||||
pIcode->setAsgn(asgn.lhs, asgn.rhs);
|
||||
next1->invalidate();
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
pIcode->setUnary( HLI_PUSH, asgn.lhs);
|
||||
next1->invalidate();
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
newUnaryHlIcode (pIcode, HLI_PUSH, lhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Wild ass checkLongEq success on opcode %d\n",pIcode->ll()->getOpcode());
|
||||
} /*eos*/
|
||||
}
|
||||
}
|
||||
//TODO: Simplify this!
|
||||
|
||||
/* Check long conditional (i.e. 2 CMPs and 3 branches */
|
||||
else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), l23, &arc)))
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
(isLong23 (idx, pIcode->inBB, pProc->Icode.GetFirstIcode(),
|
||||
&off, &arc)))
|
||||
{
|
||||
if ( checkLongEq (pLocId.id.longStkId, pIcode, i, this, asgn, *l23->ll()) )
|
||||
{
|
||||
advance(pIcode,longJCond23 (asgn, pIcode, arc, l23));
|
||||
}
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, pProc, arc, off);
|
||||
}
|
||||
|
||||
/* Check for long conditional equality or inequality. This requires
|
||||
* 2 CMPs and 2 branches */
|
||||
else if ((pIcode->ll()->getOpcode() == iCMP) && isLong22 (pIcode, pEnd, l23))
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
isLong22 (pIcode, pEnd, &off))
|
||||
{
|
||||
if ( checkLongEq (pLocId.id.longStkId, pIcode, i, this,asgn, *l23->ll()) )
|
||||
{
|
||||
advance(pIcode,longJCond22 (asgn, pIcode,pEnd));
|
||||
}
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond22 (rhs, lhs, pIcode, &idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
int Function::findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE beg)
|
||||
{
|
||||
Assignment asgn;
|
||||
LLOperand * pmH,* pmL;
|
||||
iICODE pIcode;
|
||||
riICODE rev(beg);
|
||||
bool forced_finish=false;
|
||||
for (; not forced_finish and rev!=Icode.rend();rev++) //idx = pLocId_idx - 1; idx > 0 ; idx--
|
||||
|
||||
|
||||
static void propLongReg (Int i, ID *pLocId, PPROC pProc)
|
||||
/* Finds the definition of the long register pointed to by pLocId, and
|
||||
* transforms that instruction into a HIGH_LEVEL icode instruction.
|
||||
* Arguments: i : index into the local identifier table
|
||||
* pLocId: ptr to the long local identifier
|
||||
* pProc : ptr to current procedure's record. */
|
||||
{ COND_EXPR *lhs, *rhs;
|
||||
Int idx, j, off, arc;
|
||||
PICODE pIcode, pEnd;
|
||||
PMEM pmH, pmL; /* Pointers to dst LOW_LEVEL icodes */
|
||||
|
||||
/* Process all definitions/uses of long registers at an icode position */
|
||||
pEnd = pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() -1);
|
||||
for (j = 0; j < pLocId->idx.csym; j++)
|
||||
{
|
||||
pIcode = (++riICODE(rev)).base();//forward iterator from rev
|
||||
iICODE next1((++iICODE(pIcode))); // next instruction
|
||||
ICODE &icode(*pIcode);
|
||||
|
||||
|
||||
if ((icode.type == HIGH_LEVEL) || ( not icode.valid() ))
|
||||
continue;
|
||||
if (icode.ll()->getOpcode() != next1->ll()->getOpcode())
|
||||
/* Check backwards for a definition of this long register */
|
||||
for (idx = pLocId->idx.idx[j] - 1; idx > 0 ; idx--)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx-1);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
switch (icode.ll()->getOpcode())
|
||||
{
|
||||
if (pIcode->ic.ll.opcode == (pIcode+1)->ic.ll.opcode)
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iMOV:
|
||||
pmH = &icode.ll()->dst;
|
||||
pmL = &next1->ll()->dst;
|
||||
if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi))
|
||||
pmH = &pIcode->ic.ll.dst;
|
||||
pmL = &(pIcode+1)->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) &&
|
||||
(pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
localId.id_arr[loc_ident_idx].idx.push_back(pIcode);//idx-1//insert
|
||||
icode.setRegDU( pmL->regi, eDEF);
|
||||
asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
asgn.rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, *next1->ll());
|
||||
icode.setAsgn(asgn.lhs, asgn.rhs);
|
||||
next1->invalidate();
|
||||
forced_finish=true; /* to exit the loop */
|
||||
lhs = idCondExpLongIdx (i);
|
||||
insertIdx (&pProc->localId.id[i].idx, idx-1);
|
||||
setRegDU (pIcode, pmL->regi, E_DEF);
|
||||
rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
|
||||
idx, E_USE, 1);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx = 0; /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case iPOP:
|
||||
pmH = &next1->ll()->dst;
|
||||
pmL = &icode.ll()->dst;
|
||||
if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi))
|
||||
pmH = &(pIcode+1)->ic.ll.dst;
|
||||
pmL = &pIcode->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) &&
|
||||
(pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
icode.setRegDU( pmH->regi, eDEF);
|
||||
icode.setUnary(HLI_POP, asgn.lhs);
|
||||
next1->invalidate();
|
||||
asgn.lhs=0;
|
||||
forced_finish=true; /* to exit the loop */
|
||||
lhs = idCondExpLongIdx (i);
|
||||
setRegDU (pIcode, pmH->regi, E_DEF);
|
||||
newUnaryHlIcode (pIcode, HLI_POP, lhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx = 0; /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
// /**** others missing ***/
|
||||
/**** others missing ***/
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
pmL = &icode.ll()->dst;
|
||||
pmH = &next1->ll()->dst;
|
||||
if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi))
|
||||
pmL = &pIcode->ic.ll.dst;
|
||||
pmH = &(pIcode+1)->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) &&
|
||||
(pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
asgn.rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, LOW_FIRST, pIcode, eUSE, *next1->ll());
|
||||
icode.setRegDU( pmH->regi, USE_DEF);
|
||||
switch (icode.ll()->getOpcode())
|
||||
{
|
||||
case iAND: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, AND);
|
||||
lhs = idCondExpLongIdx (i);
|
||||
setRegDU (pIcode, pmH->regi, USE_DEF);
|
||||
rhs = idCondExpLong (&pProc->localId, SRC, pIcode, LOW_FIRST,
|
||||
idx, E_USE, 1);
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = boolCondExp (lhs, rhs, AND);
|
||||
break;
|
||||
case iOR:
|
||||
asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, OR);
|
||||
case iOR: rhs = boolCondExp (lhs, rhs, OR);
|
||||
break;
|
||||
case iXOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, XOR);
|
||||
case iXOR: rhs = boolCondExp (lhs, rhs, XOR);
|
||||
break;
|
||||
} /* eos */
|
||||
icode.setAsgn(asgn.lhs, asgn.rhs);
|
||||
next1->invalidate();
|
||||
forced_finish=true; /* to exit the loop */
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx = 0;
|
||||
}
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
return rev!=Icode.rend();
|
||||
}
|
||||
int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg)
|
||||
{
|
||||
bool forced_finish=false;
|
||||
auto pEnd=Icode.end();
|
||||
iICODE long_loc;
|
||||
Assignment asgn;
|
||||
for (auto pIcode=beg; not forced_finish; ++pIcode)
|
||||
{
|
||||
iICODE next1(++iICODE(pIcode));
|
||||
if(next1==pEnd)
|
||||
break;
|
||||
LLOperand * pmH,* pmL; /* Pointers to dst LOW_LEVEL icodes */
|
||||
int arc;
|
||||
|
||||
if ((pIcode->type == HIGH_LEVEL) || ( not pIcode->valid() ))
|
||||
/* If no definition backwards, check forward for a use of this long reg */
|
||||
if (idx <= 0)
|
||||
for (idx = pLocId->idx.idx[j] + 1; idx < pProc->Icode.GetNumIcodes() - 1; idx++)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
if (pIcode->ll()->getOpcode() == next1->ll()->getOpcode())
|
||||
switch (pIcode->ll()->getOpcode())
|
||||
{
|
||||
if (pIcode->ic.ll.opcode == (pIcode+1)->ic.ll.opcode)
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iMOV:
|
||||
if ((pLocId.id.longId.h == pIcode->ll()->src().getReg2()) &&
|
||||
(pLocId.id.longId.l == next1->ll()->src().getReg2()))
|
||||
if ((pLocId->id.longId.h == pIcode->ic.ll.src.regi) &&
|
||||
(pLocId->id.longId.l == (pIcode+1)->ic.ll.src.regi))
|
||||
{
|
||||
pIcode->setRegDU( next1->ll()->src().getReg2(), eUSE);
|
||||
|
||||
asgn.rhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
asgn.lhs = COND_EXPR::idLong (&this->localId, DST, pIcode,HIGH_FIRST, pIcode, eDEF, *next1->ll());
|
||||
|
||||
pIcode->setAsgn(asgn.lhs, asgn.rhs);
|
||||
next1->invalidate();
|
||||
forced_finish =true; /* to exit the loop */
|
||||
rhs = idCondExpLongIdx (i);
|
||||
setRegDU (pIcode, (pIcode+1)->ic.ll.src.regi, E_USE);
|
||||
lhs = idCondExpLong (&pProc->localId, DST, pIcode,
|
||||
HIGH_FIRST, idx, E_DEF, 1);
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
if ((pLocId.id.longId.h == pIcode->ll()->src().getReg2()) &&
|
||||
(pLocId.id.longId.l == next1->ll()->src().getReg2()))
|
||||
if ((pLocId->id.longId.h == pIcode->ic.ll.src.regi) &&
|
||||
(pLocId->id.longId.l == (pIcode+1)->ic.ll.src.regi))
|
||||
{
|
||||
asgn.rhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
pIcode->setRegDU( next1->ll()->src().getReg2(), eUSE);
|
||||
pIcode->setUnary(HLI_PUSH, asgn.rhs);
|
||||
next1->invalidate();
|
||||
rhs = idCondExpLongIdx (i);
|
||||
setRegDU (pIcode, (pIcode+1)->ic.ll.src.regi, E_USE);
|
||||
newUnaryHlIcode (pIcode, HLI_PUSH, lhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
}
|
||||
forced_finish =true; /* to exit the loop */
|
||||
idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
break;
|
||||
|
||||
/*** others missing ****/
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
pmL = &pIcode->ll()->dst;
|
||||
pmH = &next1->ll()->dst;
|
||||
if ((pLocId.id.longId.h == pmH->regi) &&
|
||||
(pLocId.id.longId.l == pmL->regi))
|
||||
pmL = &pIcode->ic.ll.dst;
|
||||
pmH = &(pIcode+1)->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) &&
|
||||
(pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
pIcode->setRegDU( pmH->regi, USE_DEF);
|
||||
asgn.rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode,
|
||||
LOW_FIRST, pIcode, eUSE, *next1->ll());
|
||||
switch (pIcode->ll()->getOpcode()) {
|
||||
case iAND: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, AND);
|
||||
lhs = idCondExpLongIdx (i);
|
||||
setRegDU (pIcode, pmH->regi, USE_DEF);
|
||||
rhs = idCondExpLong (&pProc->localId, SRC, pIcode,
|
||||
LOW_FIRST, idx, E_USE, 1);
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = boolCondExp (lhs, rhs, AND);
|
||||
break;
|
||||
case iOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, OR);
|
||||
case iOR: rhs = boolCondExp (lhs, rhs, OR);
|
||||
break;
|
||||
case iXOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, XOR);
|
||||
case iXOR: rhs = boolCondExp (lhs, rhs, XOR);
|
||||
break;
|
||||
}
|
||||
pIcode->setAsgn(asgn.lhs, asgn.rhs);
|
||||
next1->invalidate();
|
||||
// ftw loop restart ????
|
||||
//idx = 0;
|
||||
// maybe this should end the loop instead
|
||||
forced_finish =true; /* to exit the loop */
|
||||
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||
invalidateIcode (pIcode + 1);
|
||||
idx = 0;
|
||||
}
|
||||
break;
|
||||
} /* eos */
|
||||
|
||||
/* Check long conditional (i.e. 2 CMPs and 3 branches */
|
||||
else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), long_loc, &arc)))
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
(isLong23 (idx, pIcode->inBB, pProc->Icode.GetFirstIcode(),
|
||||
&off, &arc)))
|
||||
{
|
||||
if (checkLongRegEq (pLocId.id.longId, pIcode, loc_ident_idx, this, asgn, *long_loc->ll()))
|
||||
{
|
||||
// reduce the advance by 1 here (loop increases) ?
|
||||
advance(pIcode,longJCond23 (asgn, pIcode, arc, long_loc));
|
||||
}
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, pProc, arc, off);
|
||||
}
|
||||
|
||||
/* Check for long conditional equality or inequality. This requires
|
||||
* 2 CMPs and 2 branches */
|
||||
else if (pIcode->ll()->match(iCMP) && (isLong22 (pIcode, pEnd, long_loc)))
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
(isLong22 (pIcode, pEnd, &off)))
|
||||
{
|
||||
if (checkLongRegEq (pLocId.id.longId, pIcode, loc_ident_idx, this, asgn, *long_loc->ll()) )
|
||||
{
|
||||
// TODO: verify that removing -1 does not change anything !
|
||||
advance(pIcode,longJCond22 (asgn, pIcode,pEnd));
|
||||
}
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond22 (rhs, lhs, pIcode, &idx);
|
||||
}
|
||||
|
||||
/* Check for OR regH, regL
|
||||
* JX lab
|
||||
* => HLI_JCOND (regH:regL X 0) lab
|
||||
* This is better code than HLI_JCOND (HI(regH:regL) | LO(regH:regL)) */
|
||||
else if (pIcode->ll()->match(iOR) && (next1 != pEnd) && (isJCond ((llIcode)next1->ll()->getOpcode())))
|
||||
else if ((pIcode->ic.ll.opcode == iOR) && ((pIcode+1) < pEnd) &&
|
||||
(isJCond ((pIcode+1)->ic.ll.opcode)))
|
||||
{
|
||||
if (pLocId.id.longId.srcDstRegMatch(pIcode,pIcode))
|
||||
if ((pIcode->ic.ll.dst.regi == pLocId->id.longId.h) &&
|
||||
(pIcode->ic.ll.src.regi == pLocId->id.longId.l))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx);
|
||||
asgn.rhs = COND_EXPR::idKte (0, 4); /* long 0 */
|
||||
asgn.lhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, condOpJCond[next1->ll()->getOpcode() - iJB]);
|
||||
next1->setJCond(asgn.lhs);
|
||||
next1->copyDU(*pIcode, eUSE, eUSE);
|
||||
pIcode->invalidate();
|
||||
lhs = idCondExpLongIdx (i);
|
||||
rhs = idCondExpKte (0, 4); /* long 0 */
|
||||
lhs = boolCondExp (lhs, rhs,
|
||||
condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]);
|
||||
newJCondHlIcode (pIcode+1, lhs);
|
||||
copyDU (pIcode+1, pIcode, E_USE, E_USE);
|
||||
invalidateIcode (pIcode);
|
||||
}
|
||||
}
|
||||
} /* end for */
|
||||
}
|
||||
|
||||
/** Finds the definition of the long register pointed to by pLocId, and
|
||||
* transforms that instruction into a HIGH_LEVEL icode instruction.
|
||||
* @arg i index into the local identifier table
|
||||
* @arg pLocId ptr to the long local identifier
|
||||
*
|
||||
*/
|
||||
void Function::propLongReg (int loc_ident_idx, const ID &pLocId)
|
||||
{
|
||||
/* Process all definitions/uses of long registers at an icode position */
|
||||
// WARNING: this loop modifies the iterated-over container.
|
||||
size_t initial_size=pLocId.idx.size();
|
||||
for (int j = 0; j < pLocId.idx.size(); j++)
|
||||
{
|
||||
auto idx_iter=pLocId.idx.begin();
|
||||
std::advance(idx_iter,j);
|
||||
/* Check backwards for a definition of this long register */
|
||||
if (findBackwarLongDefs(loc_ident_idx,pLocId,*idx_iter))
|
||||
{
|
||||
//assert(initial_size==pLocId.idx.size());
|
||||
continue;
|
||||
}
|
||||
/* If no definition backwards, check forward for a use of this long reg */
|
||||
findForwardLongUses(loc_ident_idx,pLocId,*idx_iter);
|
||||
//assert(initial_size==pLocId.idx.size());
|
||||
} /* end for */
|
||||
} /* end for */
|
||||
}
|
||||
|
||||
|
||||
static void propLongGlb (Int i, ID *pLocId, PPROC pProc)
|
||||
/* Propagates the long global address across all LOW_LEVEL icodes.
|
||||
* Transforms some LOW_LEVEL icodes into HIGH_LEVEL */
|
||||
void Function::propLongGlb (int i, const ID &pLocId)
|
||||
{
|
||||
printf("WARN: Function::propLongGlb not implemented");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void propLong (PPROC pProc)
|
||||
/* Propagated identifier information, thus converting some LOW_LEVEL icodes
|
||||
* into HIGH_LEVEL icodes. */
|
||||
void Function::propLong()
|
||||
{
|
||||
int i;
|
||||
/* Pointer to current local identifier */
|
||||
{ Int i;
|
||||
ID *pLocId; /* Pointer to current local identifier */
|
||||
|
||||
for (i = 0; i < localId.csym(); i++)
|
||||
for (i = 0; i < pProc->localId.csym; i++)
|
||||
{
|
||||
const ID &pLocId(localId.id_arr[i]);
|
||||
if ((pLocId.type==TYPE_LONG_SIGN) || (pLocId.type==TYPE_LONG_UNSIGN))
|
||||
pLocId = &pProc->localId.id[i];
|
||||
if ((pLocId->type==TYPE_LONG_SIGN) || (pLocId->type==TYPE_LONG_UNSIGN))
|
||||
{
|
||||
switch (pLocId.loc)
|
||||
{
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId);
|
||||
switch (pLocId->loc) {
|
||||
case STK_FRAME: propLongStk (i, pLocId, pProc);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId);
|
||||
case REG_FRAME: propLongReg (i, pLocId, pProc);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId);
|
||||
case GLB_FRAME: propLongGlb (i, pLocId, pProc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,129 +3,154 @@
|
||||
* constructs an equivalent reducible graph if one is not found.
|
||||
* (C) Cristina Cifuentes
|
||||
********************************************************************/
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "dcc.h"
|
||||
#include <stdio.h>
|
||||
#ifdef __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h> /* For free() */
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
static int numInt; /* Number of intervals */
|
||||
static Int numInt; /* Number of intervals */
|
||||
|
||||
|
||||
#define nonEmpty(q) (q != NULL)
|
||||
/* Returns whether the queue q is empty or not */
|
||||
bool trivialGraph(BB *G)
|
||||
{
|
||||
return G->edges.empty();
|
||||
}
|
||||
|
||||
#define trivialGraph(G) (G->numOutEdges == 0)
|
||||
/* Returns whether the graph is a trivial graph or not */
|
||||
|
||||
|
||||
static BB *firstOfQueue (queue **Q)
|
||||
/* Returns the first element in the queue Q, and removes this element
|
||||
* from the list. Q is not an empty queue. */
|
||||
static BB *firstOfQueue (queue &Q)
|
||||
{
|
||||
assert(!Q.empty());
|
||||
BB *res=Q.front();
|
||||
Q.pop_front();
|
||||
return res;
|
||||
{ queue *elim;
|
||||
BB *first;
|
||||
|
||||
elim = *Q; /* Pointer to first node */
|
||||
first = (*Q)->node; /* First element */
|
||||
*Q = (*Q)->next; /* Pointer to next node */
|
||||
free (elim); /* Free storage */
|
||||
return (first);
|
||||
}
|
||||
|
||||
|
||||
queue *appendQueue (queue **Q, BB *node)
|
||||
/* Appends pointer to node at the end of the queue Q if node is not present
|
||||
* in this queue. Returns the queue node just appended. */
|
||||
queue::iterator appendQueue (queue &Q, BB *node)
|
||||
{
|
||||
auto iter=std::find(Q.begin(),Q.end(),node);
|
||||
if(iter!=Q.end())
|
||||
return iter;
|
||||
Q.push_back(node);
|
||||
iter=Q.end();
|
||||
--iter;
|
||||
return iter;
|
||||
{ queue *pq, *l;
|
||||
|
||||
pq = allocStruc(queue);
|
||||
pq->node = node;
|
||||
pq->next = NULL;
|
||||
|
||||
if (Q)
|
||||
if (*Q)
|
||||
{
|
||||
for (l = *Q; l->next && l->node != node; l = l->next)
|
||||
;
|
||||
if (l->node != node)
|
||||
l->next = pq;
|
||||
}
|
||||
else /* (*Q) == NULL */
|
||||
*Q = pq;
|
||||
return (pq);
|
||||
}
|
||||
|
||||
|
||||
static BB *firstOfInt (interval *pI)
|
||||
/* Returns the next unprocessed node of the interval list (pointed to by
|
||||
* pI->currNode). Removes this element logically from the list, by updating
|
||||
* the currNode pointer to the next unprocessed element. */
|
||||
BB *interval::firstOfInt ()
|
||||
{
|
||||
auto pq = currNode;
|
||||
if (pq == nodes.end())
|
||||
return 0;
|
||||
++currNode;
|
||||
return *pq;
|
||||
{ queue *pq;
|
||||
|
||||
pq = pI->currNode;
|
||||
if (pq == NULL)
|
||||
return (NULL);
|
||||
pI->currNode = pq->next;
|
||||
return (pq->node);
|
||||
}
|
||||
|
||||
|
||||
/* Appends node @node to the end of the interval list @pI, updates currNode
|
||||
* if necessary, and removes the node from the header list @pqH if it is
|
||||
static queue *appendNodeInt (queue *pqH, BB *node, interval *pI)
|
||||
/* Appends node node to the end of the interval list I, updates currNode
|
||||
* if necessary, and removes the node from the header list H if it is
|
||||
* there. The interval header information is placed in the field
|
||||
* node->inInterval.
|
||||
* Note: nodes are added to the interval list in interval order (which
|
||||
* topsorts the dominance relation). */
|
||||
static void appendNodeInt (queue &pqH, BB *node, interval *pI)
|
||||
{
|
||||
queue::iterator pq; /* Pointer to current node of the list */
|
||||
{ queue *pq, /* Pointer to current node of the list */
|
||||
*prev; /* Pointer to previous node in the list */
|
||||
|
||||
/* Append node if it is not already in the interval list */
|
||||
pq = appendQueue (pI->nodes, node);
|
||||
pq = appendQueue (&pI->nodes, node);
|
||||
|
||||
/* Update currNode if necessary */
|
||||
if (pI->currNode == pI->nodes.end())
|
||||
if (pI->currNode == NULL)
|
||||
pI->currNode = pq;
|
||||
|
||||
/* Check header list for occurrence of node, if found, remove it
|
||||
* and decrement number of out-edges from this interval. */
|
||||
if (node->beenOnH && !pqH.empty())
|
||||
if (node->beenOnH && pqH)
|
||||
{
|
||||
auto found_iter=std::find(pqH.begin(),pqH.end(),node);
|
||||
if(found_iter!=pqH.end())
|
||||
prev = pqH;
|
||||
for (pq = prev; pq && pq->node != node; pq = pq->next)
|
||||
prev = pq;
|
||||
if (pq == prev)
|
||||
{
|
||||
pI->numOutEdges -= (uint8_t)(*found_iter)->inEdges.size() - 1;
|
||||
pqH.erase(found_iter);
|
||||
pqH = pqH->next;
|
||||
pI->numOutEdges -= (byte)pq->node->numInEdges - 1;
|
||||
}
|
||||
else if (pq)
|
||||
{
|
||||
prev->next = pq->next;
|
||||
pI->numOutEdges -= (byte)pq->node->numInEdges - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update interval header information for this basic block */
|
||||
node->inInterval = pI;
|
||||
|
||||
return (pqH);
|
||||
}
|
||||
|
||||
|
||||
static void findIntervals (derSeq *derivedGi)
|
||||
/* Finds the intervals of graph derivedGi->Gi and places them in the list
|
||||
* of intervals derivedGi->Ii.
|
||||
* Algorithm by M.S.Hecht. */
|
||||
void derSeq_Entry::findIntervals (Function *c)
|
||||
{
|
||||
interval *pI, /* Interval being processed */
|
||||
{ interval *pI, /* Interval being processed */
|
||||
*J; /* ^ last interval in derivedGi->Ii */
|
||||
BB *h, /* Node being processed */
|
||||
*header, /* Current interval's header node */
|
||||
*succ; /* Successor basic block */
|
||||
int i; /* Counter */
|
||||
queue H; /* Queue of possible header nodes */
|
||||
boolT first = true; /* First pass through the loop */
|
||||
Int i; /* Counter */
|
||||
queue *H; /* Queue of possible header nodes */
|
||||
boolT first = TRUE; /* First pass through the loop */
|
||||
|
||||
appendQueue (H, Gi); /* H = {first node of G} */
|
||||
Gi->beenOnH = true;
|
||||
Gi->reachingInt = BB::Create(0,"",c); /* ^ empty BB */
|
||||
H = appendQueue (NULL, derivedGi->Gi); /* H = {first node of G} */
|
||||
derivedGi->Gi->beenOnH = TRUE;
|
||||
derivedGi->Gi->reachingInt = allocStruc(BB); /* ^ empty BB */
|
||||
memset (derivedGi->Gi->reachingInt, 0, sizeof(BB));
|
||||
|
||||
/* Process header nodes list H */
|
||||
while (!H.empty())
|
||||
while (nonEmpty (H))
|
||||
{
|
||||
header = firstOfQueue (H);
|
||||
pI = new interval;
|
||||
pI->numInt = (uint8_t)numInt++;
|
||||
header = firstOfQueue (&H);
|
||||
pI = allocStruc(interval);
|
||||
memset (pI, 0, sizeof(interval));
|
||||
pI->numInt = (byte)numInt++;
|
||||
if (first) /* ^ to first interval */
|
||||
Ii = J = pI;
|
||||
appendNodeInt (H, header, pI); /* pI(header) = {header} */
|
||||
derivedGi->Ii = J = pI;
|
||||
H = appendNodeInt (H, header, pI); /* pI(header) = {header} */
|
||||
|
||||
/* Process all nodes in the current interval list */
|
||||
while ((h = pI->firstOfInt()) != NULL)
|
||||
while ((h = firstOfInt (pI)) != NULL)
|
||||
{
|
||||
/* Check all immediate successors of h */
|
||||
for (i = 0; i < h->edges.size(); i++)
|
||||
for (i = 0; i < h->numOutEdges; i++)
|
||||
{
|
||||
succ = h->edges[i].BBptr;
|
||||
succ->inEdgeCount--;
|
||||
@ -134,21 +159,22 @@ void derSeq_Entry::findIntervals (Function *c)
|
||||
{
|
||||
succ->reachingInt = header;
|
||||
if (succ->inEdgeCount == 0)
|
||||
appendNodeInt (H, succ, pI);
|
||||
H = appendNodeInt (H, succ, pI);
|
||||
else if (! succ->beenOnH) /* out edge */
|
||||
{
|
||||
appendQueue (H, succ);
|
||||
succ->beenOnH = true;
|
||||
appendQueue (&H, succ);
|
||||
succ->beenOnH = TRUE;
|
||||
pI->numOutEdges++;
|
||||
}
|
||||
}
|
||||
else /* node has been visited before */
|
||||
if (succ->inEdgeCount == 0)
|
||||
{
|
||||
if (succ->reachingInt == header || succ->inInterval == pI) /* same interval */
|
||||
if (succ->reachingInt == header ||
|
||||
succ->inInterval == pI) /* same interval */
|
||||
{
|
||||
if (succ != header)
|
||||
appendNodeInt (H, succ, pI);
|
||||
H = appendNodeInt (H, succ, pI);
|
||||
}
|
||||
else /* out edge */
|
||||
pI->numOutEdges++;
|
||||
@ -165,119 +191,128 @@ void derSeq_Entry::findIntervals (Function *c)
|
||||
J = pI;
|
||||
}
|
||||
else /* first interval */
|
||||
first = false;
|
||||
first = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Displays the intervals of the graph Gi. */
|
||||
static void displayIntervals (interval *pI)
|
||||
{
|
||||
/* Displays the intervals of the graph Gi. */
|
||||
{ queue *nodePtr;
|
||||
|
||||
while (pI)
|
||||
{
|
||||
printf (" Interval #: %ld\t#OutEdges: %ld\n", pI->numInt, pI->numOutEdges);
|
||||
for(BB *node : pI->nodes)
|
||||
nodePtr = pI->nodes;
|
||||
printf (" Interval #: %ld\t#OutEdges: %ld\n",
|
||||
pI->numInt, pI->numOutEdges);
|
||||
|
||||
while (nodePtr)
|
||||
{
|
||||
if (node->correspInt == NULL) /* real BBs */
|
||||
printf (" Node: %ld\n", node->begin()->loc_ip);
|
||||
else // BBs represent intervals
|
||||
printf (" Node (corresp int): %d\n", node->correspInt->numInt);
|
||||
if (nodePtr->node->correspInt == NULL) /* real BBs */
|
||||
printf (" Node: %ld\n", nodePtr->node->start);
|
||||
else /* BBs represent intervals */
|
||||
printf (" Node (corresp int): %d\n",
|
||||
nodePtr->node->correspInt->numInt);
|
||||
nodePtr = nodePtr->next;
|
||||
}
|
||||
pI = pI->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static derSeq *newDerivedSeq()
|
||||
/* Allocates space for a new derSeq node. */
|
||||
static derSeq_Entry *newDerivedSeq()
|
||||
{
|
||||
return new derSeq_Entry;
|
||||
{ derSeq *pder;
|
||||
|
||||
pder = allocStruc(derSeq);
|
||||
memset (pder, 0, sizeof(derSeq));
|
||||
return (pder);
|
||||
}
|
||||
|
||||
|
||||
static void freeQueue (queue **q)
|
||||
/* Frees the storage allocated for the queue q*/
|
||||
static void freeQueue (queue &q)
|
||||
{
|
||||
q.clear();
|
||||
}
|
||||
{ queue *queuePtr;
|
||||
|
||||
|
||||
/* Frees the storage allocated for the interval pI */
|
||||
static void freeInterval (interval **pI)
|
||||
{
|
||||
interval *Iptr;
|
||||
|
||||
while (*pI)
|
||||
for (queuePtr = *q; queuePtr; queuePtr = *q)
|
||||
{
|
||||
(*pI)->nodes.clear();
|
||||
Iptr = *pI;
|
||||
*pI = (*pI)->next;
|
||||
delete (Iptr);
|
||||
*q = (*q)->next;
|
||||
free (queuePtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Frees the storage allocated by the derived sequence structure, except
|
||||
* for the original graph cfg (derivedG->Gi). */
|
||||
void freeDerivedSeq(derSeq &derivedG)
|
||||
{
|
||||
derivedG.clear();
|
||||
}
|
||||
derSeq_Entry::~derSeq_Entry()
|
||||
{
|
||||
freeInterval (&Ii);
|
||||
// if(Gi && Gi->nodeType == INTERVAL_NODE)
|
||||
// freeCFG (Gi);
|
||||
static void freeInterval (interval **pI)
|
||||
/* Frees the storage allocated for the interval pI */
|
||||
{ interval *Iptr;
|
||||
|
||||
while (*pI)
|
||||
{
|
||||
freeQueue (&((*pI)->nodes));
|
||||
Iptr = *pI;
|
||||
*pI = (*pI)->next;
|
||||
free (Iptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void freeDerivedSeq(derSeq *derivedG)
|
||||
/* Frees the storage allocated by the derived sequence structure, except
|
||||
* for the original graph cfg (derivedG->Gi). */
|
||||
{ derSeq *derivedGi;
|
||||
|
||||
while (derivedG)
|
||||
{
|
||||
freeInterval (&(derivedG->Ii));
|
||||
if (derivedG->Gi->nodeType == INTERVAL_NODE)
|
||||
freeCFG (derivedG->Gi);
|
||||
derivedGi = derivedG;
|
||||
derivedG = derivedG->next;
|
||||
free (derivedGi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolT nextOrderGraph (derSeq *derivedGi)
|
||||
/* Finds the next order graph of derivedGi->Gi according to its intervals
|
||||
* (derivedGi->Ii), and places it in derivedGi->next->Gi. */
|
||||
bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
{
|
||||
interval *Ii; /* Interval being processed */
|
||||
{ interval *Ii; /* Interval being processed */
|
||||
BB *BBnode, /* New basic block of intervals */
|
||||
*curr, /* BB being checked for out edges */
|
||||
*succ /* Successor node */
|
||||
;
|
||||
//queue *listIi; /* List of intervals */
|
||||
int i, /* Index to outEdges array */
|
||||
*succ, /* Successor node */
|
||||
derInt;
|
||||
queue *listIi; /* List of intervals */
|
||||
Int i, /* Index to outEdges array */
|
||||
j; /* Index to successors */
|
||||
boolT sameGraph; /* Boolean, isomorphic graphs */
|
||||
|
||||
/* Process Gi's intervals */
|
||||
derSeq_Entry &prev_entry(derivedGi.back());
|
||||
derivedGi.push_back(derSeq_Entry());
|
||||
derSeq_Entry &new_entry(derivedGi.back());
|
||||
Ii = prev_entry.Ii;
|
||||
sameGraph = true;
|
||||
BBnode = 0;
|
||||
std::vector<BB *> bbs;
|
||||
while (Ii)
|
||||
{
|
||||
derivedGi->next = newDerivedSeq();
|
||||
Ii = derivedGi->Ii;
|
||||
sameGraph = TRUE;
|
||||
derInt.next = NULL;
|
||||
BBnode = &derInt;
|
||||
|
||||
while (Ii) {
|
||||
i = 0;
|
||||
bbs.push_back(BB::Create(-1, -1, INTERVAL_NODE, Ii->numOutEdges, this));
|
||||
BBnode = bbs.back();
|
||||
BBnode = newBB (BBnode, -1, -1, INTERVAL_NODE, Ii->numOutEdges, NULL);
|
||||
BBnode->correspInt = Ii;
|
||||
const queue &listIi(Ii->nodes);
|
||||
listIi = Ii->nodes;
|
||||
|
||||
/* Check for more than 1 interval */
|
||||
if (sameGraph && (listIi.size()>1))
|
||||
sameGraph = false;
|
||||
if (sameGraph && listIi->next)
|
||||
sameGraph = FALSE;
|
||||
|
||||
/* Find out edges */
|
||||
|
||||
if (BBnode->edges.size() > 0)
|
||||
{
|
||||
for(BB *curr : listIi)
|
||||
{
|
||||
for (j = 0; j < curr->edges.size(); j++)
|
||||
{
|
||||
if (BBnode->numOutEdges > 0)
|
||||
while (listIi) {
|
||||
curr = listIi->node;
|
||||
for (j = 0; j < curr->numOutEdges; j++) {
|
||||
succ = curr->edges[j].BBptr;
|
||||
if (succ->inInterval != curr->inInterval)
|
||||
BBnode->edges[i++].intPtr = succ->inInterval;
|
||||
}
|
||||
}
|
||||
listIi = listIi->next;
|
||||
}
|
||||
|
||||
/* Next interval */
|
||||
@ -287,104 +322,99 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
/* Convert list of pointers to intervals into a real graph.
|
||||
* Determines the number of in edges to each new BB, and places it
|
||||
* in numInEdges and inEdgeCount for later interval processing. */
|
||||
curr = new_entry.Gi = bbs.front();
|
||||
for(BB *curr : bbs)
|
||||
{
|
||||
for(TYPEADR_TYPE &edge : curr->edges)
|
||||
{
|
||||
BBnode = new_entry.Gi; /* BB of an interval */
|
||||
auto iter= std::find_if(bbs.begin(),bbs.end(),
|
||||
[&edge](BB *node)->bool { return edge.intPtr==node->correspInt;});
|
||||
if(iter==bbs.end())
|
||||
fatalError (INVALID_INT_BB);
|
||||
edge.BBptr = *iter;
|
||||
(*iter)->inEdges.push_back((BB *)nullptr);
|
||||
(*iter)->inEdgeCount++;
|
||||
curr = derivedGi->next->Gi = derInt.next;
|
||||
while (curr) {
|
||||
for (i = 0; i < curr->numOutEdges; i++) {
|
||||
BBnode = derivedGi->next->Gi; /* BB of an interval */
|
||||
while (BBnode && curr->edges[i].intPtr != BBnode->correspInt)
|
||||
BBnode = BBnode->next;
|
||||
if (BBnode) {
|
||||
curr->edges[i].BBptr = BBnode;
|
||||
BBnode->numInEdges++;
|
||||
BBnode->inEdgeCount++;
|
||||
}
|
||||
else
|
||||
fatalError (INVALID_INT_BB);
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
return (boolT)(! sameGraph);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static byte findDerivedSeq (derSeq *derivedGi)
|
||||
/* Finds the derived sequence of the graph derivedG->Gi (ie. cfg).
|
||||
* Constructs the n-th order graph and places all the intermediate graphs
|
||||
* in the derivedG list sequence. */
|
||||
uint8_t Function::findDerivedSeq (derSeq &derivedGi)
|
||||
{
|
||||
BB *Gi; /* Current derived sequence graph */
|
||||
{ BB *Gi; /* Current derived sequence graph */
|
||||
|
||||
derSeq::iterator iter=derivedGi.begin();
|
||||
Gi = iter->Gi;
|
||||
Gi = derivedGi->Gi;
|
||||
while (! trivialGraph (Gi))
|
||||
{
|
||||
/* Find the intervals of Gi and place them in derivedGi->Ii */
|
||||
iter->findIntervals(this);
|
||||
findIntervals (derivedGi);
|
||||
|
||||
/* Create Gi+1 and check if it is equivalent to Gi */
|
||||
if (! nextOrderGraph (derivedGi))
|
||||
break;
|
||||
++iter;
|
||||
Gi = iter->Gi;
|
||||
|
||||
derivedGi = derivedGi->next;
|
||||
Gi = derivedGi->Gi;
|
||||
stats.nOrder++;
|
||||
}
|
||||
|
||||
if (! trivialGraph (Gi))
|
||||
{
|
||||
++iter;
|
||||
derivedGi.erase(iter,derivedGi.end()); /* remove Gi+1 */
|
||||
// freeDerivedSeq(derivedGi->next);
|
||||
// derivedGi->next = NULL;
|
||||
return false;
|
||||
freeDerivedSeq(derivedGi->next); /* remove Gi+1 */
|
||||
derivedGi->next = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
derivedGi.back().findIntervals (this);
|
||||
return true;
|
||||
findIntervals (derivedGi);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void nodeSplitting (BB *G)
|
||||
/* Converts the irreducible graph G into an equivalent reducible one, by
|
||||
* means of node splitting. */
|
||||
static void nodeSplitting (std::list<BB *> &G)
|
||||
{
|
||||
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void displayDerivedSeq(derSeq *derGi)
|
||||
/* Displays the derived sequence and intervals of the graph G */
|
||||
void derSeq::display()
|
||||
{
|
||||
int n = 1; /* Derived sequence number */
|
||||
Int n = 1; /* Derived sequence number */
|
||||
printf ("\nDerived Sequence Intervals\n");
|
||||
derSeq::iterator iter=this->begin();
|
||||
while (iter!=this->end())
|
||||
while (derGi)
|
||||
{
|
||||
printf ("\nIntervals for G%lX\n", n++);
|
||||
displayIntervals (iter->Ii);
|
||||
++iter;
|
||||
displayIntervals (derGi->Ii);
|
||||
derGi = derGi->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void checkReducibility (PPROC pProc, derSeq **derivedG)
|
||||
/* Checks whether the control flow graph, cfg, is reducible or not.
|
||||
* If it is not reducible, it is converted into an equivalent reducible
|
||||
* graph by node splitting. The derived sequence of graphs built from cfg
|
||||
* are returned in the pointer *derivedG.
|
||||
*/
|
||||
derSeq * Function::checkReducibility()
|
||||
{
|
||||
derSeq * der_seq;
|
||||
uint8_t reducible; /* Reducible graph flag */
|
||||
{ byte reducible; /* Reducible graph flag */
|
||||
|
||||
numInt = 1; /* reinitialize no. of intervals*/
|
||||
stats.nOrder = 1; /* nOrder(cfg) = 1 */
|
||||
der_seq = new derSeq;
|
||||
der_seq->resize(1);
|
||||
der_seq->back().Gi = m_cfg.front();
|
||||
reducible = findDerivedSeq(*der_seq);
|
||||
*derivedG = newDerivedSeq();
|
||||
(*derivedG)->Gi = pProc->cfg;
|
||||
reducible = findDerivedSeq(*derivedG);
|
||||
|
||||
if (! reducible)
|
||||
{
|
||||
flg |= GRAPH_IRRED;
|
||||
nodeSplitting (m_cfg);
|
||||
if (! reducible) {
|
||||
pProc->flg |= GRAPH_IRRED;
|
||||
nodeSplitting (pProc->cfg);
|
||||
}
|
||||
return der_seq;
|
||||
}
|
||||
|
||||
|
||||
1040
src/scanner.cpp
1040
src/scanner.cpp
File diff suppressed because it is too large
Load Diff
630
src/symtab.cpp
630
src/symtab.cpp
@ -10,7 +10,7 @@
|
||||
\* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/* This file implements a symbol table with a symbolic name, a symbol value
|
||||
(uint16_t), and a procedure number. Two tables are maintained, to be able to
|
||||
(word), and a procedure number. Two tables are maintained, to be able to
|
||||
look up by name or by value. Pointers are used for the duplicated symbolic
|
||||
name to save space. Both tables have the same structure.
|
||||
The hash tables automatically expand when they get 90% full; they are
|
||||
@ -19,176 +19,564 @@
|
||||
Linear probing is used, due to the difficulty of implementing (e.g.)
|
||||
quadratic probing with a variable table size.
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dcc.h"
|
||||
#include "symtab.h"
|
||||
|
||||
#define TABLESIZE 16 /* Number of entries added each expansion */
|
||||
/* Probably has to be a power of 2 */
|
||||
/* Probably has to be a power of 2 */
|
||||
#define STRTABSIZE 256 /* Size string table is inc'd by */
|
||||
#define NIL ((uint16_t)-1)
|
||||
using namespace std;
|
||||
#define NIL ((word)-1)
|
||||
|
||||
|
||||
|
||||
static word numEntry; /* Number of entries in this table */
|
||||
static word tableSize; /* Size of the table (entries) */
|
||||
static SYMTABLE *symTab; /* Pointer to the symbol hashed table */
|
||||
static SYMTABLE *valTab; /* Pointer to the value hashed table */
|
||||
|
||||
static char *pStrTab; /* Pointer to the current string table */
|
||||
static int strTabNext; /* Next free index into pStrTab */
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<SYMTABLE> : public unary_function<const SYMTABLE &,size_t>
|
||||
{
|
||||
size_t operator()(const SYMTABLE & key) const
|
||||
{
|
||||
uint16_t h = 0;
|
||||
h = (uint16_t)(key.symOff ^ (key.symOff >> 8));
|
||||
return h;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
static tableType curTableType; /* Which table is current */
|
||||
struct TABLEINFO_TYPE
|
||||
typedef struct _tableInfo
|
||||
{
|
||||
TABLEINFO_TYPE()
|
||||
{
|
||||
symTab=valTab=0;
|
||||
}
|
||||
//void deleteVal(uint32_t symOff, Function *symProc, boolT bSymToo);
|
||||
void create(tableType type);
|
||||
void destroy();
|
||||
private:
|
||||
SYMTABLE *symTab;
|
||||
SYMTABLE *valTab;
|
||||
word numEntry;
|
||||
word tableSize;
|
||||
} TABLEINFO_TYPE;
|
||||
|
||||
SYMTABLE *symTab; /* Pointer to the symbol hashed table */
|
||||
SYMTABLE *valTab; /* Pointer to the value hashed table */
|
||||
uint16_t numEntry; /* Number of entries in this table */
|
||||
uint16_t tableSize;/* Size of the table (entries) */
|
||||
unordered_map<string,SYMTABLE> z;
|
||||
unordered_map<SYMTABLE,string> z2;
|
||||
};
|
||||
TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */
|
||||
|
||||
static TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */
|
||||
static TABLEINFO_TYPE currentTabInfo;
|
||||
|
||||
/* Local prototypes */
|
||||
static void expandSym(void);
|
||||
|
||||
/* Create a new symbol table. Returns "handle" */
|
||||
void TABLEINFO_TYPE::create(tableType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Comment:
|
||||
numEntry = 0;
|
||||
tableSize = TABLESIZE;
|
||||
valTab = new SYMTABLE [TABLESIZE];
|
||||
symTab = 0;
|
||||
break;
|
||||
case Label:
|
||||
currentTabInfo.numEntry = 0;
|
||||
currentTabInfo.tableSize = TABLESIZE;
|
||||
currentTabInfo.symTab = new SYMTABLE [TABLESIZE];
|
||||
currentTabInfo.valTab = new SYMTABLE [TABLESIZE];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void createSymTables(void)
|
||||
{
|
||||
/* Initilise the comment table */
|
||||
/* NB - there is no symbol hashed comment table */
|
||||
currentTabInfo.create(Comment);
|
||||
tableInfo[Comment] = currentTabInfo;
|
||||
|
||||
numEntry = 0;
|
||||
tableSize = TABLESIZE;
|
||||
valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
|
||||
memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE);
|
||||
|
||||
tableInfo[Comment].symTab = 0;
|
||||
tableInfo[Comment].valTab = valTab;
|
||||
tableInfo[Comment].numEntry = numEntry;
|
||||
tableInfo[Comment].tableSize = tableSize;
|
||||
|
||||
/* Initialise the label table */
|
||||
currentTabInfo.create(Label);
|
||||
numEntry = 0;
|
||||
tableSize = TABLESIZE;
|
||||
symTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
|
||||
memset(symTab, 0, sizeof(SYMTABLE) * TABLESIZE);
|
||||
|
||||
tableInfo[Label] = currentTabInfo;
|
||||
valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
|
||||
memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE);
|
||||
|
||||
tableInfo[Label].symTab = symTab;
|
||||
tableInfo[Label].valTab = valTab;
|
||||
tableInfo[Label].numEntry = numEntry;
|
||||
tableInfo[Label].tableSize = tableSize;
|
||||
curTableType = Label;
|
||||
|
||||
/* Now the string table */
|
||||
strTabNext = 0;
|
||||
pStrTab = new char[STRTABSIZE];
|
||||
pStrTab = (char *)allocMem(STRTABSIZE);
|
||||
|
||||
tableInfo[Label].symTab = symTab;
|
||||
tableInfo[Label].valTab = valTab;
|
||||
tableInfo[Label].numEntry = numEntry;
|
||||
tableInfo[Label].tableSize = tableSize;
|
||||
curTableType = Label;
|
||||
|
||||
}
|
||||
|
||||
void selectTable(tableType tt)
|
||||
void
|
||||
selectTable(tableType tt)
|
||||
{
|
||||
if (curTableType == tt)
|
||||
return; /* Nothing to do */
|
||||
currentTabInfo = tableInfo[tt];
|
||||
if (curTableType == tt) return; /* Nothing to do */
|
||||
|
||||
symTab = tableInfo[tt].symTab;
|
||||
valTab = tableInfo[tt].valTab;
|
||||
numEntry = tableInfo[tt].numEntry;
|
||||
tableSize= tableInfo[tt].tableSize;
|
||||
curTableType = tt;
|
||||
}
|
||||
void TABLEINFO_TYPE::destroy()
|
||||
{
|
||||
delete [] symTab; // The symbol hashed label table
|
||||
delete [] valTab; // And the value hashed label table
|
||||
}
|
||||
|
||||
void destroySymTables(void)
|
||||
{
|
||||
selectTable(Label);
|
||||
currentTabInfo.destroy();
|
||||
free(symTab); /* The symbol hashed label table */
|
||||
free(valTab); /* And the value hashed label table */
|
||||
selectTable(Comment);
|
||||
currentTabInfo.destroy();
|
||||
free(valTab); /* And the value hashed comment table */
|
||||
}
|
||||
|
||||
/* Using the value, read the symbolic name */
|
||||
boolT readVal(std::ostringstream &symName, uint32_t symOff, Function * symProc)
|
||||
{
|
||||
return false; // no symbolic names for now
|
||||
}
|
||||
|
||||
/* Updates the type of the symbol in the symbol table. The size is updated
|
||||
* if necessary (0 means no update necessary). */
|
||||
void SYMTAB::updateSymType (uint32_t symbol,const TypeContainer &tc)
|
||||
/* Hash the symbolic name */
|
||||
word symHash(char *name, word *pre)
|
||||
{
|
||||
int i;
|
||||
auto iter=findByLabel(symbol);
|
||||
if(iter==end())
|
||||
return;
|
||||
iter->type = tc.m_type;
|
||||
if (tc.m_size != 0)
|
||||
iter->size = tc.m_size;
|
||||
}
|
||||
word h = 0;
|
||||
char ch;
|
||||
|
||||
/* Creates an entry in the global symbol table (symtab) if the variable
|
||||
* is not there yet. If it is part of the symtab, the size of the variable
|
||||
* is checked and updated if the old size was less than the new size (ie.
|
||||
* the maximum size is always saved). */
|
||||
//TODO: SYMTAB::updateGlobSym should be renamed to insertOrUpdateSym
|
||||
SYM * SYMTAB::updateGlobSym (uint32_t operand, int size, uint16_t duFlag,bool &inserted_new)
|
||||
{
|
||||
/* Check for symbol in symbol table */
|
||||
auto iter = findByLabel(operand);
|
||||
if(iter!=end())
|
||||
for (i=0; i < (int)strlen(name); i++)
|
||||
{
|
||||
if(iter->size<size)
|
||||
iter->size = size;
|
||||
inserted_new=false;
|
||||
return &(*iter);
|
||||
ch = name[i];
|
||||
h = (h << 2) ^ ch;
|
||||
h += (ch >> 2) + (ch << 5);
|
||||
}
|
||||
|
||||
/* New symbol, not in symbol table */
|
||||
SYM v;
|
||||
char buf[32]={};
|
||||
sprintf (buf, "var%05X", operand);
|
||||
v.name = buf;
|
||||
v.label = operand;
|
||||
v.size = size;
|
||||
v.type = TypeContainer::defaultTypeForSize(size);
|
||||
if (duFlag == eDuVal::USE) /* must already have init value */
|
||||
*pre = h; /* Pre modulo hash value */
|
||||
return h % tableSize; /* Post modulo hash value */
|
||||
}
|
||||
|
||||
/* Hash the symOff and symProc fields */
|
||||
/* Note: for the time being, there no use is made of the symProc field */
|
||||
word
|
||||
valHash(dword symOff, PPROC symProc, word *pre)
|
||||
{
|
||||
word h = 0;
|
||||
|
||||
h = (word)(symOff ^ (symOff >> 8));
|
||||
|
||||
*pre = h; /* Pre modulo hash value */
|
||||
return h % tableSize; /* Post modulo hash value */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo)
|
||||
{
|
||||
word h, pre, j;
|
||||
|
||||
if ((numEntry / 9 * 10) >= tableSize)
|
||||
{
|
||||
v.duVal.use =1; // USEVAL;
|
||||
v.duVal.val =1;
|
||||
/* Table is full. Expand it */
|
||||
expandSym();
|
||||
}
|
||||
|
||||
/* Enter it into the value hashed table first */
|
||||
h = valHash(symOff, symProc, &pre); /* Ideal spot for this entry */
|
||||
if (valTab[h].symProc == 0) /* Collision? */
|
||||
{
|
||||
/* No. Just insert here */
|
||||
valTab[h].pSymName= symName; /* Symbol name ptr */
|
||||
valTab[h].symOff = symOff; /* Offset of the symbol */
|
||||
valTab[h].symProc = symProc; /* Symbol's proc num */
|
||||
valTab[h].preHash = pre; /* Pre modulo hash value */
|
||||
valTab[h].postHash= h; /* Post modulo hash value */
|
||||
valTab[h].nextOvf = NIL; /* No overflow */
|
||||
valTab[h].prevOvf = NIL; /* No back link */
|
||||
}
|
||||
else
|
||||
{
|
||||
v.duVal.setFlags(duFlag);
|
||||
/* Linear probing, for now */
|
||||
j = (h+1) % tableSize;
|
||||
while (j != h)
|
||||
{
|
||||
if (valTab[j].symProc == 0)
|
||||
{
|
||||
/* Insert here */
|
||||
valTab[j].pSymName= symName; /* Symbol name ptr */
|
||||
valTab[j].symOff = symOff; /* Offset of the symbol */
|
||||
valTab[j].symProc = symProc; /* Symbol's proc num */
|
||||
valTab[j].preHash = pre; /* Pre modulo hash value */
|
||||
valTab[j].postHash= h; /* Post modulo hash value */
|
||||
/* Insert after the primary entry in the table */
|
||||
valTab[j].nextOvf = valTab[h].nextOvf;
|
||||
valTab[h].nextOvf = j;
|
||||
valTab[j].prevOvf = h; /* The backlink */
|
||||
break;
|
||||
}
|
||||
push_back(v);
|
||||
inserted_new=true;
|
||||
return (&back());
|
||||
else
|
||||
{
|
||||
/* Probe further */
|
||||
j = (j+1) % tableSize;
|
||||
}
|
||||
}
|
||||
if (j == h)
|
||||
{
|
||||
printf("enterSym: val table overflow!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now enter into the symbol hashed table as well, if reqd */
|
||||
if (!bSymToo) return;
|
||||
h = symHash(symName, &pre); /* Ideal spot for this entry */
|
||||
if (symTab[h].pSymName == 0) /* Collision? */
|
||||
{
|
||||
/* No. Just insert here */
|
||||
symTab[h].pSymName= symName; /* Symbol name ptr */
|
||||
symTab[h].symOff = symOff; /* Offset of the symbol */
|
||||
symTab[h].symProc = symProc; /* Symbol's proc num */
|
||||
symTab[h].preHash = pre; /* Pre modulo hash value */
|
||||
symTab[h].postHash= h; /* Post modulo hash value */
|
||||
symTab[h].nextOvf = NIL; /* No overflow */
|
||||
symTab[h].prevOvf = NIL; /* No back link */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Linear probing, for now */
|
||||
j = (h+1) % tableSize;
|
||||
while (j != h)
|
||||
{
|
||||
if (symTab[j].pSymName == 0)
|
||||
{
|
||||
/* Insert here */
|
||||
symTab[j].pSymName= symName; /* Symbol name ptr */
|
||||
symTab[j].symOff = symOff; /* Offset of the symbol */
|
||||
symTab[j].symProc = symProc; /* Symbol's proc num */
|
||||
symTab[j].preHash = pre; /* Pre modulo hash value */
|
||||
symTab[j].postHash= h; /* Post modulo hash value */
|
||||
/* Insert after the primary entry in the table */
|
||||
symTab[j].nextOvf = symTab[h].nextOvf;
|
||||
symTab[h].nextOvf = j;
|
||||
symTab[j].prevOvf = h; /* The backlink */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Probe further */
|
||||
j = (j+1) % tableSize;
|
||||
}
|
||||
}
|
||||
if (j == h)
|
||||
{
|
||||
printf("enterSym: sym table overflow!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//template<> class SymbolTableCommon<SYM>;
|
||||
//template<> class SymbolTableCommon<STKSYM>;
|
||||
|
||||
boolT
|
||||
findSym(char *symName, word *pIndex)
|
||||
{
|
||||
word h, j, pre;
|
||||
|
||||
h = symHash(symName, &pre);
|
||||
j = h;
|
||||
do
|
||||
{
|
||||
if (symTab[j].pSymName == 0)
|
||||
{
|
||||
return FALSE; /* No entry at all */
|
||||
}
|
||||
if (strcmp(symName, symTab[j].pSymName) == 0)
|
||||
{
|
||||
*pIndex = j;
|
||||
return TRUE; /* Symbol found */
|
||||
}
|
||||
j = symTab[j].nextOvf; /* Follow the chain */
|
||||
}
|
||||
while (j != NIL);
|
||||
return FALSE; /* End of chain */
|
||||
}
|
||||
|
||||
/* Find symbol by value */
|
||||
boolT
|
||||
findVal(dword symOff, PPROC symProc, word *pIndex)
|
||||
{
|
||||
word h, j, pre;
|
||||
|
||||
h = valHash(symOff, symProc, &pre);
|
||||
j = h;
|
||||
do
|
||||
{
|
||||
if (valTab[j].symProc == 0)
|
||||
{
|
||||
return FALSE; /* No entry at all */
|
||||
}
|
||||
if ((valTab[j].symOff == symOff)
|
||||
/*&& (valTab[j].symProc == symProc)*/)
|
||||
{
|
||||
*pIndex = j;
|
||||
return TRUE; /* Symbol found */
|
||||
}
|
||||
j = valTab[j].nextOvf; /* Follow the chain */
|
||||
}
|
||||
while (j != NIL);
|
||||
return FALSE; /* End of chain */
|
||||
}
|
||||
|
||||
word
|
||||
findBlankSym(char *symName)
|
||||
{
|
||||
word h, j, pre;
|
||||
|
||||
h = symHash(symName, &pre);
|
||||
j = h;
|
||||
do
|
||||
{
|
||||
if (symTab[j].pSymName == 0)
|
||||
{
|
||||
return j; /* Empty entry. Terminate probing */
|
||||
}
|
||||
j = (++j) % tableSize; /* Linear probing */
|
||||
}
|
||||
while (j != h);
|
||||
printf("Could not find blank entry in table! Num entries is %ld of %ld\n",
|
||||
(long)numEntry, (long)tableSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Using the symbolic name, read the value */
|
||||
boolT
|
||||
readSym(char *symName, dword *pSymOff, PPROC *pSymProc)
|
||||
{
|
||||
word i;
|
||||
|
||||
if (!findSym(symName, &i))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*pSymOff = symTab[i].symOff;
|
||||
*pSymProc= symTab[i].symProc;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Using the value, read the symbolic name */
|
||||
boolT
|
||||
readVal(char *symName, dword symOff, PPROC symProc)
|
||||
{
|
||||
word i;
|
||||
|
||||
if (!findVal(symOff, symProc, &i))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
strcpy(symName, valTab[i].pSymName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* A doubly linked list of entries belonging to the same hash bucket is
|
||||
maintained, to prevent the need for many entries to be moved when deleting
|
||||
an entry. It is implemented with indexes, and is not an open hashing system.
|
||||
Symbols are deleted from both hash tables.
|
||||
*/
|
||||
|
||||
/* Known limitation: strings are never deleted from the string table */
|
||||
|
||||
void
|
||||
deleteSym(char *symName)
|
||||
{
|
||||
word i, j, back;
|
||||
dword symOff;
|
||||
PPROC symProc;
|
||||
|
||||
/* Delete from symbol hashed table first */
|
||||
if (!findSym(symName, &i))
|
||||
{
|
||||
printf("Could not delete non existant symbol name %s\n", symName);
|
||||
exit(1);
|
||||
}
|
||||
symOff = symTab[i].symOff; /* Remember these for valTab */
|
||||
symProc= symTab[i].symProc;
|
||||
j = symTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
symTab[symTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current name */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = symTab[j].prevOvf;
|
||||
memcpy(&symTab[i], &symTab[j], sizeof(SYMTABLE));
|
||||
symTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
symTab[j].pSymName = 0; /* Rub out the name */
|
||||
|
||||
|
||||
/* Delete from value hashed table */
|
||||
if (!findVal(symOff, symProc, &i))
|
||||
{
|
||||
printf("Could not delete non existant symbol off %04X proc %d\n",
|
||||
symOff, symProc);
|
||||
exit(1);
|
||||
}
|
||||
j = valTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
valTab[valTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current entry */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = valTab[j].prevOvf;
|
||||
memcpy(&valTab[i], &valTab[j], sizeof(SYMTABLE));
|
||||
valTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
valTab[j].symProc = 0; /* Rub out the entry */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
deleteVal(dword symOff, PPROC symProc, boolT bSymToo)
|
||||
{
|
||||
word i, j, back;
|
||||
char *symName;
|
||||
|
||||
/* Delete from value hashed table */
|
||||
if (!findVal(symOff, symProc, &i))
|
||||
{
|
||||
printf("Could not delete non existant symbol off %04X proc %p\n",
|
||||
symOff, symProc);
|
||||
exit(1);
|
||||
}
|
||||
symName = symTab[i].pSymName; /* Remember this for symTab */
|
||||
j = valTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
valTab[valTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current entry */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = valTab[j].prevOvf;
|
||||
memcpy(&valTab[i], &valTab[j], sizeof(SYMTABLE));
|
||||
valTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
valTab[j].symProc = 0; /* Rub out the entry */
|
||||
|
||||
/* If requested, delete from symbol hashed table now */
|
||||
if (!bSymToo) return;
|
||||
if (!findSym(symName, &i))
|
||||
{
|
||||
printf("Could not delete non existant symbol name %s\n", symName);
|
||||
exit(1);
|
||||
}
|
||||
j = symTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
symTab[symTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current name */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = symTab[j].prevOvf;
|
||||
memcpy(&symTab[i], &symTab[j], sizeof(SYMTABLE));
|
||||
symTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
symTab[j].pSymName = 0; /* Rub out the name */
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
expandSym(void)
|
||||
{
|
||||
word i, j, n, newPost;
|
||||
|
||||
printf("\nResizing table...\r");
|
||||
/* We double the table size each time, so on average only half of the
|
||||
entries move to the new half. This works because we are effectively
|
||||
shifting the "binary point" of the hash value to the left each time,
|
||||
thereby leaving the number unchanged or adding an MSBit of 1. */
|
||||
tableSize <<= 2;
|
||||
symTab = (SYMTABLE*)reallocVar(symTab, tableSize * sizeof(SYMTABLE));
|
||||
memset (&symTab[tableSize/2], 0, (tableSize/2) * sizeof(SYMTABLE));
|
||||
|
||||
/* Now we have to move some of the entries to take advantage of the extra
|
||||
space */
|
||||
|
||||
for (i=0; i < numEntry; i++)
|
||||
{
|
||||
newPost = symTab[i].preHash % tableSize;
|
||||
if (newPost != symTab[i].postHash)
|
||||
{
|
||||
/* This entry is now in the wrong place. Copy it to the new position,
|
||||
then delete it. */
|
||||
j = findBlankSym(symTab[i].pSymName);
|
||||
memcpy(&symTab[j], &symTab[i], sizeof(SYMTABLE));
|
||||
/* Correct the post hash value */
|
||||
symTab[j].postHash = newPost;
|
||||
|
||||
/* Now adjust links */
|
||||
n = symTab[j].prevOvf;
|
||||
if (n != NIL)
|
||||
{
|
||||
symTab[n].nextOvf = j;
|
||||
}
|
||||
|
||||
n = symTab[j].nextOvf;
|
||||
if (n != NIL)
|
||||
{
|
||||
symTab[n].prevOvf = j;
|
||||
}
|
||||
|
||||
/* Mark old position as deleted */
|
||||
symTab[i].pSymName = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function adds to the string table. At this stage, strings are not
|
||||
deleted */
|
||||
char *
|
||||
addStrTbl(char *pStr)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((strTabNext + strlen(pStr) + 1) >= STRTABSIZE)
|
||||
{
|
||||
/* We can't realloc the old string table pointer, since that will
|
||||
potentially move the string table, and pointers will be invalid.
|
||||
So we realloc this one to its present usage (hopefully it won't
|
||||
move), and allocate a new one */
|
||||
if (reallocVar((void *)pStrTab, strTabNext) != pStrTab)
|
||||
{
|
||||
printf("Damn it! String table moved on shrinking!\n");
|
||||
exit(1);
|
||||
}
|
||||
pStrTab = (char *)allocMem(STRTABSIZE);
|
||||
strTabNext = 0;
|
||||
}
|
||||
p = strcpy(&pStrTab[strTabNext], pStr);
|
||||
strTabNext += strlen(pStr) +1;
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
#include "dcc.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(CowriteTest, HandlesZeroInput) {
|
||||
EXPECT_EQ(1, 1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// The following line must be executed to initialize Google Mock
|
||||
// (and Google Test) before running the tests.
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
194
src/udm.cpp
194
src/udm.cpp
@ -4,104 +4,154 @@
|
||||
* that just plays with abstract cfg's and intervals and such like.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include "project.h"
|
||||
|
||||
extern Project g_proj;
|
||||
static void displayCFG(Function * pProc);
|
||||
static void displayDfs(BB * pBB);
|
||||
#include "dcc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static void displayCFG(PPROC pProc);
|
||||
static void displayDfs(PBB pBB);
|
||||
|
||||
/****************************************************************************
|
||||
* udm
|
||||
****************************************************************************/
|
||||
void Function::buildCFG(Disassembler &ds)
|
||||
{
|
||||
if(flg & PROC_ISLIB)
|
||||
return; // Ignore library functions
|
||||
createCFG();
|
||||
if (option.VeryVerbose)
|
||||
displayCFG();
|
||||
|
||||
compressCFG(); // Remove redundancies and add in-edge information
|
||||
|
||||
if (option.asm2)
|
||||
{
|
||||
ds.disassem(this); // Print 2nd pass assembler listing
|
||||
}
|
||||
|
||||
/* Idiom analysis and propagation of long type */
|
||||
lowLevelAnalysis();
|
||||
|
||||
/* Generate HIGH_LEVEL icodes whenever possible */
|
||||
highLevelGen();
|
||||
}
|
||||
void Function::controlFlowAnalysis()
|
||||
{
|
||||
if (flg & PROC_ISLIB)
|
||||
return; /* Ignore library functions */
|
||||
derSeq *derivedG=0;
|
||||
|
||||
/* Make cfg reducible and build derived sequences */
|
||||
derivedG=checkReducibility();
|
||||
|
||||
if (option.VeryVerbose)
|
||||
derivedG->display();
|
||||
|
||||
/* Structure the graph */
|
||||
structure(derivedG);
|
||||
|
||||
/* Check for compound conditions */
|
||||
compoundCond ();
|
||||
|
||||
if (option.verbose)
|
||||
{
|
||||
printf("\nDepth first traversal - Proc %s\n", name.c_str());
|
||||
m_cfg.front()->displayDfs();
|
||||
}
|
||||
|
||||
/* Free storage occupied by this procedure */
|
||||
freeDerivedSeq(*derivedG);
|
||||
|
||||
}
|
||||
void udm(void)
|
||||
{
|
||||
{ PPROC pProc;
|
||||
derSeq *derivedG;
|
||||
|
||||
/* Build the control flow graph, find idioms, and convert low-level
|
||||
* icodes to high-level ones */
|
||||
Disassembler ds(2);
|
||||
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
|
||||
for (pProc = pLastProc; pProc; pProc = pProc->prev)
|
||||
{
|
||||
iter->buildCFG(ds);
|
||||
}
|
||||
|
||||
if (pProc->flg & PROC_ISLIB)
|
||||
continue; /* Ignore library functions */
|
||||
|
||||
/* Create the basic control flow graph */
|
||||
pProc->cfg = createCFG(pProc);
|
||||
if (option.VeryVerbose)
|
||||
displayCFG(pProc);
|
||||
|
||||
/* Remove redundancies and add in-edge information */
|
||||
compressCFG(pProc);
|
||||
|
||||
/* Print 2nd pass assembler listing */
|
||||
if (option.asm2)
|
||||
disassem(2, pProc);
|
||||
|
||||
/* Idiom analysis and propagation of long type */
|
||||
lowLevelAnalysis (pProc);
|
||||
|
||||
/* Generate HIGH_LEVEL icodes whenever possible */
|
||||
highLevelGen (pProc);
|
||||
}
|
||||
|
||||
/* Data flow analysis - eliminate condition codes, extraneous registers
|
||||
* and intermediate instructions. Find expressions by forward
|
||||
* substitution algorithm */
|
||||
std::bitset<32> live_regs;
|
||||
g_proj.pProcList.front().dataFlow (live_regs);
|
||||
dataFlow (pProcList, 0);
|
||||
|
||||
/* Control flow analysis - structuring algorithm */
|
||||
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
|
||||
for (pProc = pLastProc; pProc; pProc = pProc->prev)
|
||||
{
|
||||
iter->controlFlowAnalysis();
|
||||
|
||||
if (pProc->flg & PROC_ISLIB)
|
||||
continue; /* Ignore library functions */
|
||||
|
||||
/* Make cfg reducible and build derived sequences */
|
||||
checkReducibility(pProc, &derivedG);
|
||||
|
||||
if (option.VeryVerbose)
|
||||
displayDerivedSeq(derivedG);
|
||||
|
||||
/* Structure the graph */
|
||||
structure(pProc, derivedG);
|
||||
|
||||
/* Check for compound conditions */
|
||||
compoundCond (pProc);
|
||||
|
||||
if (option.verbose) {
|
||||
printf("\nDepth first traversal - Proc %s\n", pProc->name);
|
||||
displayDfs(pProc->cfg);
|
||||
}
|
||||
|
||||
/* Free storage occupied by this procedure */
|
||||
freeDerivedSeq(derivedG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *nodeType[] = {"branch", "if", "case", "fall", "return", "call",
|
||||
"loop", "repeat", "interval", "cycleHead",
|
||||
"caseHead", "terminate",
|
||||
"nowhere" };
|
||||
|
||||
static char *loopType[] = {"noLoop", "while", "repeat", "loop", "for"};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* displayCFG - Displays the Basic Block list
|
||||
***************************************************************************/
|
||||
void Function::displayCFG()
|
||||
static void displayCFG(PPROC pProc)
|
||||
{
|
||||
printf("\nBasic Block List - Proc %s", name.c_str());
|
||||
for (BB *pBB : m_cfg)
|
||||
{
|
||||
pBB->display();
|
||||
Int i;
|
||||
PBB pBB;
|
||||
|
||||
printf("\nBasic Block List - Proc %s", pProc->name);
|
||||
|
||||
for (pBB = pProc->cfg; pBB; pBB = pBB->next) {
|
||||
printf("\nnode type = %s, ", nodeType[pBB->nodeType]);
|
||||
printf("start = %ld, length = %ld, #out edges = %ld\n",
|
||||
pBB->start, pBB->length, pBB->numOutEdges);
|
||||
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
printf(" outEdge[%2d] = %ld\n",i, pBB->edges[i].BBptr->start);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* displayDfs - Displays the CFG using a depth first traversal
|
||||
****************************************************************************/
|
||||
static void displayDfs(PBB pBB)
|
||||
{
|
||||
Int i;
|
||||
|
||||
if (! pBB)
|
||||
return;
|
||||
pBB->traversed = DFS_DISP;
|
||||
|
||||
printf("node type = %s, ", nodeType[pBB->nodeType]);
|
||||
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
|
||||
pBB->start, pBB->length, pBB->numInEdges, pBB->numOutEdges);
|
||||
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
|
||||
pBB->dfsFirstNum, pBB->dfsLastNum,
|
||||
pBB->immedDom == MAX ? -1 : pBB->immedDom);
|
||||
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
|
||||
loopType[pBB->loopType],
|
||||
pBB->loopHead == MAX ? -1 : pBB->loopHead,
|
||||
pBB->latchNode == MAX ? -1 : pBB->latchNode,
|
||||
pBB->loopFollow == MAX ? -1 : pBB->loopFollow);
|
||||
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
|
||||
pBB->ifFollow == MAX ? -1 : pBB->ifFollow,
|
||||
pBB->caseHead == MAX ? -1 : pBB->caseHead,
|
||||
pBB->caseTail == MAX ? -1 : pBB->caseTail);
|
||||
|
||||
if (pBB->nodeType == INTERVAL_NODE)
|
||||
printf("corresponding interval = %ld\n", pBB->correspInt->numInt);
|
||||
else for (i = 0; i < pBB->numInEdges; i++)
|
||||
printf (" inEdge[%ld] = %ld\n", i, pBB->inEdges[i]->start);
|
||||
|
||||
/* Display out edges information */
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
if (pBB->nodeType == INTERVAL_NODE)
|
||||
printf(" outEdge[%ld] = %ld\n", i,
|
||||
pBB->edges[i].BBptr->correspInt->numInt);
|
||||
else
|
||||
printf(" outEdge[%ld] = %ld\n", i, pBB->edges[i].BBptr->start);
|
||||
printf("----\n");
|
||||
|
||||
/* Recursive call on successors of current node */
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
if (pBB->edges[i].BBptr->traversed != DFS_DISP)
|
||||
displayDfs(pBB->edges[i].BBptr);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user