Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a59d07ef2 |
@ -1,7 +1,7 @@
|
|||||||
PROJECT(dcc_original)
|
PROJECT(dcc_original)
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
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)
|
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)")
|
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||||
@ -14,25 +14,24 @@ ENDIF()
|
|||||||
|
|
||||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
FIND_PACKAGE(LLVM)
|
#FIND_PACKAGE(LLVM)
|
||||||
FIND_PACKAGE(Boost)
|
#FIND_PACKAGE(Boost)
|
||||||
IF(dcc_build_tests)
|
#IF(dcc_build_tests)
|
||||||
FIND_PACKAGE(GMock)
|
# FIND_PACKAGE(GMock)
|
||||||
ENDIF()
|
#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(
|
INCLUDE_DIRECTORIES(
|
||||||
3rd_party/libdisasm
|
# 3rd_party/libdisasm
|
||||||
include
|
include
|
||||||
include/idioms
|
# include/idioms
|
||||||
${Boost_INCLUDE_DIRS}
|
# ${Boost_INCLUDE_DIRS}
|
||||||
${LLVM_INCLUDE_DIRS}
|
# ${LLVM_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(dcc_SOURCES
|
set(dcc_SOURCES
|
||||||
src/dcc.cpp
|
|
||||||
src/ast.cpp
|
src/ast.cpp
|
||||||
src/backend.cpp
|
src/backend.cpp
|
||||||
src/bundle.cpp
|
src/bundle.cpp
|
||||||
@ -40,75 +39,47 @@ set(dcc_SOURCES
|
|||||||
src/comwrite.cpp
|
src/comwrite.cpp
|
||||||
src/control.cpp
|
src/control.cpp
|
||||||
src/dataflow.cpp
|
src/dataflow.cpp
|
||||||
|
src/dcc.cpp
|
||||||
src/disassem.cpp
|
src/disassem.cpp
|
||||||
src/error.cpp
|
src/error.cpp
|
||||||
src/fixwild.cpp
|
src/fixwild.cpp
|
||||||
src/frontend.cpp
|
src/frontend.cpp
|
||||||
src/graph.cpp
|
src/graph.cpp
|
||||||
src/hlicode.cpp
|
src/hlicode.cpp
|
||||||
src/machine_x86.cpp
|
|
||||||
src/icode.cpp
|
src/icode.cpp
|
||||||
src/idioms.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/locident.cpp
|
||||||
src/parser.cpp
|
src/parser.cpp
|
||||||
src/perfhlib.cpp
|
src/perfhlib.cpp
|
||||||
src/procs.cpp
|
src/procs.cpp
|
||||||
src/project.cpp
|
|
||||||
src/Procedure.cpp
|
|
||||||
src/proplong.cpp
|
src/proplong.cpp
|
||||||
src/reducible.cpp
|
src/reducible.cpp
|
||||||
src/scanner.cpp
|
src/scanner.cpp
|
||||||
src/symtab.cpp
|
src/symtab.cpp
|
||||||
src/udm.cpp
|
src/udm.cpp
|
||||||
src/BasicBlock.cpp
|
|
||||||
)
|
)
|
||||||
set(dcc_HEADERS
|
set(dcc_HEADERS
|
||||||
include/ast.h
|
include/ast.h
|
||||||
include/bundle.h
|
include/bundle.h
|
||||||
include/BinaryImage.h
|
|
||||||
include/dcc.h
|
include/dcc.h
|
||||||
include/disassem.h
|
include/disassem.h
|
||||||
include/dosdcc.h
|
include/dosdcc.h
|
||||||
include/error.h
|
include/error.h
|
||||||
include/graph.h
|
include/graph.h
|
||||||
include/hlicode.h
|
include/hlicode.h
|
||||||
include/machine_x86.h
|
|
||||||
include/icode.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/locident.h
|
||||||
include/perfhlib.h
|
include/perfhlib.h
|
||||||
include/project.h
|
|
||||||
include/scanner.h
|
include/scanner.h
|
||||||
include/state.h
|
include/state.h
|
||||||
include/symtab.h
|
include/symtab.h
|
||||||
include/types.h
|
include/types.h
|
||||||
include/Procedure.h
|
|
||||||
include/StackFrame.h
|
|
||||||
include/BasicBlock.h
|
|
||||||
)
|
)
|
||||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
||||||
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
||||||
|
|
||||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||||
TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
|
#TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
|
||||||
if(dcc_build_tests)
|
#if(dcc_build_tests)
|
||||||
ADD_SUBDIRECTORY(src)
|
#ADD_SUBDIRECTORY(src)
|
||||||
endif()
|
#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);
|
|
||||||
};
|
|
||||||
272
include/ast.h
272
include/ast.h
@ -4,12 +4,9 @@
|
|||||||
* Date: September 1993
|
* Date: September 1993
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
*/
|
*/
|
||||||
#pragma once
|
|
||||||
#include <cstring>
|
#define operandSize 20
|
||||||
#include <list>
|
|
||||||
#include "Enums.h"
|
|
||||||
#include <boost/range.hpp>
|
|
||||||
static const int operandSize=20;
|
|
||||||
/* The following definitions and types define the Conditional Expression
|
/* The following definitions and types define the Conditional Expression
|
||||||
* attributed syntax tree, as defined by the following EBNF:
|
* attributed syntax tree, as defined by the following EBNF:
|
||||||
CondExp ::= CondTerm AND CondTerm | CondTerm
|
CondExp ::= CondTerm AND CondTerm | CondTerm
|
||||||
@ -18,160 +15,123 @@ static const int operandSize=20;
|
|||||||
Identifier ::= globalVar | register | localVar | parameter | constant
|
Identifier ::= globalVar | register | localVar | parameter | constant
|
||||||
op ::= <= | < | = | != | > | >=
|
op ::= <= | < | = | != | > | >=
|
||||||
*/
|
*/
|
||||||
/* High-level BOOLEAN conditions for iJB..iJNS icodes */
|
|
||||||
static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
|
||||||
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
|
||||||
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
|
||||||
|
|
||||||
struct Function;
|
/* Conditional Expression enumeration nodes and operators */
|
||||||
struct STKFRAME;
|
typedef enum {
|
||||||
struct LOCAL_ID;
|
BOOLEAN_OP, /* condOps */
|
||||||
struct ICODE;
|
NEGATION, /* not (2's complement) */
|
||||||
struct LLInst;
|
ADDRESSOF, /* addressOf (&) */
|
||||||
struct ID;
|
DEREFERENCE, /* contents of (*) */
|
||||||
typedef std::list<ICODE>::iterator iICODE;
|
IDENTIFIER, /* {register | local | param | constant | global} */
|
||||||
typedef boost::iterator_range<iICODE> rICODE;
|
/* The following are only available to C programs */
|
||||||
#include "IdentType.h"
|
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 condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
||||||
|
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
||||||
|
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
||||||
|
|
||||||
|
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 */
|
/* Expression data type */
|
||||||
struct COND_EXPR
|
typedef struct _condExpr {
|
||||||
{
|
condNodeType type; /* Conditional Expression Node Type */
|
||||||
protected:
|
|
||||||
struct /* for BOOLEAN_OP */
|
|
||||||
{
|
|
||||||
condOp op;
|
|
||||||
COND_EXPR *lhs;
|
|
||||||
COND_EXPR *rhs;
|
|
||||||
} boolExpr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
condNodeType m_type; /* Conditional Expression Node Type */
|
|
||||||
union _exprNode { /* Different cond expr nodes */
|
union _exprNode { /* Different cond expr nodes */
|
||||||
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
struct { /* for BOOLEAN_OP */
|
||||||
IDENTTYPE ident; /* for IDENTIFIER */
|
condOp op;
|
||||||
} expr;
|
struct _condExpr *lhs;
|
||||||
COND_EXPR *lhs()
|
struct _condExpr *rhs;
|
||||||
{
|
} boolExpr;
|
||||||
assert(m_type==BOOLEAN_OP);
|
struct _condExpr *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||||
return boolExpr.lhs;
|
IDENTTYPE ident; /* for IDENTIFIER */
|
||||||
}
|
} expr;
|
||||||
const COND_EXPR *lhs() const
|
} COND_EXPR;
|
||||||
{
|
|
||||||
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));
|
|
||||||
|
|
||||||
}
|
/* Sequence of conditional expression data type */
|
||||||
virtual ~COND_EXPR() {}
|
/*** NOTE: not used at present ****/
|
||||||
public:
|
typedef struct _condExpSeq {
|
||||||
virtual COND_EXPR *inverse() const; // return new COND_EXPR that is invarse of this
|
COND_EXPR *expr;
|
||||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
struct _condExpSeq *next;
|
||||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
} SEQ_COND_EXPR;
|
||||||
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);
|
|
||||||
|
|
||||||
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).
|
* Purpose: Module to handle the bundle type (array of pointers to strings).
|
||||||
* (C) Cristina Cifuentes
|
* (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
|
#include <stdio.h>
|
||||||
{
|
|
||||||
public:
|
typedef struct {
|
||||||
void appendCode(const char *format, ...);
|
Int numLines; /* Number of lines in the table */
|
||||||
void appendCode(const std::string &s);
|
Int allocLines; /* Number of lines allocated in the table */
|
||||||
void appendDecl(const char *format, ...);
|
char **str; /* Table of strings */
|
||||||
void appendDecl(const std::string &);
|
} strTable;
|
||||||
void init()
|
|
||||||
{
|
|
||||||
decl.clear();
|
typedef struct {
|
||||||
code.clear();
|
|
||||||
}
|
|
||||||
strTable decl; /* Declarations */
|
strTable decl; /* Declarations */
|
||||||
strTable code; /* C code */
|
strTable code; /* C code */
|
||||||
int current_indent;
|
} bundle;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define lineSize 360 /* 3 lines in the mean time */
|
#define lineSize 360 /* 3 lines in the mean time */
|
||||||
|
|
||||||
//void newBundle (bundle *procCode);
|
void newBundle (bundle *procCode);
|
||||||
void writeBundle (std::ostream &ios, 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);
|
void freeBundle (bundle *procCode);
|
||||||
|
|
||||||
|
|||||||
361
include/dcc.h
361
include/dcc.h
@ -2,15 +2,8 @@
|
|||||||
* dcc project general header
|
* dcc project general header
|
||||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
* (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 "types.h"
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "icode.h"
|
#include "icode.h"
|
||||||
@ -18,31 +11,134 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "bundle.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 */
|
/* CALL GRAPH NODE */
|
||||||
struct CALL_GRAPH
|
typedef struct _callGraph {
|
||||||
{
|
PPROC proc; /* Pointer to procedure in pProcList */
|
||||||
ilFunction proc; /* Pointer to procedure in pProcList */
|
Int numOutEdges; /* # of out edges (ie. # procs invoked) */
|
||||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
Int numAlloc; /* # of out edges allocated */
|
||||||
public:
|
struct _callGraph **outEdges; /* array of out edges */
|
||||||
void write();
|
} CALL_GRAPH;
|
||||||
CALL_GRAPH() : outEdges(0)
|
typedef CALL_GRAPH *PCALL_GRAPH;
|
||||||
{
|
#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||||
}
|
|
||||||
public:
|
extern PPROC pProcList; /* Pointer to the head of the procedure list */
|
||||||
void writeNodeCallGraph(int indIdx);
|
extern PPROC pLastProc; /* Pointer to last node of the proc list */
|
||||||
bool insertCallGraph(ilFunction caller, ilFunction callee);
|
extern PCALL_GRAPH callGraph; /* Pointer to the head of the call graph */
|
||||||
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 */
|
|
||||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
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 ****/
|
/**** Global variables ****/
|
||||||
|
|
||||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||||
@ -55,95 +151,174 @@ typedef struct { /* Command line option flags */
|
|||||||
unsigned Map : 1;
|
unsigned Map : 1;
|
||||||
unsigned Stats : 1;
|
unsigned Stats : 1;
|
||||||
unsigned Interact : 1; /* Interactive mode */
|
unsigned Interact : 1; /* Interactive mode */
|
||||||
unsigned Calls : 1; /* Follow register indirect calls */
|
unsigned Calls : 1; /* Follow register indirect calls */
|
||||||
char filename[80]; /* The input filename */
|
char filename[80]; /* The input filename */
|
||||||
} OPTION;
|
} OPTION;
|
||||||
|
|
||||||
extern OPTION option; /* Command line options */
|
extern OPTION option; /* Command line options */
|
||||||
|
extern SYMTAB symtab; /* Global symbol table */
|
||||||
|
|
||||||
#include "BinaryImage.h"
|
typedef struct { /* Loaded program image parameters */
|
||||||
extern std::bitset<32> duReg[30]; /* def/use bits for registers */
|
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 PROG prog; /* Loaded program image parameters */
|
||||||
extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */
|
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 */
|
/* 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 */
|
/* Memory map states */
|
||||||
enum eAreaType
|
#define BM_UNKNOWN 0 /* Unscanned memory */
|
||||||
{
|
#define BM_DATA 1 /* Data */
|
||||||
BM_UNKNOWN = 0, /* Unscanned memory */
|
#define BM_CODE 2 /* Code */
|
||||||
BM_DATA = 1, /* Data */
|
#define BM_IMPURE 3 /* Used as Data and Code*/
|
||||||
BM_CODE = 2, /* Code */
|
|
||||||
BM_IMPURE = 3 /* Used as Data and Code*/
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Intermediate instructions statistics */
|
/* Intermediate instructions statistics */
|
||||||
struct STATS
|
typedef struct {
|
||||||
{
|
Int numBBbef; /* number of basic blocks initially */
|
||||||
int numBBbef; /* number of basic blocks initially */
|
Int numBBaft; /* number of basic blocks at the end */
|
||||||
int numBBaft; /* number of basic blocks at the end */
|
Int nOrder; /* n-th order */
|
||||||
int nOrder; /* n-th order */
|
Int numLLIcode; /* number of low-level Icode instructions */
|
||||||
int numLLIcode; /* number of low-level Icode instructions */
|
Int numHLIcode; /* number of high-level Icode instructions */
|
||||||
int numHLIcode; /* number of high-level Icode instructions */
|
Int totalLL; /* total number of low-level Icode insts */
|
||||||
int totalLL; /* total number of low-level Icode insts */
|
Int totalHL; /* total number of high-level Icod insts */
|
||||||
int totalHL; /* total number of high-level Icod insts */
|
} STATS;
|
||||||
};
|
|
||||||
|
|
||||||
extern STATS stats; /* Icode statistics */
|
extern STATS stats; /* Icode statistics */
|
||||||
|
|
||||||
|
|
||||||
/**** Global function prototypes ****/
|
/**** 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 udm(void); /* udm.c */
|
||||||
void freeCFG(BB * cfg); /* graph.c */
|
PBB createCFG(PPROC pProc); /* graph.c */
|
||||||
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
|
void compressCFG(PPROC pProc); /* graph.c */
|
||||||
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
|
void freeCFG(PBB cfg); /* graph.c */
|
||||||
char *cChar(uint8_t c); /* backend.c */
|
PBB newBB(PBB, Int, Int, byte, Int, PPROC); /* graph.c */
|
||||||
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
|
void BackEnd(char *filename, PCALL_GRAPH); /* backend.c */
|
||||||
void parse (CALL_GRAPH * *); /* parser.c */
|
char *cChar(byte c); /* backend.c */
|
||||||
|
Int scan(dword ip, PICODE p); /* scanner.c */
|
||||||
int strSize (uint8_t *, char); /* parser.c */
|
void parse (PCALL_GRAPH *); /* parser.c */
|
||||||
//void disassem(int pass, Function * pProc); /* disassem.c */
|
boolT labelSrch(PICODE pIc, Int n, dword tg, Int *pIdx); /* parser.c */
|
||||||
void interactDis(Function * initProc, int initIC); /* disassem.c */
|
void setState(PSTATE state, word reg, int16 value); /* parser.c */
|
||||||
bool JmpInst(llIcode opcode); /* idioms.c */
|
Int strSize (byte *, char); /* parser.c */
|
||||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.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 SetupLibCheck(void); /* chklib.c */
|
||||||
void CleanupLibCheck(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 */
|
/* Exported functions from procs.c */
|
||||||
boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction);
|
boolT insertCallGraph (PCALL_GRAPH, PPROC, PPROC);
|
||||||
void adjustActArgType (COND_EXPR *, hlType, Function *);
|
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 */
|
/* Exported functions from ast.c */
|
||||||
std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, int *);
|
COND_EXPR *boolCondExp (COND_EXPR *lhs, COND_EXPR *rhs, condOp op);
|
||||||
int hlTypeSize (const COND_EXPR *, Function *);
|
COND_EXPR *unaryCondExp (condNodeType, COND_EXPR *exp);
|
||||||
//hlType expType (const COND_EXPR *, Function *);
|
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 */
|
/* Exported functions from hlicode.c */
|
||||||
std::string writeCall (Function *, STKFRAME &, Function *, int *);
|
void newAsgnHlIcode (PICODE, COND_EXPR *, COND_EXPR *);
|
||||||
char *writeJcond (const HLTYPE &, Function *, int *);
|
void newCallHlIcode (PICODE);
|
||||||
char *writeJcondInv (HLTYPE, Function *, int *);
|
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 */
|
||||||
|
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 *);
|
||||||
|
|
||||||
|
|
||||||
/* 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 *);
|
|
||||||
|
|
||||||
|
|
||||||
extern const char *indentStr(int level);
|
|
||||||
|
|||||||
@ -2,32 +2,7 @@
|
|||||||
* dcc project disassembler header
|
* dcc project disassembler header
|
||||||
* (C) Mike van Emmerik
|
* (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) */
|
/* Definitions for extended keys (first key is zero) */
|
||||||
|
|
||||||
#define EXT 0x100 /* "Extended" flag */
|
#define EXT 0x100 /* "Extended" flag */
|
||||||
@ -44,10 +19,10 @@ public:
|
|||||||
#ifdef _CONSOLE
|
#ifdef _CONSOLE
|
||||||
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
|
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
|
||||||
#define KEY_LEFT 0x4B
|
#define KEY_LEFT 0x4B
|
||||||
#define KEY_UP 0x48
|
#define KEY_UP 0x48
|
||||||
#define KEY_RIGHT 0x4D
|
#define KEY_RIGHT 0x4D
|
||||||
#define KEY_NPAGE 0x51
|
#define KEY_NPAGE 0x51
|
||||||
#define KEY_PPAGE 0x49
|
#define KEY_PPAGE 0x49
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __UNIX__
|
#ifdef __UNIX__
|
||||||
|
|||||||
@ -5,34 +5,34 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
/* Type definitions for intel 80x86 architecture */
|
/* Type definitions for intel 80x86 architecture */
|
||||||
typedef unsigned int uint16_t; /* 16 bits */
|
typedef unsigned int Word; /* 16 bits */
|
||||||
typedef unsigned char uint8_t; /* 8 bits */
|
typedef unsigned char Byte; /* 8 bits */
|
||||||
typedef union {
|
typedef union {
|
||||||
unsigned long dW;
|
unsigned long dW;
|
||||||
uint16_t wL, wH; /* 2 words */
|
Word wL, wH; /* 2 words */
|
||||||
} Dword; /* 32 bits */
|
} 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 {
|
typedef struct {
|
||||||
/* low uint8_t */
|
/* low byte */
|
||||||
uint16_t lowBitWord : 1;
|
Word lowBitWord : 1;
|
||||||
uint16_t filler1 : 6;
|
Word filler1 : 6;
|
||||||
uint16_t highBitByte : 1;
|
Word highBitByte : 1;
|
||||||
/* high uint8_t */
|
/* high byte */
|
||||||
uint16_t lowBitByte : 1;
|
Word lowBitByte : 1;
|
||||||
uint16_t filler2 : 6;
|
Word filler2 : 6;
|
||||||
uint16_t highBitWord : 1;
|
Word highBitWord : 1;
|
||||||
} wordBits;
|
} 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 lowBit(a) ((wordBits)(a).lowBitWord)
|
||||||
#define highBitByte(a) ((wordBits)(a).highBitByte)
|
#define highBitByte(a) ((wordBits)(a).highBitByte)
|
||||||
#define lowBitByte(a) ((wordBits)(a).lowBitByte)
|
#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).highBitWord):\
|
||||||
((wordBits)(a).highBitByte))
|
((wordBits)(a).highBitByte))
|
||||||
|
|
||||||
/* uint16_t register variables */
|
/* Word register variables */
|
||||||
#define ax regs.x.ax
|
#define ax regs.x.ax
|
||||||
#define bx regs.x.bx
|
#define bx regs.x.bx
|
||||||
#define cx regs.x.cx
|
#define cx regs.x.cx
|
||||||
@ -52,7 +52,7 @@ typedef struct {
|
|||||||
#define carry regs.x.cflags
|
#define carry regs.x.cflags
|
||||||
#define overF regs.x.flags /***** check *****/
|
#define overF regs.x.flags /***** check *****/
|
||||||
|
|
||||||
/* uint8_t register variables */
|
/* Byte register variables */
|
||||||
#define ah regs.h.ah
|
#define ah regs.h.ah
|
||||||
#define al regs.h.al
|
#define al regs.h.al
|
||||||
#define bh regs.h.bh
|
#define bh regs.h.bh
|
||||||
@ -64,8 +64,8 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
/* High and low words of a Dword */
|
/* High and low words of a Dword */
|
||||||
#define highWord(w) (*((uint16_t*)&(w) + 1))
|
#define highWord(w) (*((Word*)&(w) + 1))
|
||||||
#define lowWord(w) ((uint16_t)(w))
|
#define lowWord(w) ((Word)(w))
|
||||||
|
|
||||||
#define MAXByte 0xFF
|
#define MAXByte 0xFF
|
||||||
#define MAXWord 0xFFFF
|
#define MAXWord 0xFFFF
|
||||||
@ -74,4 +74,7 @@ typedef struct {
|
|||||||
#define MAXSignWord 0x7FFF
|
#define MAXSignWord 0x7FFF
|
||||||
#define MINSignWord 0x8001
|
#define MINSignWord 0x8001
|
||||||
|
|
||||||
|
/* Booleans */
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
|||||||
@ -2,35 +2,32 @@
|
|||||||
* Error codes
|
* Error codes
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* These definitions refer to errorMessage in error.c */
|
/* 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,
|
#define USAGE 0
|
||||||
INVALID_SYNTHETIC_BB,
|
#define INVALID_ARG 1
|
||||||
INVALID_INT_BB,
|
#define INVALID_OPCODE 2
|
||||||
IP_OUT_OF_RANGE,
|
#define INVALID_386OP 3
|
||||||
DEF_NOT_FOUND,
|
#define FUNNY_SEGOVR 4
|
||||||
JX_NOT_DEF,
|
#define FUNNY_REP 5
|
||||||
NOT_DEF_USE,
|
#define CANNOT_OPEN 6
|
||||||
REPEAT_FAIL,
|
#define CANNOT_READ 7
|
||||||
WHILE_FAIL
|
#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 fatalError(Int errId, ...);
|
||||||
void reportError(eErrorId errId, ...);
|
void reportError(Int errId, ...);
|
||||||
|
|
||||||
|
|||||||
173
include/graph.h
173
include/graph.h
@ -2,49 +2,37 @@
|
|||||||
* CFG, BB and interval related definitions
|
* CFG, BB and interval related definitions
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
struct Function;
|
|
||||||
/* Types of basic block nodes */
|
/* Types of basic block nodes */
|
||||||
/* Real basic blocks: type defined according to their out-edges */
|
/* Real basic blocks: type defined according to their out-edges */
|
||||||
enum eBBKind
|
#define ONE_BRANCH 0 /* unconditional branch */
|
||||||
{
|
#define TWO_BRANCH 1 /* conditional branch */
|
||||||
ONE_BRANCH = 0, /* unconditional branch */
|
#define MULTI_BRANCH 2 /* case branch */
|
||||||
TWO_BRANCH = 1, /* conditional branch */
|
#define FALL_NODE 3 /* fall through */
|
||||||
MULTI_BRANCH=2, /* case branch */
|
#define RETURN_NODE 4 /* procedure/program return */
|
||||||
FALL_NODE=3, /* fall through */
|
#define CALL_NODE 5 /* procedure call */
|
||||||
RETURN_NODE=4, /* procedure/program return */
|
#define LOOP_NODE 6 /* loop instruction */
|
||||||
CALL_NODE=5, /* procedure call */
|
#define REP_NODE 7 /* repeat instruction */
|
||||||
LOOP_NODE=6, /* loop instruction */
|
#define INTERVAL_NODE 8 /* contains interval list */
|
||||||
REP_NODE=7, /* repeat instruction */
|
|
||||||
INTERVAL_NODE=8, /* contains interval list */
|
|
||||||
|
|
||||||
TERMINATE_NODE=11, /* Exit to DOS */
|
#define TERMINATE_NODE 11 /* Exit to DOS */
|
||||||
NOWHERE_NODE=12 /* No outedges going anywhere */
|
#define NOWHERE_NODE 12 /* No outedges going anywhere */
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Depth-first traversal constants */
|
/* Depth-first traversal constants */
|
||||||
enum eDFS
|
#define DFS_DISP 1 /* Display graph pass */
|
||||||
{
|
#define DFS_MERGE 2 /* Merge nodes pass */
|
||||||
DFS_NONE,
|
#define DFS_NUM 3 /* DFS numbering pass */
|
||||||
DFS_DISP=1, /* Display graph pass */
|
#define DFS_CASE 4 /* Case pass */
|
||||||
DFS_MERGE=2, /* Merge nodes pass */
|
#define DFS_ALPHA 5 /* Alpha code generation*/
|
||||||
DFS_NUM=3, /* DFS numbering pass */
|
#define DFS_JMP 9 /* rmJMP pass - must be largest flag */
|
||||||
DFS_CASE=4, /* Case pass */
|
|
||||||
DFS_ALPHA=5, /* Alpha code generation*/
|
|
||||||
DFS_JMP=9 /* rmJMP pass - must be largest flag */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Control flow analysis constants */
|
/* Control flow analysis constants */
|
||||||
enum eNodeHeaderType
|
#define NO_TYPE 0 /* node is not a loop header*/
|
||||||
{
|
#define WHILE_TYPE 1 /* node is a while header */
|
||||||
NO_TYPE=0, /* node is not a loop header*/
|
#define REPEAT_TYPE 2 /* node is a repeat header */
|
||||||
WHILE_TYPE=1, /* node is a while header */
|
#define ENDLESS_TYPE 3 /* endless loop header */
|
||||||
REPEAT_TYPE=2, /* node is a repeat header */
|
|
||||||
ENDLESS_TYPE=3 /* endless loop header */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Uninitialized values for certain fields */
|
/* Uninitialized values for certain fields */
|
||||||
#define NO_NODE MAX /* node has no associated node */
|
#define NO_NODE MAX /* node has no associated node */
|
||||||
@ -55,47 +43,90 @@ enum eNodeHeaderType
|
|||||||
#define ELSE 1 /* else edge */
|
#define ELSE 1 /* else edge */
|
||||||
|
|
||||||
/* Basic Block (BB) flags */
|
/* Basic Block (BB) flags */
|
||||||
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
||||||
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
|
#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 */
|
dword ip; /* Out edge icode address */
|
||||||
uint8_t numOutEdges; /* Number of out edges */
|
struct _BB *BBptr; /* Out edge pointer to next BB */
|
||||||
queue nodes; /* Nodes of the interval*/
|
interval *intPtr; /* Out edge ptr to next interval*/
|
||||||
queue::iterator currNode; /* Current node */
|
} TYPEADR_TYPE;
|
||||||
interval *next; /* Next interval */
|
|
||||||
BB *firstOfInt();
|
/* Basic block (BB) node definition */
|
||||||
interval()
|
typedef struct _BB {
|
||||||
{
|
byte nodeType; /* Type of node */
|
||||||
numInt=numOutEdges=0;
|
Int traversed; /* Boolean: traversed yet? */
|
||||||
currNode=nodes.end();
|
Int start; /* First instruction offset */
|
||||||
next=0;
|
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 */
|
/* Derived Sequence structure */
|
||||||
struct derSeq_Entry
|
typedef struct _derivedNode {
|
||||||
{
|
BB *Gi; /* Graph pointer */
|
||||||
BB * Gi; /* Graph pointer */
|
interval *Ii; /* Interval list of Gi */
|
||||||
interval * Ii; /* Interval list of Gi */
|
struct _derivedNode *next; /* Next derived graph */
|
||||||
derSeq_Entry() : Gi(0),Ii(0)
|
} derSeq;
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
~derSeq_Entry();
|
|
||||||
public:
|
|
||||||
void findIntervals(Function *c);
|
|
||||||
};
|
|
||||||
class derSeq : public std::list<derSeq_Entry>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void display();
|
|
||||||
};
|
|
||||||
void freeDerivedSeq(derSeq &derivedG); /* reducible.c */
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* File: hlIcode.h
|
* File: hlIcode.h
|
||||||
* Purpose: module definitions for high-level icodes
|
* Purpose: module definitions for high-level icodes
|
||||||
* Date: September 1993
|
* Date: September 1993
|
||||||
@ -6,8 +6,16 @@
|
|||||||
|
|
||||||
|
|
||||||
/* High level icodes opcodes - def in file icode.h */
|
/* 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 */
|
hlIcode opcode; /* hlIcode opcode */
|
||||||
union { /* different operands */
|
union { /* different operands */
|
||||||
struct {
|
struct {
|
||||||
@ -17,4 +25,12 @@ struct HLICODE
|
|||||||
COND_EXPR *exp; /* for HLI_JCOND, INC, DEC */
|
COND_EXPR *exp; /* for HLI_JCOND, INC, DEC */
|
||||||
} oper; /* operand */
|
} oper; /* operand */
|
||||||
boolT valid; /* has a valid hlIcode */
|
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;
|
||||||
|
|
||||||
|
|||||||
808
include/icode.h
808
include/icode.h
@ -2,489 +2,367 @@
|
|||||||
* I-code related definitions
|
* I-code related definitions
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
/* LOW_LEVEL icode flags */
|
||||||
#include <list>
|
#define B 0x000001 /* Byte operands (value implicitly used) */
|
||||||
#include <bitset>
|
#define I 0x000002 /* Immed. source */
|
||||||
#include <llvm/ADT/ilist.h>
|
#define NOT_HLL 0x000004 /* Not HLL inst. */
|
||||||
#include <llvm/ADT/ilist_node.h>
|
#define FLOAT_OP 0x000008 /* ESC or WAIT */
|
||||||
#include <llvm/CodeGen/MachineInstr.h>
|
|
||||||
#include <llvm/MC/MCInst.h>
|
#define SEG_IMMED 0x000010 /* Number is relocated segment value */
|
||||||
#include <llvm/MC/MCAsmInfo.h>
|
#define IMPURE 0x000020 /* Instruction modifies code */
|
||||||
#include <llvm/Value.h>
|
#define WORD_OFF 0x000040 /* Inst has word offset ie.could be address */
|
||||||
#include <llvm/Instruction.h>
|
#define TERMINATES 0x000080 /* Instruction terminates program */
|
||||||
#include <boost/range.hpp>
|
|
||||||
#include "libdis.h"
|
#define CASE 0x000100 /* Label as case part of switch */
|
||||||
#include "Enums.h"
|
#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
|
#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;
|
/* LOW_LEVEL icode opcodes */
|
||||||
struct Function;
|
typedef enum {
|
||||||
struct STKFRAME;
|
iCBW, /* 0 */
|
||||||
struct CIcodeRec;
|
iAAA,
|
||||||
struct ICODE;
|
iAAD,
|
||||||
struct bundle;
|
iAAM,
|
||||||
typedef std::list<ICODE>::iterator iICODE;
|
iAAS,
|
||||||
typedef std::list<ICODE>::reverse_iterator riICODE;
|
iADC,
|
||||||
typedef boost::iterator_range<iICODE> rCODE;
|
iADD,
|
||||||
extern std::bitset<32> duReg[30];
|
iAND,
|
||||||
/* uint8_t and uint16_t registers */
|
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 */
|
/* Def/use of flags - low 4 bits represent flags */
|
||||||
struct DU
|
typedef struct {
|
||||||
{
|
byte d;
|
||||||
uint8_t d;
|
byte u;
|
||||||
uint8_t 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) */
|
/* 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);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CallType : public HlTypeSupport
|
|
||||||
{
|
|
||||||
//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 */
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HLTYPE
|
|
||||||
{
|
|
||||||
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 */
|
/* LOW_LEVEL icode operand record */
|
||||||
struct LLOperand
|
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;
|
||||||
|
|
||||||
|
/* 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
|
||||||
{
|
{
|
||||||
llvm::MCOperand llvm_op;
|
hlIcode opcode; /* hlIcode opcode */
|
||||||
eReg seg; /* CS, DS, ES, SS */
|
union { /* different operands */
|
||||||
eReg segOver; /* CS, DS, ES, SS if segment override */
|
struct { /* for HLI_ASSIGN */
|
||||||
int16_t segValue; /* Value of segment seg during analysis */
|
COND_EXPR *lhs;
|
||||||
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
|
COND_EXPR *rhs;
|
||||||
int16_t off; /* memory address offset */
|
} asgn;
|
||||||
uint32_t opz; /* idx of immed src op */
|
COND_EXPR *exp; /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
|
||||||
//union {/* Source operand if (flg & I) */
|
struct { /* for HLI_CALL */
|
||||||
struct { /* Call & # actual arg bytes */
|
struct _proc *proc;
|
||||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
struct _STKFRAME *args; /* actual arguments */
|
||||||
int cb; /* # actual arg bytes */
|
} call;
|
||||||
} proc;
|
} oper; /* operand */
|
||||||
LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0)
|
} HLTYPE;
|
||||||
{
|
|
||||||
proc.proc=0;
|
typedef struct
|
||||||
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:
|
llIcode opcode; /* llIcode instruction */
|
||||||
uint32_t flg; /* icode flags */
|
byte numBytes; /* Number of bytes this instr */
|
||||||
LLOperand m_src; /* source operand */
|
flags32 flg; /* icode flags */
|
||||||
public:
|
dword label; /* offset in image (20-bit adr) */
|
||||||
int codeIdx; /* Index into cCode.code */
|
ICODEMEM dst; /* destination operand */
|
||||||
uint8_t numBytes; /* Number of bytes this instr */
|
ICODEMEM src; /* source operand */
|
||||||
uint32_t label; /* offset in image (20-bit adr) */
|
union { /* Source operand if (flg & I) */
|
||||||
LLOperand dst; /* destination operand */
|
dword op; /* idx of immed src op */
|
||||||
DU flagDU; /* def/use of flags */
|
struct { /* Call & # actual arg bytes */
|
||||||
int caseEntry;
|
struct _proc *proc; /* ^ target proc (for CALL(F))*/
|
||||||
std::vector<uint32_t> caseTbl2;
|
Int cb; /* # actual arg bytes */
|
||||||
int hllLabNum; /* label # for hll codegen */
|
} proc;
|
||||||
bool conditionalJump()
|
} immed;
|
||||||
{
|
DU flagDU; /* def/use of flags */
|
||||||
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ);
|
struct { /* Case table if op==JMP && !I */
|
||||||
}
|
Int numEntries; /* # entries in case table */
|
||||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
dword *entries; /* array of offsets */
|
||||||
void setFlags(uint32_t flag) {flg |= flag;}
|
} caseTbl;
|
||||||
void clrFlags(uint32_t flag)
|
Int hllLabNum; /* label # for hll codegen */
|
||||||
{
|
} LLTYPE;
|
||||||
if(getOpcode()==iMOD)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
flg &= ~flag;
|
|
||||||
}
|
|
||||||
uint32_t getFlag() const {return flg;}
|
|
||||||
//llIcode getOpcode() const { return opcode; }
|
|
||||||
|
|
||||||
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 */
|
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
||||||
struct ICODE
|
typedef struct {
|
||||||
{
|
icodeType type; /* Icode type */
|
||||||
// use llvm names at least
|
boolT invalid; /* Has no HIGH_LEVEL equivalent */
|
||||||
typedef BB MachineBasicBlock;
|
struct _BB *inBB; /* BB to which this icode belongs */
|
||||||
protected:
|
DU_ICODE du; /* Def/use regs/vars */
|
||||||
LLInst m_ll;
|
DU1 du1; /* du chain 1 */
|
||||||
HLTYPE m_hl;
|
Int codeIdx; /* Index into cCode.code */
|
||||||
MachineBasicBlock * Parent; /* BB to which this icode belongs */
|
struct { /* Different types of icodes */
|
||||||
bool invalid; /* Has no HIGH_LEVEL equivalent */
|
LLTYPE ll;
|
||||||
public:
|
HLTYPE hl; /* For HIGH_LEVEL icodes */
|
||||||
x86_insn_t insn;
|
} ic; /* intermediate code */
|
||||||
template<int FLAG>
|
} ICODE;
|
||||||
struct FlagFilter
|
typedef ICODE* PICODE;
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
icodeType type; /* Icode type */
|
|
||||||
DU_ICODE du; /* Def/use regs/vars */
|
|
||||||
DU1 du1; /* du chain 1 */
|
|
||||||
int loc_ip; // used by CICodeRec to number ICODEs
|
|
||||||
|
|
||||||
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.
|
// 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:
|
public:
|
||||||
CIcodeRec(); // Constructor
|
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
|
* (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 */
|
/* Type definition */
|
||||||
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
|
typedef struct {
|
||||||
// TODO: why ?
|
Int csym; /* # symbols used */
|
||||||
struct COND_EXPR;
|
Int alloc; /* # symbols allocated */
|
||||||
struct ICODE;
|
Int *idx; /* Array of integer indexes */
|
||||||
struct LLInst;
|
} IDX_ARRAY;
|
||||||
typedef std::list<ICODE>::iterator iICODE;
|
|
||||||
struct IDX_ARRAY : public std::vector<iICODE>
|
/* Type definitions used in the decompiled program */
|
||||||
{
|
typedef enum {
|
||||||
bool inList(iICODE idx)
|
TYPE_UNKNOWN = 0, /* unknown so far */
|
||||||
{
|
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
|
||||||
return std::find(begin(),end(),idx)!=end();
|
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
|
typedef enum
|
||||||
{
|
{
|
||||||
STK_FRAME, /* For stack vars */
|
STK_FRAME, /* For stack vars */
|
||||||
REG_FRAME, /* For register variables */
|
REG_FRAME, /* For register variables */
|
||||||
GLB_FRAME /* For globals */
|
GLB_FRAME, /* For globals */
|
||||||
} frameType;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
int16_t seg; /* segment value */
|
int16 seg; /* segment value */
|
||||||
int16_t off; /* offset */
|
int16 off; /* offset */
|
||||||
eReg regi; /* optional indexed register */
|
byte regi; /* optional indexed register */
|
||||||
} BWGLB_TYPE;
|
} BWGLB_TYPE;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{ /* For TYPE_LONG_(UN)SIGN on the stack */
|
{ /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||||
int offH; /* high offset from BP */
|
Int offH; /* high offset from BP */
|
||||||
int offL; /* low offset from BP */
|
Int offL; /* low offset from BP */
|
||||||
} LONG_STKID_TYPE;
|
} LONG_STKID_TYPE;
|
||||||
struct LONGID_TYPE
|
typedef struct
|
||||||
{ /* For TYPE_LONG_(UN)SIGN registers */
|
{ /* For TYPE_LONG_(UN)SIGN registers */
|
||||||
eReg h; /* high register */
|
byte h; /* high register */
|
||||||
eReg l; /* low register */
|
byte l; /* low register */
|
||||||
bool srcDstRegMatch(iICODE a,iICODE b) const;
|
} LONGID_TYPE;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* ID, LOCAL_ID */
|
/* ID, LOCAL_ID */
|
||||||
struct ID
|
typedef struct {
|
||||||
{
|
hlType type; /* Probable type */
|
||||||
hlType type; /* Probable type */
|
boolT illegal;/* Boolean: not a valid field any more */
|
||||||
bool illegal; /* Boolean: not a valid field any more */
|
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
|
||||||
//std::vector<iICODE> idx;
|
frameType loc; /* Frame location */
|
||||||
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
|
boolT hasMacro;/* Identifier requires a macro */
|
||||||
frameType loc; /* Frame location */
|
char macro[10];/* Macro for this identifier */
|
||||||
bool hasMacro; /* Identifier requires a macro */
|
char name[20];/* Identifier's name */
|
||||||
char macro[10]; /* Macro for this identifier */
|
union { /* Different types of identifiers */
|
||||||
std::string name; /* Identifier's name */
|
byte regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
|
||||||
union { /* Different types of identifiers */
|
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
|
||||||
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
|
byte regOff; /* register offset (if any) */
|
||||||
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
|
Int off; /* offset from BP */
|
||||||
uint8_t regOff; /* register offset (if any) */
|
} bwId;
|
||||||
int off; /* offset from BP */
|
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(WORD)_(UN)SIGN globals */
|
||||||
} bwId;
|
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
|
LONG_STKID_TYPE longStkId;/* For TYPE_LONG_(UN)SIGN on the stack */
|
||||||
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
|
struct { /* For TYPE_LONG_(UN)SIGN globals */
|
||||||
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
|
int16 seg; /* segment value */
|
||||||
struct { /* For TYPE_LONG_(UN)SIGN globals */
|
int16 offH; /* offset high */
|
||||||
int16_t seg; /* segment value */
|
int16 offL; /* offset low */
|
||||||
int16_t offH; /* offset high */
|
byte regi; /* optional indexed register */
|
||||||
int16_t offL; /* offset low */
|
} longGlb;
|
||||||
uint8_t regi; /* optional indexed register */
|
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
||||||
} longGlb;
|
dword h; /* high word */
|
||||||
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
dword l; /* low word */
|
||||||
uint32_t h; /* high uint16_t */
|
} longKte;
|
||||||
uint32_t l; /* low uint16_t */
|
} id;
|
||||||
} longKte;
|
} ID;
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LOCAL_ID
|
typedef struct {
|
||||||
{
|
Int csym; /* No. of symbols in the table */
|
||||||
std::vector<ID> id_arr;
|
Int alloc; /* No. of symbols allocated */
|
||||||
protected:
|
ID *id; /* Identifier */
|
||||||
int newLongIdx(int16_t seg, int16_t offH, int16_t offL, uint8_t regi, hlType t);
|
} LOCAL_ID;
|
||||||
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_);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
/* Perfect hashing function library. Contains functions to generate perfect
|
||||||
hashing functions
|
hashing functions
|
||||||
* (C) Mike van Emmerik
|
* (C) Mike van Emmerik
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define bool unsigned char
|
|
||||||
#define uint8_t unsigned char
|
#define TRUE 1
|
||||||
#define uint16_t unsigned short
|
#define FALSE 0
|
||||||
|
#define bool unsigned char
|
||||||
|
#define byte unsigned char
|
||||||
|
#define word unsigned short
|
||||||
|
|
||||||
/* Prototypes */
|
/* 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 hashCleanup(void); /* Frees memory allocated by hashParams() */
|
||||||
void map(void); /* Part 1 of creating the tables */
|
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: */
|
/* 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 */
|
void dispKey(int i); /* Display the key */
|
||||||
class PatternHasher
|
|
||||||
{
|
|
||||||
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
/* Macro reads a LH word from the image regardless of host convention */
|
||||||
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 */
|
|
||||||
#ifndef LH
|
#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
|
#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
|
/* Scanner functions
|
||||||
* (C) Cristina Cifuentes, Jeff Ledermann
|
* (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
|
* dcc project header
|
||||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include "machine_x86.h"
|
|
||||||
|
|
||||||
/* STATE TABLE */
|
/* STATE TABLE */
|
||||||
struct STATE
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t IP; /* Offset into Image */
|
dword IP; /* Offset into Image */
|
||||||
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
|
int16 r[INDEXBASE]; /* Value of segs and AX */
|
||||||
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
|
byte f[INDEXBASE]; /* True if r[.] has a value */
|
||||||
struct
|
struct
|
||||||
{ /* For case stmt indexed reg */
|
{ /* For case stmt indexed reg */
|
||||||
uint8_t regi; /* Last conditional jump */
|
byte regi; /* Last conditional jump */
|
||||||
int16_t immed; /* Contents of the previous register */
|
int16 immed; /* Contents of the previous register */
|
||||||
} JCond;
|
} JCond;
|
||||||
void setState(uint16_t reg, int16_t value);
|
} STATE;
|
||||||
void checkStartup();
|
typedef STATE *PSTATE;
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
118
include/symtab.h
118
include/symtab.h
@ -2,112 +2,42 @@
|
|||||||
* Symbol table prototypes
|
* Symbol table prototypes
|
||||||
* (C) Mike van Emmerik
|
* (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 */
|
/* 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)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
typedef struct
|
||||||
int32_t label; /* physical address (20 bit) */
|
|
||||||
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
|
||||||
};
|
|
||||||
/* STACK FRAME */
|
|
||||||
struct STKSYM : public SymbolCommon
|
|
||||||
{
|
{
|
||||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
char *pSymName; /* Ptr to symbolic name or comment */
|
||||||
COND_EXPR *regs; /* For register arguments only */
|
dword symOff; /* Symbol image offset */
|
||||||
int16_t label; /* Immediate off from BP (+:args, -:params) */
|
PPROC symProc; /* Procedure pointer */
|
||||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
word preHash; /* Hash value before the modulo */
|
||||||
bool hasMacro; /* This type needs a macro */
|
word postHash; /* Hash value after the modulo */
|
||||||
std::string macro; /* Macro name */
|
word nextOvf; /* Next entry this hash bucket, or -1 */
|
||||||
bool invalid; /* Boolean: invalid entry in formal arg list*/
|
word prevOvf; /* Back link in Ovf chain */
|
||||||
STKSYM()
|
} SYMTABLE;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
enum _tableType /* The table types */
|
||||||
/* 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 */
|
|
||||||
{
|
{
|
||||||
Label=0, /* The label table */
|
Label=0, /* The label table */
|
||||||
Comment, /* The comment table */
|
Comment, /* The comment table */
|
||||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum _tableType tableType; /* For convenience */
|
||||||
|
|
||||||
void createSymTables(void);
|
void createSymTables(void);
|
||||||
void destroySymTables(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 */
|
void selectTable(tableType); /* Select a particular table */
|
||||||
|
|
||||||
|
char *addStrTbl(char *pStr); /* Add string to string table */
|
||||||
|
|
||||||
|
|||||||
@ -2,19 +2,34 @@
|
|||||||
* dcc project general header
|
* dcc project general header
|
||||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
|
||||||
#include <cassert>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "Enums.h"
|
|
||||||
/**** Common definitions and macros ****/
|
/**** 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
|
#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 */
|
/* Type definitions used in the program */
|
||||||
typedef unsigned char byte; /* 8 bits */
|
typedef unsigned char byte; /* 8 bits */
|
||||||
typedef unsigned short word;/* 16 bits */
|
typedef unsigned short word;/* 16 bits */
|
||||||
typedef short int16; /* 16 bits */
|
typedef short int16; /* 16 bits */
|
||||||
typedef unsigned char boolT; /* 8 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 */
|
#define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */
|
||||||
|
|
||||||
/* These are for C library signature detection */
|
/* These are for C library signature detection */
|
||||||
@ -24,15 +39,17 @@ typedef unsigned char boolT; /* 8 bits */
|
|||||||
|
|
||||||
/****** MACROS *******/
|
/****** 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 */
|
/* 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 */
|
/* 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) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
|
||||||
#define LH(p) ((word)((byte *)(p))[0] + ((word)((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 */
|
/* 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 */
|
/* 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 */
|
/* Macro tests bit b for type t in prog.map */
|
||||||
#define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1)))
|
#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 */
|
/* Macro to convert a segment, offset definition into a 20 bit address */
|
||||||
#define opAdr(seg,off) ((seg << 4) + off)
|
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
1476
src/ast.cpp
1476
src/ast.cpp
File diff suppressed because it is too large
Load Diff
829
src/backend.cpp
829
src/backend.cpp
@ -4,40 +4,47 @@
|
|||||||
* Purpose: Back-end module. Generates C code for each procedure.
|
* Purpose: Back-end module. Generates C code for each procedure.
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <cassert>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include "disassem.h"
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "project.h"
|
|
||||||
bundle cCode; /* Procedure declaration and code */
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/* Returns a unique index to the next label */
|
bundle cCode; /* Procedure declaration and code */
|
||||||
int getNextLabel()
|
|
||||||
{
|
/* Indentation buffer */
|
||||||
static int labelIdx = 1; /* index of the next label */
|
#define indSize 81 /* size of the indentation buffer. Each indentation
|
||||||
return (labelIdx++);
|
* 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 */
|
||||||
|
{
|
||||||
|
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 */
|
/* 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 ("Number of Icode instructions:\n");
|
||||||
printf (" Low-level : %4d\n", stats.numLLIcode);
|
printf (" Low-level : %4d\n", stats.numLLIcode);
|
||||||
if (! (flg & PROC_ASM))
|
if (! (pProc->flg & PROC_ASM))
|
||||||
{
|
{
|
||||||
printf (" High-level: %4d\n", stats.numHLIcode);
|
printf (" High-level: %4d\n", stats.numHLIcode);
|
||||||
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
|
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
|
||||||
100.0) / stats.numLLIcode);
|
100.0) / stats.numLLIcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -48,315 +55,619 @@ static void fixupLabels (PPROC pProc)
|
|||||||
* a unique label number for it. This label is placed in the associated
|
* 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
|
* icode for the node (pProc->Icode). The procedure is done in sequential
|
||||||
* order of dsfLast numbering. */
|
* 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 */
|
PBB *dfsLast; /* pointer to the dfsLast array */
|
||||||
|
|
||||||
dfsLast = pProc->dfsLast;
|
dfsLast = pProc->dfsLast;
|
||||||
for (i = 0; i < pProc->numBBs; i++)
|
for (i = 0; i < pProc->numBBs; i++)
|
||||||
if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) {
|
if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) {
|
||||||
pProc->Icode.icode[dfsLast[i]->start].ll()->flg |= HLL_LABEL;
|
pProc->Icode.icode[dfsLast[i]->start].ic.ll.flg |= HLL_LABEL;
|
||||||
pProc->Icode.icode[dfsLast[i]->start].ll()->hllLabNum = getNextLabel();
|
pProc->Icode.icode[dfsLast[i]->start].ic.ll.hllLabNum = getNextLabel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
char *cChar (byte c)
|
||||||
/* Returns the corresponding C string for the given character c. Character
|
/* Returns the corresponding C string for the given character c. Character
|
||||||
* constants such as carriage return and line feed, require 2 C characters. */
|
* 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) {
|
switch (c) {
|
||||||
case 0x8: /* backspace */
|
case 0x8: /* backspace */
|
||||||
sprintf (res, "\\b");
|
sprintf (res, "\\b");
|
||||||
break;
|
break;
|
||||||
case 0x9: /* horizontal tab */
|
case 0x9: /* horizontal tab */
|
||||||
sprintf (res, "\\t");
|
sprintf (res, "\\t");
|
||||||
break;
|
break;
|
||||||
case 0x0A: /* new line */
|
case 0x0A: /* new line */
|
||||||
sprintf (res, "\\n");
|
sprintf (res, "\\n");
|
||||||
break;
|
break;
|
||||||
case 0x0C: /* form feed */
|
case 0x0C: /* form feed */
|
||||||
sprintf (res, "\\f");
|
sprintf (res, "\\f");
|
||||||
break;
|
break;
|
||||||
case 0x0D: /* carriage return */
|
case 0x0D: /* carriage return */
|
||||||
sprintf (res, "\\r");
|
sprintf (res, "\\r");
|
||||||
break;
|
break;
|
||||||
default: /* any other character*/
|
default: /* any other character*/
|
||||||
sprintf (res, "%c", c);
|
sprintf (res, "%c", c);
|
||||||
}
|
}
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Prints the variable's name and initial contents on the file.
|
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:
|
* Note: to get to the value of the variable:
|
||||||
* com file: prog.Image[operand]
|
* com file: prog.Image[operand]
|
||||||
* exe file: prog.Image[operand+0x100] */
|
* exe file: prog.Image[operand+0x100] */
|
||||||
static void printGlobVar (std::ostream &ostr,SYM * psym)
|
{ Int j;
|
||||||
{
|
dword relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
|
||||||
int j;
|
char *strContents; /* initial contents of variable */
|
||||||
PROG &prog(Project::get()->prog);
|
|
||||||
uint32_t relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
|
|
||||||
|
|
||||||
switch (psym->size)
|
switch (psym->size) {
|
||||||
{
|
case 1: appendStrTab (&cCode.decl, "byte\t%s = %ld;\n",
|
||||||
case 1:
|
psym->name, prog.Image[relocOp]);
|
||||||
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.Image[relocOp]<<";\n";
|
break;
|
||||||
break;
|
case 2: appendStrTab (&cCode.decl, "word\t%s = %ld;\n",
|
||||||
case 2:
|
psym->name, LH(prog.Image+relocOp));
|
||||||
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
|
break;
|
||||||
break;
|
case 4: if (psym->type == TYPE_PTR) /* pointer */
|
||||||
case 4: if (psym->type == TYPE_PTR) /* pointer */
|
appendStrTab (&cCode.decl, "word\t*%s = %ld;\n",
|
||||||
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
|
psym->name, LH(prog.Image+relocOp));
|
||||||
else /* char */
|
else /* char */
|
||||||
ostr << "char\t"<<psym->name<<"[4] = \""<<
|
appendStrTab (&cCode.decl,
|
||||||
prog.Image[relocOp]<<prog.Image[relocOp+1]<<
|
"char\t%s[4] = \"%c%c%c%c\";\n",
|
||||||
prog.Image[relocOp+2]<<prog.Image[relocOp+3]<<";\n";
|
psym->name, prog.Image[relocOp],
|
||||||
break;
|
prog.Image[relocOp+1], prog.Image[relocOp+2],
|
||||||
default:
|
prog.Image[relocOp+3]);
|
||||||
{
|
break;
|
||||||
ostringstream strContents;
|
default:strContents = (char *)allocMem((psym->size*2+1) *sizeof(char));
|
||||||
for (j=0; j < psym->size; j++)
|
strContents[0] = '\0';
|
||||||
strContents << cChar(prog.Image[relocOp + j]);
|
for (j=0; j < psym->size; 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.
|
// Note: Not called at present.
|
||||||
|
static void writeGlobSymTable()
|
||||||
/* Writes the contents of the symbol table, along with any variable
|
/* Writes the contents of the symbol table, along with any variable
|
||||||
* initialization. */
|
* initialization. */
|
||||||
void Project::writeGlobSymTable()
|
{ Int idx;
|
||||||
{
|
char type[10];
|
||||||
std::ostringstream ostr;
|
PSYM pSym;
|
||||||
|
|
||||||
if (symtab.empty())
|
if (symtab.csym)
|
||||||
return;
|
{
|
||||||
ostr<<"/* Global variables */\n";
|
appendStrTab (&cCode.decl, "/* Global variables */\n");
|
||||||
for (SYM &sym : symtab)
|
for (idx = 0; idx < symtab.csym; idx++)
|
||||||
{
|
{
|
||||||
if (sym.duVal.isUSE_VAL()) /* first used */
|
pSym = &symtab.sym[idx];
|
||||||
printGlobVar (ostr,&sym);
|
if (symtab.sym[idx].duVal & USEVAL) /* first used */
|
||||||
else { /* first defined */
|
printGlobVar (&(symtab.sym[idx]));
|
||||||
switch (sym.size) {
|
else { /* first defined */
|
||||||
case 1: ostr<<"uint8_t\t"; break;
|
switch (pSym->size) {
|
||||||
case 2: ostr<<"int\t"; break;
|
case 1: strcpy (type, "byte\t"); break;
|
||||||
case 4: if (sym.type == TYPE_PTR)
|
case 2: strcpy (type, "int\t"); break;
|
||||||
ostr<<"int\t*";
|
case 4: if (pSym->type == TYPE_PTR)
|
||||||
else
|
strcpy (type, "int\t*");
|
||||||
ostr<<"char\t*";
|
else
|
||||||
break;
|
strcpy (type, "char\t*");
|
||||||
default: ostr<<"char\t*";
|
break;
|
||||||
}
|
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
|
/* Writes the header information and global variables to the output C file
|
||||||
* fp. */
|
* fp. */
|
||||||
static void writeHeader (std::ostream &_ios, char *fileName)
|
{
|
||||||
{
|
/* Write header information */
|
||||||
PROG &prog(Project::get()->prog);
|
newBundle (&cCode);
|
||||||
/* Write header information */
|
appendStrTab (&cCode.decl, "/*\n");
|
||||||
cCode.init();
|
appendStrTab (&cCode.decl, " * Input file\t: %s\n", fileName);
|
||||||
cCode.appendDecl( "/*\n");
|
appendStrTab (&cCode.decl, " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
||||||
cCode.appendDecl( " * Input file\t: %s\n", fileName);
|
appendStrTab (&cCode.decl, " */\n\n#include \"dcc.h\"\n\n");
|
||||||
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
|
||||||
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
|
|
||||||
|
|
||||||
/* Write global symbol table */
|
/* Write global symbol table */
|
||||||
/** writeGlobSymTable(); *** need to change them into locident fmt ***/
|
/** writeGlobSymTable(); *** need to change them into locident fmt ***/
|
||||||
writeBundle (_ios, cCode);
|
writeBundle (fp, cCode);
|
||||||
freeBundle (&cCode);
|
freeBundle (&cCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Not currently called!
|
|
||||||
|
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
|
/* 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
|
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||||
* is created and a goto is also emitted.
|
* 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
|
* 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. */
|
* 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 */
|
/* Generate new label */
|
||||||
pt->ll()->hllLabNum = getNextLabel();
|
pt->ic.ll.hllLabNum = getNextLabel();
|
||||||
pt->ll()->setFlags(HLL_LABEL);
|
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,
|
/* Writes the procedure's declaration (including arguments), local variables,
|
||||||
* and invokes the procedure that writes the code of the given record *hli */
|
* and invokes the procedure that writes the code of the given record *hli */
|
||||||
void Function::codeGen (std::ostream &fs)
|
{ Int i, numLoc;
|
||||||
{
|
PSTKFRAME args; /* Procedure arguments */
|
||||||
int numLoc;
|
char buf[200], /* Procedure's definition */
|
||||||
ostringstream ostr;
|
arg[30]; /* One argument */
|
||||||
//STKFRAME * args; /* Procedure arguments */
|
ID *locid; /* Pointer to one local identifier */
|
||||||
//char buf[200], /* Procedure's definition */
|
BB *pBB; /* Pointer to basic block */
|
||||||
// arg[30]; /* One argument */
|
|
||||||
BB *pBB; /* Pointer to basic block */
|
|
||||||
|
|
||||||
/* Write procedure/function header */
|
/* Write procedure/function header */
|
||||||
cCode.init();
|
newBundle (&cCode);
|
||||||
if (flg & PROC_IS_FUNC) /* Function */
|
if (pProc->flg & PROC_IS_FUNC) /* Function */
|
||||||
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" (";
|
appendStrTab (&cCode.decl, "\n%s %s (", hlTypes[pProc->retVal.type],
|
||||||
|
pProc->name);
|
||||||
else /* Procedure */
|
else /* Procedure */
|
||||||
ostr<< "\nvoid "<<name<<" (";
|
appendStrTab (&cCode.decl, "\nvoid %s (", pProc->name);
|
||||||
|
|
||||||
/* Write arguments */
|
/* 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 )
|
if (args->sym[i].invalid == FALSE)
|
||||||
continue;
|
{
|
||||||
ostr<<hlTypes[args[i].type]<<" "<<args[i].name;
|
sprintf (arg,"%s %s",hlTypes[args->sym[i].type], args->sym[i].name);
|
||||||
if (i < (args.size() - 1))
|
strcat (buf, arg);
|
||||||
ostr<<", ";
|
if (i < (args->numArgs - 1))
|
||||||
|
strcat (buf, ", ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ostr<<")\n";
|
strcat (buf, ")\n");
|
||||||
|
appendStrTab (&cCode.decl, "%s", buf);
|
||||||
|
|
||||||
/* Write comments */
|
/* Write comments */
|
||||||
writeProcComments( ostr );
|
writeProcComments (pProc, &cCode.decl);
|
||||||
|
|
||||||
/* Write local variables */
|
/* Write local variables */
|
||||||
if (! (flg & PROC_ASM))
|
if (! (pProc->flg & PROC_ASM))
|
||||||
{
|
{
|
||||||
numLoc = 0;
|
locid = &pProc->localId.id[0];
|
||||||
for (ID &refId : localId )
|
numLoc = 0;
|
||||||
{
|
for (i = 0; i < pProc->localId.csym; i++, locid++)
|
||||||
/* Output only non-invalidated entries */
|
{
|
||||||
if ( refId.illegal )
|
/* Output only non-invalidated entries */
|
||||||
continue;
|
if (locid->illegal == FALSE)
|
||||||
if (refId.loc == REG_FRAME)
|
{
|
||||||
{
|
if (locid->loc == REG_FRAME)
|
||||||
/* Register variables are assigned to a local variable */
|
{
|
||||||
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) ||
|
/* Register variables are assigned to a local variable */
|
||||||
((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. */
|
/* 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)
|
}
|
||||||
{
|
|
||||||
/* Name local variables and output appropriate type */
|
|
||||||
refId.setLocalName(++numLoc);
|
|
||||||
ostr << TypeContainer::typeName(refId.type)<<" "<<refId.name<<";\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fs<<ostr.str();
|
|
||||||
/* Write procedure's code */
|
|
||||||
if (flg & PROC_ASM) /* generate assembler */
|
|
||||||
{
|
|
||||||
Disassembler ds(3);
|
|
||||||
ds.disassem(this);
|
|
||||||
}
|
|
||||||
else /* generate C */
|
|
||||||
{
|
|
||||||
m_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
cCode.appendCode( "}\n\n");
|
else if (locid->loc == STK_FRAME)
|
||||||
writeBundle (fs, cCode);
|
{
|
||||||
freeBundle (&cCode);
|
/* Name local variables and output appropriate type */
|
||||||
|
sprintf (locid->name, "loc%ld", ++numLoc);
|
||||||
|
appendStrTab (&cCode.decl, "%s %s;\n",
|
||||||
|
hlTypes[locid->type], locid->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Write procedure's code */
|
||||||
|
if (pProc->flg & PROC_ASM) /* generate assembler */
|
||||||
|
disassem (3, pProc);
|
||||||
|
else /* generate C */
|
||||||
|
writeCode (pProc->cfg, 1, pProc, &numLoc, MAX, UN_INIT);
|
||||||
|
|
||||||
|
appendStrTab (&cCode.code, "}\n\n");
|
||||||
|
writeBundle (fp, cCode);
|
||||||
|
freeBundle (&cCode);
|
||||||
|
|
||||||
/* Write Live register analysis information */
|
/* Write Live register analysis information */
|
||||||
if (option.verbose)
|
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 */
|
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
|
||||||
cout << "BB "<<i<<"\n";
|
printf ("BB %d\n", i);
|
||||||
cout << " Start = "<<pBB->begin()->loc_ip;
|
printf (" Start = %d, end = %d\n", pBB->start, pBB->start +
|
||||||
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
|
pBB->length - 1);
|
||||||
cout << " LiveUse = ";
|
printf (" LiveUse = ");
|
||||||
Machine_X86::writeRegVector(cout,pBB->liveUse);
|
writeBitVector (pBB->liveUse);
|
||||||
cout << "\n Def = ";
|
printf ("\n Def = ");
|
||||||
Machine_X86::writeRegVector(cout,pBB->def);
|
writeBitVector (pBB->def);
|
||||||
cout << "\n LiveOut = ";
|
printf ("\n LiveOut = ");
|
||||||
Machine_X86::writeRegVector(cout,pBB->liveOut);
|
writeBitVector (pBB->liveOut);
|
||||||
cout << "\n LiveIn = ";
|
printf ("\n LiveIn = ");
|
||||||
Machine_X86::writeRegVector(cout,pBB->liveIn);
|
writeBitVector (pBB->liveIn);
|
||||||
cout <<"\n\n";
|
printf ("\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void backBackEnd (char *filename, PCALL_GRAPH pcallGraph, FILE *fp)
|
||||||
/* Recursive procedure. Displays the procedure's code in depth-first order
|
/* Recursive procedure. Displays the procedure's code in depth-first order
|
||||||
* of the call graph. */
|
* 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 */
|
/* Check if this procedure has been processed already */
|
||||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
|
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
|
||||||
(pcallGraph->proc->flg & PROC_ISLIB))
|
(pcallGraph->proc->flg & PROC_ISLIB))
|
||||||
return;
|
return;
|
||||||
pcallGraph->proc->flg |= PROC_OUTPUT;
|
pcallGraph->proc->flg |= PROC_OUTPUT;
|
||||||
|
|
||||||
/* Dfs if this procedure has any successors */
|
/* 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 */
|
/* Generate code for this procedure */
|
||||||
stats.numLLIcode = pcallGraph->proc->Icode.size();
|
stats.numLLIcode = pcallGraph->proc->Icode.GetNumIcodes();
|
||||||
stats.numHLIcode = 0;
|
stats.numHLIcode = 0;
|
||||||
pcallGraph->proc->codeGen (_ios);
|
codeGen (pcallGraph->proc, fp);
|
||||||
|
|
||||||
/* Generate statistics */
|
/* Generate statistics */
|
||||||
if (option.Stats)
|
if (option.Stats)
|
||||||
pcallGraph->proc->displayStats ();
|
displayStats (pcallGraph->proc);
|
||||||
if (! (pcallGraph->proc->flg & PROC_ASM))
|
if (! (pcallGraph->proc->flg & PROC_ASM))
|
||||||
{
|
{
|
||||||
stats.totalLL += stats.numLLIcode;
|
stats.totalLL += stats.numLLIcode;
|
||||||
stats.totalHL += stats.numHLIcode;
|
stats.totalHL += stats.numHLIcode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackEnd (char *fileName, PCALL_GRAPH pcallGraph)
|
||||||
/* Invokes the necessary routines to produce code one procedure at a time. */
|
/* 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 */
|
/* Get output file name */
|
||||||
std::string outNam(fileName);
|
outName = strcpy ((char*)allocMem(strlen(fileName)+1), fileName);
|
||||||
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
|
if ((ext = strrchr (outName, '.')) != NULL)
|
||||||
|
*ext = '\0';
|
||||||
|
strcat (outName, ".b"); /* b for beta */
|
||||||
|
|
||||||
/* Open output file */
|
/* Open output file */
|
||||||
fs.open(outNam);
|
fp = fopen (outName, "wt");
|
||||||
if(!fs.is_open())
|
if (!fp)
|
||||||
fatalError (CANNOT_OPEN, outNam.c_str());
|
fatalError (CANNOT_OPEN, outName);
|
||||||
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
|
printf ("dcc: Writing C beta file %s\n", outName);
|
||||||
|
|
||||||
/* Header information */
|
/* Header information */
|
||||||
writeHeader (fs, fileName);
|
writeHeader (fp, fileName);
|
||||||
|
|
||||||
/* Initialize total Icode instructions statistics */
|
/* Initialize total Icode instructions statistics */
|
||||||
stats.totalLL = 0;
|
stats.totalLL = 0;
|
||||||
stats.totalHL = 0;
|
stats.totalHL = 0;
|
||||||
|
|
||||||
/* Process each procedure at a time */
|
/* Process each procedure at a time */
|
||||||
backBackEnd (fileName, pcallGraph, fs);
|
backBackEnd (fileName, pcallGraph, fp);
|
||||||
|
|
||||||
/* Close output file */
|
/* Close output file */
|
||||||
fs.close();
|
fclose (fp);
|
||||||
printf ("dcc: Finished writing C beta file\n");
|
printf ("dcc: Finished writing C beta file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
126
src/bundle.cpp
126
src/bundle.cpp
@ -6,89 +6,107 @@
|
|||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <iostream>
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define deltaProcLines 20
|
#define deltaProcLines 20
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
void newBundle (bundle *procCode)
|
||||||
/* Allocates memory for a new bundle and initializes it to zero. */
|
/* 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
|
/* Adds the given label to the start of the line strTab[idx]. The first
|
||||||
* tab is removed and replaced by this label */
|
* tab is removed and replaced by this label */
|
||||||
void strTable::addLabelBundle (int idx, int label)
|
{ char s[lineSize];
|
||||||
{
|
|
||||||
char s[16];
|
sprintf (s, "l%ld: %s", label, &strTab->str[idx][4]);
|
||||||
sprintf (s, "l%d: ", label);
|
strcpy (strTab->str[idx], s);
|
||||||
if(at(idx).size()<4)
|
|
||||||
at(idx)=s;
|
|
||||||
else
|
|
||||||
at(idx) = string(s)+at(idx).substr(4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void writeStrTab (FILE *fp, strTable strTab)
|
||||||
/* Writes the contents of the string table on the file fp. */
|
/* Writes the contents of the string table on the file fp. */
|
||||||
static void writeStrTab (std::ostream &ios, strTable &strTab)
|
{ Int i;
|
||||||
{
|
|
||||||
for (size_t i = 0; i < strTab.size(); i++)
|
for (i = 0; i < strTab.numLines; i++)
|
||||||
ios << strTab[i];
|
fprintf (fp, "%s", strTab.str[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void writeBundle (FILE *fp, bundle procCode)
|
||||||
/* Writes the contents of the bundle (procedure code and declaration) to
|
/* Writes the contents of the bundle (procedure code and declaration) to
|
||||||
* a file. */
|
* a file. */
|
||||||
void writeBundle (std::ostream &ios, bundle procCode)
|
|
||||||
{
|
{
|
||||||
writeStrTab (ios, procCode.decl);
|
writeStrTab (fp, procCode.decl);
|
||||||
writeStrTab (ios, procCode.code);
|
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. */
|
/* Frees the storage allocated by the string table. */
|
||||||
static void freeStrTab (strTable &strTab)
|
{ Int i;
|
||||||
{
|
|
||||||
strTab.clear();
|
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)
|
void freeBundle (bundle *procCode)
|
||||||
{
|
/* Deallocates the space taken by the bundle procCode */
|
||||||
freeStrTab (procCode->decl);
|
{
|
||||||
freeStrTab (procCode->code);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
688
src/chklib.cpp
688
src/chklib.cpp
File diff suppressed because it is too large
Load Diff
494
src/comwrite.cpp
494
src/comwrite.cpp
@ -7,274 +7,258 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include "machine_x86.h"
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
#define intSize 40
|
#define intSize 40
|
||||||
|
|
||||||
static const char *int21h[] =
|
static char *int21h[] =
|
||||||
{
|
{"Terminate process",
|
||||||
"Terminate process",
|
"Character input with echo",
|
||||||
"Character input with echo",
|
"Character output",
|
||||||
"Character output",
|
"Auxiliary input",
|
||||||
"Auxiliary input",
|
"Auxiliary output",
|
||||||
"Auxiliary output",
|
"Printer output",
|
||||||
"Printer output",
|
"Direct console i/o",
|
||||||
"Direct console i/o",
|
"Unfiltered char i w/o echo",
|
||||||
"Unfiltered char i w/o echo",
|
"Character input without echo",
|
||||||
"Character input without echo",
|
"Display string",
|
||||||
"Display string",
|
"Buffered keyboard input",
|
||||||
"Buffered keyboard input",
|
"Check input status",
|
||||||
"Check input status",
|
"Flush input buffer and then input",
|
||||||
"Flush input buffer and then input",
|
"Disk reset",
|
||||||
"Disk reset",
|
"Select disk",
|
||||||
"Select disk",
|
"Open file",
|
||||||
"Open file",
|
"Close file",
|
||||||
"Close file",
|
"Find first file",
|
||||||
"Find first file",
|
"Find next file",
|
||||||
"Find next file",
|
"Delete file",
|
||||||
"Delete file",
|
"Sequential read",
|
||||||
"Sequential read",
|
"Sequential write",
|
||||||
"Sequential write",
|
"Create file",
|
||||||
"Create file",
|
"Rename file",
|
||||||
"Rename file",
|
"Reserved",
|
||||||
"Reserved",
|
"Get current disk",
|
||||||
"Get current disk",
|
"Set DTA address",
|
||||||
"Set DTA address",
|
"Get default drive data",
|
||||||
"Get default drive data",
|
"Get drive data",
|
||||||
"Get drive data",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Random read",
|
||||||
"Random read",
|
"Random write",
|
||||||
"Random write",
|
"Get file size",
|
||||||
"Get file size",
|
"Set relative record number",
|
||||||
"Set relative record number",
|
"Set interrupt vector",
|
||||||
"Set interrupt vector",
|
"Create new PSP",
|
||||||
"Create new PSP",
|
"Random block read",
|
||||||
"Random block read",
|
"Random block write",
|
||||||
"Random block write",
|
"Parse filename",
|
||||||
"Parse filename",
|
"Get date",
|
||||||
"Get date",
|
"Set date",
|
||||||
"Set date",
|
"Get time",
|
||||||
"Get time",
|
"Set time",
|
||||||
"Set time",
|
"Set verify flag",
|
||||||
"Set verify flag",
|
"Get DTA address",
|
||||||
"Get DTA address",
|
"Get MSDOS version number",
|
||||||
"Get MSDOS version number",
|
"Terminate and stay resident",
|
||||||
"Terminate and stay resident",
|
"Reserved",
|
||||||
"Reserved",
|
"Get or set break flag",
|
||||||
"Get or set break flag",
|
"Reserved",
|
||||||
"Reserved",
|
"Get interrupt vector",
|
||||||
"Get interrupt vector",
|
"Get drive allocation info",
|
||||||
"Get drive allocation info",
|
"Reserved",
|
||||||
"Reserved",
|
"Get or set country info",
|
||||||
"Get or set country info",
|
"Create directory",
|
||||||
"Create directory",
|
"Delete directory",
|
||||||
"Delete directory",
|
"Set current directory",
|
||||||
"Set current directory",
|
"Create file",
|
||||||
"Create file",
|
"Open file",
|
||||||
"Open file",
|
"Close file",
|
||||||
"Close file",
|
"Read file or device",
|
||||||
"Read file or device",
|
"Write file or device",
|
||||||
"Write file or device",
|
"Delete file",
|
||||||
"Delete file",
|
"Set file pointer",
|
||||||
"Set file pointer",
|
"Get or set file attributes",
|
||||||
"Get or set file attributes",
|
"IOCTL (i/o control)",
|
||||||
"IOCTL (i/o control)",
|
"Duplicate handle",
|
||||||
"Duplicate handle",
|
"Redirect handle",
|
||||||
"Redirect handle",
|
"Get current directory",
|
||||||
"Get current directory",
|
"Alloate memory block",
|
||||||
"Alloate memory block",
|
"Release memory block",
|
||||||
"Release memory block",
|
"Resize memory block",
|
||||||
"Resize memory block",
|
"Execute program (exec)",
|
||||||
"Execute program (exec)",
|
"Terminate process with return code",
|
||||||
"Terminate process with return code",
|
"Get return code",
|
||||||
"Get return code",
|
"Find first file",
|
||||||
"Find first file",
|
"Find next file",
|
||||||
"Find next file",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Get verify flag",
|
||||||
"Get verify flag",
|
"Reserved",
|
||||||
"Reserved",
|
"Rename file",
|
||||||
"Rename file",
|
"Get or set file date & time",
|
||||||
"Get or set file date & time",
|
"Get or set allocation strategy",
|
||||||
"Get or set allocation strategy",
|
"Get extended error information",
|
||||||
"Get extended error information",
|
"Create temporary file",
|
||||||
"Create temporary file",
|
"Create new file",
|
||||||
"Create new file",
|
"Lock or unlock file region",
|
||||||
"Lock or unlock file region",
|
"Reserved",
|
||||||
"Reserved",
|
"Get machine name",
|
||||||
"Get machine name",
|
"Device redirection",
|
||||||
"Device redirection",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Get PSP address",
|
||||||
"Get PSP address",
|
"Get DBCS lead byte table",
|
||||||
"Get DBCS lead uint8_t table",
|
"Reserved",
|
||||||
"Reserved",
|
"Get extended country information",
|
||||||
"Get extended country information",
|
"Get or set code page",
|
||||||
"Get or set code page",
|
"Set handle count",
|
||||||
"Set handle count",
|
"Commit file",
|
||||||
"Commit file",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Reserved",
|
||||||
"Reserved",
|
"Extended open file"
|
||||||
"Extended open file"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const char *intOthers[] = {
|
static char *intOthers[] = {
|
||||||
"Exit", /* 0x20 */
|
"Exit", /* 0x20 */
|
||||||
"", /* other table */
|
"", /* other table */
|
||||||
"Terminate handler address", /* 0x22 */
|
"Terminate handler address", /* 0x22 */
|
||||||
"Ctrl-C handler address", /* 0x23 */
|
"Ctrl-C handler address", /* 0x23 */
|
||||||
"Critical-error handler address", /* 0x24 */
|
"Critical-error handler address", /* 0x24 */
|
||||||
"Absolute disk read", /* 0x25 */
|
"Absolute disk read", /* 0x25 */
|
||||||
"Absolute disk write", /* 0x26 */
|
"Absolute disk write", /* 0x26 */
|
||||||
"Terminate and stay resident", /* 0x27 */
|
"Terminate and stay resident", /* 0x27 */
|
||||||
"Reserved", /* 0x28 */
|
"Reserved", /* 0x28 */
|
||||||
"Reserved", /* 0x29 */
|
"Reserved", /* 0x29 */
|
||||||
"Reserved", /* 0x2A */
|
"Reserved", /* 0x2A */
|
||||||
"Reserved", /* 0x2B */
|
"Reserved", /* 0x2B */
|
||||||
"Reserved", /* 0x2C */
|
"Reserved", /* 0x2C */
|
||||||
"Reserved", /* 0x2D */
|
"Reserved", /* 0x2D */
|
||||||
"Reserved" /* 0x2E */
|
"Reserved" /* 0x2E */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Writes the description of the current interrupt. Appends it to the
|
void writeIntComment (PICODE icode, char *s)
|
||||||
|
/* Writes the description of the current interrupt. Appends it to the
|
||||||
* string s. */
|
* string s. */
|
||||||
void LLInst::writeIntComment (std::ostringstream &s)
|
{ char *t;
|
||||||
{
|
|
||||||
uint32_t src_immed=src().getImm2();
|
t = (char *)allocMem(intSize * sizeof(char));
|
||||||
s<<"\t/* ";
|
if (icode->ic.ll.immed.op == 0x21)
|
||||||
if (src_immed == 0x21)
|
{ sprintf (t, "\t/* %s */\n", int21h[icode->ic.ll.dst.off]);
|
||||||
{
|
strcat (s, t);
|
||||||
s <<int21h[dst.off];
|
}
|
||||||
|
else if (icode->ic.ll.immed.op > 0x1F && icode->ic.ll.immed.op < 0x2F)
|
||||||
|
{
|
||||||
|
sprintf (t, "\t/* %s */\n", intOthers[icode->ic.ll.immed.op - 0x20]);
|
||||||
|
strcat (s, t);
|
||||||
}
|
}
|
||||||
else if (src_immed > 0x1F && src_immed < 0x2F)
|
else if (icode->ic.ll.immed.op == 0x2F)
|
||||||
{
|
switch (icode->ic.ll.dst.off) {
|
||||||
s <<intOthers[src_immed - 0x20];
|
case 0x01 : strcat (s, "\t/* Print spooler */\n");
|
||||||
}
|
break;
|
||||||
else if (src_immed == 0x2F)
|
case 0x02: strcat (s, "\t/* Assign */\n");
|
||||||
{
|
break;
|
||||||
switch (dst.off)
|
case 0x10: strcat (s, "\t/* Share */\n");
|
||||||
{
|
break;
|
||||||
case 0x01 :
|
case 0xB7: strcat (s, "\t/* Append */\n");
|
||||||
s << "Print spooler";
|
}
|
||||||
break;
|
else
|
||||||
case 0x02:
|
strcat (s, "\n");
|
||||||
s << "Assign";
|
|
||||||
break;
|
|
||||||
case 0x10:
|
|
||||||
s << "Share";
|
|
||||||
break;
|
|
||||||
case 0xB7:
|
|
||||||
s << "Append";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s<<"Unknown int";
|
|
||||||
s<<" */\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//, &cCode.decl
|
void writeProcComments (PPROC p, strTable *strTab)
|
||||||
void Function::writeProcComments()
|
{ int i;
|
||||||
{
|
ID *id; /* Pointer to register argument identifier */
|
||||||
std::ostringstream ostr;
|
PSTKSYM psym; /* Pointer to register argument symbol */
|
||||||
writeProcComments(ostr);
|
|
||||||
cCode.appendDecl(ostr.str());
|
/* About the parameters */
|
||||||
|
if (p->cbParam)
|
||||||
|
appendStrTab (strTab, "/* Takes %d bytes of parameters.\n",
|
||||||
|
p->cbParam);
|
||||||
|
else if (p->flg & REG_ARGS)
|
||||||
|
{
|
||||||
|
appendStrTab (strTab, "/* Uses register arguments:\n");
|
||||||
|
for (i = 0; i < p->args.numArgs; i++)
|
||||||
|
{
|
||||||
|
psym = &p->args.sym[i];
|
||||||
|
if (psym->regs->expr.ident.idType == REGISTER)
|
||||||
|
{
|
||||||
|
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 = &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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
appendStrTab (strTab, "/* Takes no parameters.\n");
|
||||||
|
|
||||||
|
/* Type of procedure */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
appendStrTab (strTab, " * Return value in register al.\n");
|
||||||
|
break;
|
||||||
|
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||||
|
appendStrTab (strTab, " * Return value in register ax.\n");
|
||||||
|
break;
|
||||||
|
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||||
|
appendStrTab (strTab, " * Return value in registers dx:ax.\n");
|
||||||
|
break;
|
||||||
|
} /* eos */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calling convention */
|
||||||
|
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 (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 (p->flg & GRAPH_IRRED)
|
||||||
|
appendStrTab (strTab," * Irreducible control flow graph.\n");
|
||||||
|
appendStrTab (strTab, " */\n{\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Function::writeProcComments(std::ostream &ostr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
ID *id; /* Pointer to register argument identifier */
|
|
||||||
STKSYM * 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)
|
|
||||||
{
|
|
||||||
ostr << "/* Uses register arguments:\n";
|
|
||||||
for (i = 0; i < this->args.numArgs; i++)
|
|
||||||
{
|
|
||||||
psym = &this->args[i];
|
|
||||||
ostr << " * "<<psym->name<<" = ";
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
ostr << ".\n";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ostr << "/* 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)
|
|
||||||
{
|
|
||||||
ostr << " * Untranslatable routine. Assembler provided.\n";
|
|
||||||
if (this->flg & PROC_IS_FUNC)
|
|
||||||
switch (this->retVal.type) { // TODO: Functions return value in various regs
|
|
||||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
|
||||||
ostr << " * Return value in register al.\n";
|
|
||||||
break;
|
|
||||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
|
||||||
ostr << " * Return value in register ax.\n";
|
|
||||||
break;
|
|
||||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
|
||||||
ostr << " * 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";
|
|
||||||
|
|
||||||
/* 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";
|
|
||||||
|
|
||||||
/* Graph reducibility */
|
|
||||||
if (this->flg & GRAPH_IRRED)
|
|
||||||
ostr << " * Irreducible control flow graph.\n";
|
|
||||||
ostr << " */\n{\n";
|
|
||||||
}
|
|
||||||
|
|||||||
1071
src/control.cpp
1071
src/control.cpp
File diff suppressed because it is too large
Load Diff
1988
src/dataflow.cpp
1988
src/dataflow.cpp
File diff suppressed because it is too large
Load Diff
132
src/dcc.cpp
132
src/dcc.cpp
@ -5,36 +5,37 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include "project.h"
|
|
||||||
#include <string.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 */
|
/* Global variables - extern to other modules */
|
||||||
|
char *progname; /* argv[0] - for error msgs */
|
||||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||||
SYMTAB symtab; /* Global symbol table */
|
SYMTAB symtab; /* Global symbol table */
|
||||||
STATS stats; /* cfg statistics */
|
STATS stats; /* cfg statistics */
|
||||||
//PROG prog; /* programs fields */
|
PROG prog; /* programs fields */
|
||||||
OPTION option; /* Command line options */
|
OPTION option; /* Command line options */
|
||||||
//Function * pProcList; /* List of procedures, topologically sort */
|
PPROC pProcList; /* List of procedures, topologically sort */
|
||||||
//Function * pLastProc; /* Pointer to last node in procedure list */
|
PPROC pLastProc; /* Pointer to last node in procedure list */
|
||||||
//FunctionListType pProcList;
|
CALL_GRAPH *callGraph; /* Call graph of the program */
|
||||||
//CALL_GRAPH *callGraph; /* Call graph of the program */
|
|
||||||
|
|
||||||
static char *initargs(int argc, char *argv[]);
|
static char *initargs(int argc, char *argv[]);
|
||||||
static void displayTotalStats(void);
|
static void displayTotalStats();
|
||||||
#include <llvm/Support/raw_os_ostream.h>
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* main
|
* main
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include <iostream>
|
|
||||||
extern Project g_proj;
|
|
||||||
int main(int argc, char *argv[])
|
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 */
|
/* Extract switches and filename */
|
||||||
strcpy(option.filename, initargs(argc, argv));
|
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
|
* building the call graph and attaching appropriate bits of code for
|
||||||
* each procedure.
|
* each procedure.
|
||||||
*/
|
*/
|
||||||
DccFrontend fe(option.filename);
|
FrontEnd (option.filename, &callGraph);
|
||||||
if(false==fe.FrontEnd ())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* In the middle is a so called Universal Decompiling Machine.
|
/* In the middle is a so called Universal Decompiling Machine.
|
||||||
* It processes the procedure list and I-code and attaches where it can
|
* 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
|
* analysis, data flow etc. and outputs it to output file ready for
|
||||||
* re-compilation.
|
* re-compilation.
|
||||||
*/
|
*/
|
||||||
BackEnd(option.filename, g_proj.callGraph);
|
BackEnd(option.filename, callGraph);
|
||||||
|
|
||||||
g_proj.callGraph->write();
|
writeCallGraph (callGraph);
|
||||||
|
|
||||||
if (option.Stats)
|
if (option.Stats)
|
||||||
displayTotalStats();
|
displayTotalStats();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
freeDataStructures(pProcList);
|
freeDataStructures(pProcList);
|
||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
@ -75,51 +74,50 @@ int main(int argc, char *argv[])
|
|||||||
static char *initargs(int argc, char *argv[])
|
static char *initargs(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *pc;
|
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++)
|
for (pc = argv[0]+1; *pc; pc++)
|
||||||
switch (*pc)
|
switch (*pc) {
|
||||||
{
|
case 'a': /* Print assembler listing */
|
||||||
case 'a': /* Print assembler listing */
|
if (*(pc+1) == '2')
|
||||||
if (*(pc+1) == '2')
|
option.asm2 = TRUE;
|
||||||
option.asm2 = true;
|
else
|
||||||
else
|
option.asm1 = TRUE;
|
||||||
option.asm1 = true;
|
if (*(pc+1) == '1' || *(pc+1) == '2')
|
||||||
if (*(pc+1) == '1' || *(pc+1) == '2')
|
pc++;
|
||||||
pc++;
|
break;
|
||||||
break;
|
case 'c':
|
||||||
case 'c':
|
option.Calls = TRUE;
|
||||||
option.Calls = true;
|
break;
|
||||||
break;
|
case 'i':
|
||||||
case 'i':
|
option.Interact = TRUE;
|
||||||
option.Interact = true;
|
break;
|
||||||
break;
|
case 'm': /* Print memory map */
|
||||||
case 'm': /* Print memory map */
|
option.Map = TRUE;
|
||||||
option.Map = true;
|
break;
|
||||||
break;
|
case 's': /* Print Stats */
|
||||||
case 's': /* Print Stats */
|
option.Stats = TRUE;
|
||||||
option.Stats = true;
|
break;
|
||||||
break;
|
case 'V': /* Very verbose => verbose */
|
||||||
case 'V': /* Very verbose => verbose */
|
option.VeryVerbose = TRUE;
|
||||||
option.VeryVerbose = true;
|
case 'v': /* Make everything verbose */
|
||||||
case 'v':
|
option.verbose = TRUE;
|
||||||
option.verbose = true; /* Make everything verbose */
|
break;
|
||||||
break;
|
case 'o': /* assembler output file */
|
||||||
case 'o': /* assembler output file */
|
if (*(pc+1)) {
|
||||||
if (*(pc+1)) {
|
asm1_name = asm2_name = pc+1;
|
||||||
asm1_name = asm2_name = pc+1;
|
goto NextArg;
|
||||||
goto NextArg;
|
}
|
||||||
}
|
else if (--argc > 0) {
|
||||||
else if (--argc > 0) {
|
asm1_name = asm2_name = *++argv;
|
||||||
asm1_name = asm2_name = *++argv;
|
goto NextArg;
|
||||||
goto NextArg;
|
}
|
||||||
}
|
default:
|
||||||
default:
|
fatalError(INVALID_ARG, *pc);
|
||||||
fatalError(INVALID_ARG, *pc);
|
return *argv;
|
||||||
return *argv;
|
|
||||||
}
|
}
|
||||||
NextArg:;
|
NextArg:;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
@ -128,13 +126,13 @@ NextArg:;
|
|||||||
{
|
{
|
||||||
if (! asm1_name)
|
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, '.');
|
pc = strrchr(asm1_name, '.');
|
||||||
if (pc > strrchr(asm1_name, '/'))
|
if (pc > strrchr(asm1_name, '/'))
|
||||||
{
|
{
|
||||||
*pc = '\0';
|
*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");
|
strcat(strcpy(asm2_name, asm1_name), ".a2");
|
||||||
unlink(asm2_name);
|
unlink(asm2_name);
|
||||||
strcat(asm1_name, ".a1");
|
strcat(asm1_name, ".a1");
|
||||||
@ -142,10 +140,10 @@ NextArg:;
|
|||||||
unlink(asm1_name); /* Remove asm output files */
|
unlink(asm1_name); /* Remove asm output files */
|
||||||
}
|
}
|
||||||
return *argv; /* filename of the program to decompile */
|
return *argv; /* filename of the program to decompile */
|
||||||
}
|
}
|
||||||
|
|
||||||
fatalError(USAGE);
|
fatalError(USAGE);
|
||||||
return *argv; // does not reach this.
|
return *argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
1761
src/disassem.cpp
1761
src/disassem.cpp
File diff suppressed because it is too large
Load Diff
@ -3,47 +3,54 @@
|
|||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
|
|
||||||
static std::map<eErrorId,std::string> errorMessage =
|
#include <stdio.h>
|
||||||
{
|
#include <stdlib.h>
|
||||||
{INVALID_ARG ,"Invalid option -%c\n"},
|
//#ifndef __UNIX__
|
||||||
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
|
#if 1
|
||||||
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
|
#include <stdarg.h>
|
||||||
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
|
#else
|
||||||
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
|
#include <varargs.h>
|
||||||
{CANNOT_OPEN ,"Cannot open %s\n"},
|
#endif
|
||||||
{CANNOT_READ ,"Error while reading %s\n"},
|
|
||||||
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
|
static char *errorMessage[] = {
|
||||||
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
|
"Invalid option -%c\n", /* INVALID_ARG */
|
||||||
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
|
"Invalid instruction %02X at location %06lX\n", /* INVALID_OPCODE */
|
||||||
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
|
"Don't understand 80386 instruction %02X at location %06lX\n",
|
||||||
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
|
/* INVALID_386OP */
|
||||||
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
|
"Segment override with no memory operand at location %06lX\n",
|
||||||
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
|
/* FUNNY_SEGOVR */
|
||||||
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
|
"REP prefix without a string instruction at location %06lX\n",/* FUNNY_REP */
|
||||||
{NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"},
|
"Cannot open %s\n", /* CANNOT_OPEN */
|
||||||
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
|
"Error while reading %s\n", /* CANNOT_READ */
|
||||||
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
|
"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.
|
fatalError: displays error message and exits the program.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void fatalError(eErrorId errId, ...)
|
void fatalError(Int errId, ...)
|
||||||
{ va_list args;
|
{ va_list args;
|
||||||
//#ifdef __UNIX__ /* ultrix */
|
//#ifdef __UNIX__ /* ultrix */
|
||||||
#if 0
|
#if 0
|
||||||
int errId;
|
Int errId;
|
||||||
|
|
||||||
va_start(args);
|
va_start(args);
|
||||||
errId = va_arg(args, int);
|
errId = va_arg(args, Int);
|
||||||
#else
|
#else
|
||||||
va_start(args, errId);
|
va_start(args, errId);
|
||||||
#endif
|
#endif
|
||||||
@ -52,7 +59,7 @@ void fatalError(eErrorId errId, ...)
|
|||||||
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
|
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "dcc: ");
|
fprintf(stderr, "dcc: ");
|
||||||
vfprintf(stderr, errorMessage[errId].c_str(), args);
|
vfprintf(stderr, errorMessage[errId - 1], args);
|
||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
exit((int)errId);
|
exit((int)errId);
|
||||||
@ -62,18 +69,18 @@ void fatalError(eErrorId errId, ...)
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
reportError: reports the warning/error and continues with the program.
|
reportError: reports the warning/error and continues with the program.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void reportError(eErrorId errId, ...)
|
void reportError(Int errId, ...)
|
||||||
{ va_list args;
|
{ va_list args;
|
||||||
//#ifdef __UNIX__ /* ultrix */
|
//#ifdef __UNIX__ /* ultrix */
|
||||||
#if 0
|
#if 0
|
||||||
int errId;
|
Int errId;
|
||||||
|
|
||||||
va_start(args);
|
va_start(args);
|
||||||
errId = va_arg(args, int);
|
errId = va_arg(args, Int);
|
||||||
#else /* msdos or windows*/
|
#else /* msdos or windows*/
|
||||||
va_start(args, errId);
|
va_start(args, errId);
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "dcc: ");
|
fprintf(stderr, "dcc: ");
|
||||||
vfprintf(stderr, errorMessage[errId].c_str(), args);
|
vfprintf(stderr, errorMessage[errId - 1], args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|||||||
138
src/fixwild.cpp
138
src/fixwild.cpp
@ -18,26 +18,29 @@
|
|||||||
|
|
||||||
#ifndef bool
|
#ifndef bool
|
||||||
#define bool unsigned char
|
#define bool unsigned char
|
||||||
#define uint8_t unsigned char
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#define byte unsigned char
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int pc; /* Indexes into pat[] */
|
static int pc; /* Indexes into pat[] */
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static bool ModRM(uint8_t pat[]); /* Handle the mod/rm uint8_t */
|
static bool ModRM(byte pat[]); /* Handle the mod/rm byte */
|
||||||
static bool TwoWild(uint8_t pat[]); /* Make the next 2 bytes wild */
|
static bool TwoWild(byte pat[]); /* Make the next 2 bytes wild */
|
||||||
static bool FourWild(uint8_t pat[]); /* Make the next 4 bytes wild */
|
static bool FourWild(byte pat[]); /* Make the next 4 bytes wild */
|
||||||
void fixWildCards(uint8_t pat[]); /* Main routine */
|
void fixWildCards(byte pat[]); /* Main routine */
|
||||||
|
|
||||||
|
|
||||||
/* Handle the mod/rm case. Returns true if pattern exhausted */
|
/* 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 */
|
/* A standard mod/rm byte follows opcode */
|
||||||
op = pat[pc++]; /* The mod/rm uint8_t */
|
op = pat[pc++]; /* The mod/rm byte */
|
||||||
if (pc >= PATLEN) return true; /* Skip Mod/RM */
|
if (pc >= PATLEN) return TRUE; /* Skip Mod/RM */
|
||||||
switch (op & 0xC0)
|
switch (op & 0xC0)
|
||||||
{
|
{
|
||||||
case 0x00: /* [reg] or [nnnn] */
|
case 0x00: /* [reg] or [nnnn] */
|
||||||
@ -45,42 +48,42 @@ static bool ModRM(uint8_t pat[])
|
|||||||
{
|
{
|
||||||
/* Uses [nnnn] address mode */
|
/* Uses [nnnn] address mode */
|
||||||
pat[pc++] = WILD;
|
pat[pc++] = WILD;
|
||||||
if (pc >= PATLEN) return true;
|
if (pc >= PATLEN) return TRUE;
|
||||||
pat[pc++] = WILD;
|
pat[pc++] = WILD;
|
||||||
if (pc >= PATLEN) return true;
|
if (pc >= PATLEN) return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x40: /* [reg + nn] */
|
case 0x40: /* [reg + nn] */
|
||||||
if ((pc+=1) >= PATLEN) return true;
|
if ((pc+=1) >= PATLEN) return TRUE;
|
||||||
break;
|
break;
|
||||||
case 0x80: /* [reg + nnnn] */
|
case 0x80: /* [reg + nnnn] */
|
||||||
/* Possibly just a long constant offset from a register,
|
/* Possibly just a long constant offset from a register,
|
||||||
but often will be an index from a variable */
|
but often will be an index from a variable */
|
||||||
pat[pc++] = WILD;
|
pat[pc++] = WILD;
|
||||||
if (pc >= PATLEN) return true;
|
if (pc >= PATLEN) return TRUE;
|
||||||
pat[pc++] = WILD;
|
pat[pc++] = WILD;
|
||||||
if (pc >= PATLEN) return true;
|
if (pc >= PATLEN) return TRUE;
|
||||||
break;
|
break;
|
||||||
case 0xC0: /* reg */
|
case 0xC0: /* reg */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change the next two bytes to wild cards */
|
/* Change the next two bytes to wild cards */
|
||||||
static bool
|
static bool
|
||||||
TwoWild(uint8_t pat[])
|
TwoWild(byte pat[])
|
||||||
{
|
{
|
||||||
pat[pc++] = WILD;
|
pat[pc++] = WILD;
|
||||||
if (pc >= PATLEN) return true; /* Pattern exhausted */
|
if (pc >= PATLEN) return TRUE; /* Pattern exhausted */
|
||||||
pat[pc++] = WILD;
|
pat[pc++] = WILD;
|
||||||
if (pc >= PATLEN) return true;
|
if (pc >= PATLEN) return TRUE;
|
||||||
return false;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change the next four bytes to wild cards */
|
/* Change the next four bytes to wild cards */
|
||||||
static bool
|
static bool
|
||||||
FourWild(uint8_t pat[])
|
FourWild(byte pat[])
|
||||||
{
|
{
|
||||||
TwoWild(pat);
|
TwoWild(pat);
|
||||||
return 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
|
/* Chop from the current point by wiping with zeroes. Can't rely on anything
|
||||||
after this point */
|
after this point */
|
||||||
static void
|
static void
|
||||||
chop(uint8_t pat[])
|
chop(byte pat[])
|
||||||
{
|
{
|
||||||
if (pc >= PATLEN) return; /* Could go negative otherwise */
|
if (pc >= PATLEN) return; /* Could go negative otherwise */
|
||||||
memset(&pat[pc], 0, PATLEN - pc);
|
memset(&pat[pc], 0, PATLEN - pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool op0F(uint8_t pat[])
|
static bool
|
||||||
|
op0F(byte pat[])
|
||||||
{
|
{
|
||||||
/* The two uint8_t opcodes */
|
/* The two byte opcodes */
|
||||||
uint8_t op = pat[pc++];
|
byte op = pat[pc++];
|
||||||
switch (op & 0xF0)
|
switch (op & 0xF0)
|
||||||
{
|
{
|
||||||
case 0x00: /* 00 - 0F */
|
case 0x00: /* 00 - 0F */
|
||||||
if (op >= 0x06) /* Clts, Invd, Wbinvd */
|
if (op >= 0x06) /* Clts, Invd, Wbinvd */
|
||||||
return false;
|
return FALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Grp 6, Grp 7, LAR, LSL */
|
/* Grp 6, Grp 7, LAR, LSL */
|
||||||
@ -113,10 +117,10 @@ static bool op0F(uint8_t pat[])
|
|||||||
return ModRM(pat);
|
return ModRM(pat);
|
||||||
|
|
||||||
case 0x80:
|
case 0x80:
|
||||||
pc += 2; /* uint16_t displacement cond jumps */
|
pc += 2; /* Word displacement cond jumps */
|
||||||
return false;
|
return FALSE;
|
||||||
|
|
||||||
case 0x90: /* uint8_t set on condition */
|
case 0x90: /* Byte set on condition */
|
||||||
return ModRM(pat);
|
return ModRM(pat);
|
||||||
|
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
@ -126,7 +130,7 @@ static bool op0F(uint8_t pat[])
|
|||||||
case 0xA1: /* Pop FS */
|
case 0xA1: /* Pop FS */
|
||||||
case 0xA8: /* Push GS */
|
case 0xA8: /* Push GS */
|
||||||
case 0xA9: /* Pop GS */
|
case 0xA9: /* Pop GS */
|
||||||
return false;
|
return FALSE;
|
||||||
|
|
||||||
case 0xA3: /* Bt Ev,Gv */
|
case 0xA3: /* Bt Ev,Gv */
|
||||||
case 0xAB: /* Bts Ev,Gv */
|
case 0xAB: /* Bts Ev,Gv */
|
||||||
@ -134,9 +138,9 @@ static bool op0F(uint8_t pat[])
|
|||||||
|
|
||||||
case 0xA4: /* Shld EvGbIb */
|
case 0xA4: /* Shld EvGbIb */
|
||||||
case 0xAC: /* Shrd EvGbIb */
|
case 0xAC: /* Shrd EvGbIb */
|
||||||
if (ModRM(pat)) return true;
|
if (ModRM(pat)) return TRUE;
|
||||||
pc++; /* The #num bits to shift */
|
pc++; /* The #num bits to shift */
|
||||||
return false;
|
return FALSE;
|
||||||
|
|
||||||
case 0xA5: /* Shld EvGb CL */
|
case 0xA5: /* Shld EvGb CL */
|
||||||
case 0xAD: /* Shrd EvGb CL */
|
case 0xAD: /* Shrd EvGb CL */
|
||||||
@ -150,9 +154,9 @@ static bool op0F(uint8_t pat[])
|
|||||||
if (op == 0xBA)
|
if (op == 0xBA)
|
||||||
{
|
{
|
||||||
/* Grp 8: bt/bts/btr/btc Ev,#nn */
|
/* Grp 8: bt/bts/btr/btc Ev,#nn */
|
||||||
if (ModRM(pat)) return true;
|
if (ModRM(pat)) return TRUE;
|
||||||
pc++; /* The #num bits to shift */
|
pc++; /* The #num bits to shift */
|
||||||
return false;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return ModRM(pat);
|
return ModRM(pat);
|
||||||
|
|
||||||
@ -163,10 +167,10 @@ static bool op0F(uint8_t pat[])
|
|||||||
return ModRM(pat);
|
return ModRM(pat);
|
||||||
}
|
}
|
||||||
/* Else BSWAP */
|
/* Else BSWAP */
|
||||||
return false;
|
return FALSE;
|
||||||
|
|
||||||
default:
|
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.
|
PATLEN bytes are scanned.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fixWildCards(uint8_t pat[])
|
fixWildCards(byte pat[])
|
||||||
{
|
{
|
||||||
|
|
||||||
uint8_t op, quad, intArg;
|
byte op, quad, intArg;
|
||||||
|
|
||||||
|
|
||||||
pc=0;
|
pc=0;
|
||||||
@ -193,17 +197,17 @@ fixWildCards(uint8_t pat[])
|
|||||||
op = pat[pc++];
|
op = pat[pc++];
|
||||||
if (pc >= PATLEN) return;
|
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)
|
if (quad == 0)
|
||||||
{
|
{
|
||||||
/* Arithmetic group 00-3F */
|
/* Arithmetic group 00-3F */
|
||||||
|
|
||||||
if ((op & 0xE7) == 0x26) /* First check for the odds */
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (op == 0x0F) /* 386 2 uint8_t opcodes */
|
if (op == 0x0F) /* 386 2 byte opcodes */
|
||||||
{
|
{
|
||||||
if (op0F(pat)) return;
|
if (op0F(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
@ -214,20 +218,20 @@ fixWildCards(uint8_t pat[])
|
|||||||
/* All these are constant. Work out the instr length */
|
/* All these are constant. Work out the instr length */
|
||||||
if (op & 2)
|
if (op & 2)
|
||||||
{
|
{
|
||||||
/* Push, pop, other 1 uint8_t opcodes */
|
/* Push, pop, other 1 byte opcodes */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (op & 1)
|
if (op & 1)
|
||||||
{
|
{
|
||||||
/* uint16_t immediate operands */
|
/* Word immediate operands */
|
||||||
pc += 2;
|
pc += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* uint8_t immediate operands */
|
/* Byte immediate operands */
|
||||||
pc++;
|
pc++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -253,7 +257,7 @@ fixWildCards(uint8_t pat[])
|
|||||||
/* 0x60 - 0x70 */
|
/* 0x60 - 0x70 */
|
||||||
if (op & 0x10)
|
if (op & 0x10)
|
||||||
{
|
{
|
||||||
/* 70-7F 2 uint8_t jump opcodes */
|
/* 70-7F 2 byte jump opcodes */
|
||||||
pc++;
|
pc++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -280,11 +284,11 @@ fixWildCards(uint8_t pat[])
|
|||||||
if (TwoWild(pat)) return;
|
if (TwoWild(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0x68: /* Push uint8_t */
|
case 0x68: /* Push byte */
|
||||||
case 0x6A: /* Push uint8_t */
|
case 0x6A: /* Push byte */
|
||||||
case 0x6D: /* insb port */
|
case 0x6D: /* insb port */
|
||||||
case 0x6F: /* outsb port */
|
case 0x6F: /* outsb port */
|
||||||
/* 2 uint8_t instr, no wilds */
|
/* 2 byte instr, no wilds */
|
||||||
pc++;
|
pc++;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -298,14 +302,14 @@ fixWildCards(uint8_t pat[])
|
|||||||
switch (op & 0xF0)
|
switch (op & 0xF0)
|
||||||
{
|
{
|
||||||
case 0x80: /* 80 - 8F */
|
case 0x80: /* 80 - 8F */
|
||||||
/* All have a mod/rm uint8_t */
|
/* All have a mod/rm byte */
|
||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
/* These also have immediate values */
|
/* These also have immediate values */
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case 0x80:
|
case 0x80:
|
||||||
case 0x83:
|
case 0x83:
|
||||||
/* One uint8_t immediate */
|
/* One byte immediate */
|
||||||
pc++;
|
pc++;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -324,7 +328,7 @@ fixWildCards(uint8_t pat[])
|
|||||||
if (FourWild(pat)) return;
|
if (FourWild(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* All others are 1 uint8_t opcodes */
|
/* All others are 1 byte opcodes */
|
||||||
continue;
|
continue;
|
||||||
case 0xA0: /* A0 - AF */
|
case 0xA0: /* A0 - AF */
|
||||||
if ((op & 0x0C) == 0)
|
if ((op & 0x0C) == 0)
|
||||||
@ -335,7 +339,7 @@ fixWildCards(uint8_t pat[])
|
|||||||
}
|
}
|
||||||
else if ((op & 0xFE) == 0xA8)
|
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;
|
if (op & 1) pc += 2;
|
||||||
else pc += 1;
|
else pc += 1;
|
||||||
continue;
|
continue;
|
||||||
@ -364,10 +368,10 @@ fixWildCards(uint8_t pat[])
|
|||||||
/* In the last quadrant of the op code table */
|
/* In the last quadrant of the op code table */
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case 0xC0: /* 386: Rotate group 2 ModRM, uint8_t, #uint8_t */
|
case 0xC0: /* 386: Rotate group 2 ModRM, byte, #byte */
|
||||||
case 0xC1: /* 386: Rotate group 2 ModRM, uint16_t, #uint8_t */
|
case 0xC1: /* 386: Rotate group 2 ModRM, word, #byte */
|
||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
/* uint8_t immediate value follows ModRM */
|
/* Byte immediate value follows ModRM */
|
||||||
pc++;
|
pc++;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -388,27 +392,27 @@ fixWildCards(uint8_t pat[])
|
|||||||
|
|
||||||
case 0xC6: /* Mov ModRM, #nn */
|
case 0xC6: /* Mov ModRM, #nn */
|
||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
/* uint8_t immediate value follows ModRM */
|
/* Byte immediate value follows ModRM */
|
||||||
pc++;
|
pc++;
|
||||||
continue;
|
continue;
|
||||||
case 0xC7: /* Mov ModRM, #nnnn */
|
case 0xC7: /* Mov ModRM, #nnnn */
|
||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
/* uint16_t immediate value follows ModRM */
|
/* Word immediate value follows ModRM */
|
||||||
/* Immediate 16 bit values might be constant, but also
|
/* Immediate 16 bit values might be constant, but also
|
||||||
might be relocatable. For now, make them wild */
|
might be relocatable. For now, make them wild */
|
||||||
if (TwoWild(pat)) return;
|
if (TwoWild(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xC8: /* Enter Iw, Ib */
|
case 0xC8: /* Enter Iw, Ib */
|
||||||
pc += 3; /* Constant uint16_t, uint8_t */
|
pc += 3; /* Constant word, byte */
|
||||||
continue;
|
continue;
|
||||||
case 0xC9: /* Leave */
|
case 0xC9: /* Leave */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xCC: /* int 3 */
|
case 0xCC: /* Int 3 */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xCD: /* int nn */
|
case 0xCD: /* Int nn */
|
||||||
intArg = pat[pc++];
|
intArg = pat[pc++];
|
||||||
if ((intArg >= 0x34) && (intArg <= 0x3B))
|
if ((intArg >= 0x34) && (intArg <= 0x3B))
|
||||||
{
|
{
|
||||||
@ -423,10 +427,10 @@ fixWildCards(uint8_t pat[])
|
|||||||
case 0xCF: /* Iret */
|
case 0xCF: /* Iret */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xD0: /* Group 2 rotate, uint8_t, 1 bit */
|
case 0xD0: /* Group 2 rotate, byte, 1 bit */
|
||||||
case 0xD1: /* Group 2 rotate, uint16_t, 1 bit */
|
case 0xD1: /* Group 2 rotate, word, 1 bit */
|
||||||
case 0xD2: /* Group 2 rotate, uint8_t, CL bits */
|
case 0xD2: /* Group 2 rotate, byte, CL bits */
|
||||||
case 0xD3: /* Group 2 rotate, uint16_t, CL bits */
|
case 0xD3: /* Group 2 rotate, word, CL bits */
|
||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -498,8 +502,8 @@ fixWildCards(uint8_t pat[])
|
|||||||
case 0xFD: /* Std */
|
case 0xFD: /* Std */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 0xF6: /* Group 3 uint8_t test/not/mul/div */
|
case 0xF6: /* Group 3 byte test/not/mul/div */
|
||||||
case 0xF7: /* Group 3 uint16_t test/not/mul/div */
|
case 0xF7: /* Group 3 word test/not/mul/div */
|
||||||
case 0xFE: /* Inc/Dec group 4 */
|
case 0xFE: /* Inc/Dec group 4 */
|
||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
@ -509,7 +513,7 @@ fixWildCards(uint8_t pat[])
|
|||||||
if (ModRM(pat)) return;
|
if (ModRM(pat)) return;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
default: /* Rest are single uint8_t opcodes */
|
default: /* Rest are single byte opcodes */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
693
src/frontend.cpp
693
src/frontend.cpp
@ -1,51 +1,54 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* dcc project Front End module
|
* dcc project Front End module
|
||||||
* Loads a program into simulated main memory and builds the procedure list.
|
* Loads a program into simulated main memory and builds the procedure list.
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include "disassem.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#ifdef __BORLAND__
|
||||||
|
#include <alloc.h>
|
||||||
|
#else
|
||||||
#include <malloc.h> /* For malloc, free, realloc */
|
#include <malloc.h> /* For malloc, free, realloc */
|
||||||
#include "project.h"
|
#endif
|
||||||
|
|
||||||
typedef struct { /* PSP structure */
|
typedef struct { /* PSP structure */
|
||||||
uint16_t int20h; /* interrupt 20h */
|
word int20h; /* interrupt 20h */
|
||||||
uint16_t eof; /* segment, end of allocation block */
|
word eof; /* segment, end of allocation block */
|
||||||
uint8_t res1; /* reserved */
|
byte res1; /* reserved */
|
||||||
uint8_t dosDisp[5]; /* far call to DOS function dispatcher */
|
byte dosDisp[5]; /* far call to DOS function dispatcher */
|
||||||
uint8_t int22h[4]; /* vector for terminate routine */
|
byte int22h[4]; /* vector for terminate routine */
|
||||||
uint8_t int23h[4]; /* vector for ctrl+break routine */
|
byte int23h[4]; /* vector for ctrl+break routine */
|
||||||
uint8_t int24h[4]; /* vector for error routine */
|
byte int24h[4]; /* vector for error routine */
|
||||||
uint8_t res2[22]; /* reserved */
|
byte res2[22]; /* reserved */
|
||||||
uint16_t segEnv; /* segment address of environment block */
|
word segEnv; /* segment address of environment block */
|
||||||
uint8_t res3[34]; /* reserved */
|
byte res3[34]; /* reserved */
|
||||||
uint8_t int21h[6]; /* opcode for int21h and far return */
|
byte int21h[6]; /* opcode for int21h and far return */
|
||||||
uint8_t res4[6]; /* reserved */
|
byte res4[6]; /* reserved */
|
||||||
uint8_t fcb1[16]; /* default file control block 1 */
|
byte fcb1[16]; /* default file control block 1 */
|
||||||
uint8_t fcb2[16]; /* default file control block 2 */
|
byte fcb2[16]; /* default file control block 2 */
|
||||||
uint8_t res5[4]; /* reserved */
|
byte res5[4]; /* reserved */
|
||||||
uint8_t cmdTail[0x80]; /* command tail and disk transfer area */
|
byte cmdTail[0x80]; /* command tail and disk transfer area */
|
||||||
} PSP;
|
} PSP;
|
||||||
|
|
||||||
static struct { /* EXE file header */
|
static struct { /* EXE file header */
|
||||||
uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */
|
byte sigLo; /* .EXE signature: 0x4D 0x5A */
|
||||||
uint8_t sigHi;
|
byte sigHi;
|
||||||
uint16_t lastPageSize; /* Size of the last page */
|
word lastPageSize; /* Size of the last page */
|
||||||
uint16_t numPages; /* Number of pages in the file */
|
word numPages; /* Number of pages in the file */
|
||||||
uint16_t numReloc; /* Number of relocation items */
|
word numReloc; /* Number of relocation items */
|
||||||
uint16_t numParaHeader; /* # of paragraphs in the header */
|
word numParaHeader; /* # of paragraphs in the header */
|
||||||
uint16_t minAlloc; /* Minimum number of paragraphs */
|
word minAlloc; /* Minimum number of paragraphs */
|
||||||
uint16_t maxAlloc; /* Maximum number of paragraphs */
|
word maxAlloc; /* Maximum number of paragraphs */
|
||||||
uint16_t initSS; /* Segment displacement of stack */
|
word initSS; /* Segment displacement of stack */
|
||||||
uint16_t initSP; /* Contents of SP at entry */
|
word initSP; /* Contents of SP at entry */
|
||||||
uint16_t checkSum; /* Complemented checksum */
|
word checkSum; /* Complemented checksum */
|
||||||
uint16_t initIP; /* Contents of IP at entry */
|
word initIP; /* Contents of IP at entry */
|
||||||
uint16_t initCS; /* Segment displacement of code */
|
word initCS; /* Segment displacement of code */
|
||||||
uint16_t relocTabOffset; /* Relocation table offset */
|
word relocTabOffset; /* Relocation table offset */
|
||||||
uint16_t overlayNum; /* Overlay number */
|
word overlayNum; /* Overlay number */
|
||||||
} header;
|
} header;
|
||||||
|
|
||||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||||
@ -55,294 +58,440 @@ static void displayLoadInfo(void);
|
|||||||
static void displayMemMap(void);
|
static void displayMemMap(void);
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||||
* rewritter, and displays any useful information.
|
* rewritter, and displays any useful information.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
extern Project g_proj;
|
void FrontEnd (char *filename, PCALL_GRAPH *pcallGraph)
|
||||||
bool DccFrontend::FrontEnd ()
|
|
||||||
{
|
{
|
||||||
|
PPROC pProc;
|
||||||
|
PSYM psym;
|
||||||
|
Int i, c;
|
||||||
|
|
||||||
|
/* Load program into memory */
|
||||||
|
LoadImage(filename);
|
||||||
|
|
||||||
g_proj.callGraph = 0;
|
if (option.verbose)
|
||||||
g_proj.m_fname = m_fname;
|
{
|
||||||
|
displayLoadInfo();
|
||||||
|
}
|
||||||
|
|
||||||
/* Load program into memory */
|
/* Do depth first flow analysis building call graph and procedure list,
|
||||||
LoadImage(g_proj);
|
* and attaching the I-code to each procedure */
|
||||||
|
parse (pcallGraph);
|
||||||
|
|
||||||
if (option.verbose)
|
if (option.asm1)
|
||||||
displayLoadInfo();
|
{
|
||||||
|
printf("dcc: writing assembler file %s\n", asm1_name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Do depth first flow analysis building call graph and procedure list,
|
/* Search through code looking for impure references and flag them */
|
||||||
* and attaching the I-code to each procedure */
|
for (pProc = pProcList; pProc; pProc = pProc->next)
|
||||||
parse (g_proj);
|
{
|
||||||
|
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)
|
||||||
|
disassem(1, pProc);
|
||||||
|
}
|
||||||
|
|
||||||
if (option.asm1)
|
if (option.Interact)
|
||||||
{
|
{
|
||||||
printf("dcc: writing assembler file %s\n", asm1_name);
|
interactDis(pProcList, 0); /* Interactive disassembler */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search through code looking for impure references and flag them */
|
/* Converts jump target addresses to icode offsets */
|
||||||
Disassembler ds(1);
|
for (pProc = pProcList; pProc; pProc = pProc->next)
|
||||||
for(Function &f : g_proj.pProcList)
|
bindIcodeOff (pProc);
|
||||||
{
|
|
||||||
f.markImpure();
|
|
||||||
if (option.asm1)
|
|
||||||
{
|
|
||||||
ds.disassem(&f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (option.Interact)
|
|
||||||
{
|
|
||||||
interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Converts jump target addresses to icode offsets */
|
/* Print memory bitmap */
|
||||||
for(Function &f : g_proj.pProcList)
|
if (option.Map)
|
||||||
{
|
displayMemMap();
|
||||||
f.bindIcodeOff();
|
|
||||||
}
|
|
||||||
/* 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)
|
static void displayLoadInfo(void)
|
||||||
{
|
{
|
||||||
PROG &prog(Project::get()->prog);
|
Int i;
|
||||||
int i;
|
|
||||||
|
|
||||||
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
|
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
|
||||||
if (! prog.fCOM) {
|
if (! prog.fCOM) {
|
||||||
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
|
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
|
||||||
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
|
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
|
||||||
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
|
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
|
||||||
printf("# relocation items = %04X\n", LH(&header.numReloc));
|
printf("# relocation items = %04X\n", LH(&header.numReloc));
|
||||||
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
|
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
|
||||||
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
||||||
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
||||||
}
|
}
|
||||||
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
|
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
|
||||||
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
|
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
|
||||||
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
|
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
|
||||||
|
|
||||||
if (option.VeryVerbose && prog.cReloc)
|
if (option.VeryVerbose && prog.cReloc)
|
||||||
{
|
{
|
||||||
printf("\nRelocation Table\n");
|
printf("\nRelocation Table\n");
|
||||||
for (i = 0; i < prog.cReloc; i++)
|
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");
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* fill - Fills line for displayMemMap()
|
* fill - Fills line for displayMemMap()
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static void fill(int ip, char *bf)
|
static void fill(Int ip, char *bf)
|
||||||
{
|
{
|
||||||
PROG &prog(Project::get()->prog);
|
static byte type[4] = {'.', 'd', 'c', 'x'};
|
||||||
static uint8_t type[4] = {'.', 'd', 'c', 'x'};
|
byte i;
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++, ip++)
|
for (i = 0; i < 16; i++, ip++)
|
||||||
{
|
{
|
||||||
*bf++ = ' ';
|
*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';
|
}
|
||||||
|
*bf = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* displayMemMap - Displays the memory bitmap
|
* displayMemMap - Displays the memory bitmap
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static void displayMemMap(void)
|
static void displayMemMap(void)
|
||||||
{
|
{
|
||||||
PROG &prog(Project::get()->prog);
|
char c, b1[33], b2[33], b3[33];
|
||||||
|
byte i;
|
||||||
|
Int ip = 0;
|
||||||
|
|
||||||
char c, b1[33], b2[33], b3[33];
|
printf("\nMemory Map\n");
|
||||||
uint8_t i;
|
while (ip < prog.cbImage)
|
||||||
int ip = 0;
|
{
|
||||||
|
fill(ip, b1);
|
||||||
printf("\nMemory Map\n");
|
printf("%06X %s\n", ip, b1);
|
||||||
while (ip < prog.cbImage)
|
ip += 16;
|
||||||
{
|
for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
|
||||||
fill(ip, b1);
|
; /* Check if all same */
|
||||||
printf("%06X %s\n", ip, b1);
|
if (i > 32)
|
||||||
ip += 16;
|
{
|
||||||
for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
|
fill(ip, b2); /* Skip until next two are not same */
|
||||||
; /* Check if all same */
|
fill(ip+16, b3);
|
||||||
if (i > 32)
|
if (! (strcmp(b1, b2) || strcmp(b1, b3)))
|
||||||
{
|
{
|
||||||
fill(ip, b2); /* Skip until next two are not same */
|
printf(" :\n");
|
||||||
fill(ip+16, b3);
|
do
|
||||||
if (! (strcmp(b1, b2) || strcmp(b1, b3)))
|
{
|
||||||
{
|
ip += 16;
|
||||||
printf(" :\n");
|
fill(ip+16, b1);
|
||||||
do
|
} while (! strcmp(b1, b2));
|
||||||
{
|
}
|
||||||
ip += 16;
|
}
|
||||||
fill(ip+16, b1);
|
}
|
||||||
} while (! strcmp(b1, b2));
|
printf("\n");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* LoadImage
|
* LoadImage
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void DccFrontend::LoadImage(Project &proj)
|
static void LoadImage(char *filename)
|
||||||
{
|
{
|
||||||
PROG &prog(Project::get()->prog);
|
FILE *fp;
|
||||||
FILE *fp;
|
Int i, cb;
|
||||||
int i, cb;
|
byte buf[4];
|
||||||
uint8_t buf[4];
|
|
||||||
|
|
||||||
/* Open the input file */
|
/* 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 */
|
/* Read in first 2 bytes to check EXE signature */
|
||||||
if (fread(&header, 1, 2, fp) != 2)
|
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))) {
|
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
|
||||||
/* Read rest of header */
|
/* Read rest of header */
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
if (fread(&header, sizeof(header), 1, fp) != 1)
|
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! */
|
/* This is a typical DOS kludge! */
|
||||||
if (LH(&header.relocTabOffset) == 0x40)
|
if (LH(&header.relocTabOffset) == 0x40)
|
||||||
{
|
{
|
||||||
fatalError(NEWEXE_FORMAT);
|
fatalError(NEWEXE_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the load module size.
|
/* Calculate the load module size.
|
||||||
* This is the number of pages in the file
|
* This is the number of pages in the file
|
||||||
* less the length of the header and reloc table
|
* less the length of the header and reloc table
|
||||||
* less the number of bytes unused on last page
|
* 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)
|
if (header.lastPageSize)
|
||||||
{
|
{
|
||||||
cb -= 512 - LH(&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)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);
|
||||||
|
|
||||||
/* We quietly ignore minAlloc and maxAlloc since for our
|
/* Allocate the relocation table */
|
||||||
* purposes it doesn't really matter where in real memory
|
if (prog.cReloc)
|
||||||
* the program would end up. EXE programs can't really rely on
|
{
|
||||||
* their load location so setting the PSP segment to 0 is fine.
|
prog.relocTable = (dword*)allocMem(prog.cReloc * sizeof(Int));
|
||||||
* Certainly programs that prod around in DOS or BIOS are going
|
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/* Allocate the relocation table */
|
/* Read in seg:offset pairs and convert to Image ptrs */
|
||||||
if (prog.cReloc)
|
for (i = 0; i < prog.cReloc; i++)
|
||||||
{
|
{
|
||||||
prog.relocTable = new uint32_t [prog.cReloc];
|
fread(buf, 1, 4, fp);
|
||||||
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
|
prog.relocTable[i] = LH(buf) +
|
||||||
|
(((Int)LH(buf+2) + EXE_RELOCATION)<<4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Seek to start of image */
|
||||||
|
fseek(fp, (Int)LH(&header.numParaHeader) * 16, SEEK_SET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* COM file
|
||||||
|
* In this case the load module size is just the file length
|
||||||
|
*/
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
cb = ftell(fp);
|
||||||
|
|
||||||
/* Read in seg:offset pairs and convert to Image ptrs */
|
/* COM programs start off with an ORG 100H (to leave room for a PSP)
|
||||||
for (i = 0; i < prog.cReloc; i++)
|
* This is also the implied start address so if we load the image
|
||||||
{
|
* at offset 100H addresses should all line up properly again.
|
||||||
fread(buf, 1, 4, fp);
|
*/
|
||||||
prog.relocTable[i] = LH(buf) +
|
prog.initCS = 0;
|
||||||
(((int)LH(buf+2) + EXE_RELOCATION)<<4);
|
prog.initIP = 0x100;
|
||||||
}
|
prog.initSS = 0;
|
||||||
}
|
prog.initSP = 0xFFFE;
|
||||||
/* Seek to start of image */
|
prog.cReloc = 0;
|
||||||
uint32_t start_of_image= LH(&header.numParaHeader) * 16;
|
|
||||||
fseek(fp, start_of_image, SEEK_SET);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* COM file
|
|
||||||
* In this case the load module size is just the file length
|
|
||||||
*/
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
cb = ftell(fp);
|
|
||||||
|
|
||||||
/* COM programs start off with an ORG 100H (to leave room for a PSP)
|
fseek(fp, 0, SEEK_SET);
|
||||||
* This is also the implied start address so if we load the image
|
}
|
||||||
* at offset 100H addresses should all line up properly again.
|
|
||||||
*/
|
|
||||||
prog.initCS = 0;
|
|
||||||
prog.initIP = 0x100;
|
|
||||||
prog.initSS = 0;
|
|
||||||
prog.initSP = 0xFFFE;
|
|
||||||
prog.cReloc = 0;
|
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
/* Allocate a block of memory for the program. */
|
||||||
}
|
prog.cbImage = cb + sizeof(PSP);
|
||||||
|
prog.Image = (byte*)allocMem(prog.cbImage);
|
||||||
|
prog.Image[0] = 0xCD; /* Fill in PSP Int 20h location */
|
||||||
|
prog.Image[1] = 0x20; /* for termination checking */
|
||||||
|
|
||||||
/* Allocate a block of memory for the program. */
|
/* Read in the image past where a PSP would go */
|
||||||
prog.cbImage = cb + sizeof(PSP);
|
#ifdef __DOSWIN__
|
||||||
prog.Image = new uint8_t [prog.cbImage];
|
if (cb > 0xFFFF)
|
||||||
prog.Image[0] = 0xCD; /* Fill in PSP int 20h location */
|
{
|
||||||
prog.Image[1] = 0x20; /* for termination checking */
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/* Read in the image past where a PSP would go */
|
/* Set up memory map */
|
||||||
if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
|
cb = (prog.cbImage + 3) / 4;
|
||||||
{
|
prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb);
|
||||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up memory map */
|
/* Relocate segment constants */
|
||||||
cb = (prog.cbImage + 3) / 4;
|
if (prog.cReloc)
|
||||||
prog.map = (uint8_t *)malloc(cb);
|
{
|
||||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
for (i = 0; i < prog.cReloc; i++)
|
||||||
|
{
|
||||||
|
byte *p = &prog.Image[prog.relocTable[i]];
|
||||||
|
word w = (word)LH(p) + EXE_RELOCATION;
|
||||||
|
*p++ = (byte)(w & 0x00FF);
|
||||||
|
*p = (byte)((w & 0xFF00) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Relocate segment constants */
|
fclose(fp);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* allocMem - malloc with failure test
|
* allocMem - malloc with failure test
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void *allocMem(int cb)
|
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 0 /* Microsoft specific heap debugging code */
|
||||||
/* if (! (p = (uint8_t*)calloc((size_t)cb, 1))) */
|
switch (_heapset('Z'))
|
||||||
{
|
{
|
||||||
fatalError(MALLOC_FAILED, cb);
|
case _HEAPBADBEGIN: printf("aM: Bad heap begin\n"); break;
|
||||||
}
|
case _HEAPBADNODE: printf("aM: Bad heap node\n");
|
||||||
// printf("allocMem: %p\n", p);
|
printf("Attempt to allocMem %5d bytes\n", cb);
|
||||||
return 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();
|
||||||
|
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);/**/
|
||||||
|
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
|
||||||
|
|
||||||
|
|||||||
654
src/graph.cpp
654
src/graph.cpp
@ -5,406 +5,396 @@
|
|||||||
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#if __BORLAND__
|
||||||
|
#include <alloc.h>
|
||||||
|
#else
|
||||||
#include <malloc.h> /* For free() */
|
#include <malloc.h> /* For free() */
|
||||||
#include "graph.h"
|
#endif
|
||||||
#include "project.h"
|
|
||||||
extern Project g_proj;
|
static PBB rmJMP(PPROC pProc, Int marker, PBB pBB);
|
||||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
static void mergeFallThrough(PPROC pProc, PBB pBB);
|
||||||
static void mergeFallThrough(Function * pProc, BB * pBB);
|
static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last);
|
||||||
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* createCFG - Create the basic control flow graph
|
* createCFG - Create the basic control flow graph
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void Function::createCFG()
|
PBB createCFG(PPROC pProc)
|
||||||
{
|
{
|
||||||
/* Splits Icode associated with the procedure into Basic Blocks.
|
/* Splits Icode associated with the procedure into Basic Blocks.
|
||||||
* The links between BBs represent the control flow graph of the
|
* The links between BBs represent the control flow graph of the
|
||||||
* procedure.
|
* procedure.
|
||||||
* A Basic Block is defined to end on one of the following instructions:
|
* A Basic Block is defined to end on one of the following instructions:
|
||||||
* 1) Conditional and unconditional jumps
|
* 1) Conditional and unconditional jumps
|
||||||
* 2) CALL(F)
|
* 2) CALL(F)
|
||||||
* 3) RET(F)
|
* 3) RET(F)
|
||||||
* 4) On the instruction before a join (a flagged TARGET)
|
* 4) On the instruction before a join (a flagged TARGET)
|
||||||
* 5) Repeated string instructions
|
* 5) Repeated string instructions
|
||||||
* 6) End of procedure
|
* 6) End of procedure
|
||||||
*/
|
*/
|
||||||
int i;
|
Int i;
|
||||||
int ip;
|
Int ip, start;
|
||||||
BB * psBB;
|
BB cfg;
|
||||||
BB * pBB;
|
PBB psBB;
|
||||||
iICODE pIcode = Icode.begin();
|
PBB pBB = &cfg;
|
||||||
iICODE iStart = Icode.begin();
|
PICODE pIcode = pProc->Icode.GetFirstIcode();
|
||||||
stats.numBBbef = stats.numBBaft = 0;
|
|
||||||
for (; pIcode!=Icode.end(); ++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);
|
|
||||||
|
|
||||||
}
|
cfg.next = NULL;
|
||||||
|
stats.numBBbef = stats.numBBaft = 0;
|
||||||
|
for (ip = start = 0; pProc->Icode.IsValid(pIcode); ip++, pIcode++)
|
||||||
|
{
|
||||||
|
/* Stick a NOWHERE_NODE on the end if we terminate
|
||||||
|
* with anything other than a ret, jump or terminate */
|
||||||
|
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 */
|
/* 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 iJB: case iJBE: case iJAE: case iJA:
|
||||||
case iJL: case iJLE: case iJGE: case iJG:
|
case iJL: case iJLE: case iJGE: case iJG:
|
||||||
case iJE: case iJNE: case iJS: case iJNS:
|
case iJE: case iJNE: case iJS: case iJNS:
|
||||||
case iJO: case iJNO: case iJP: case iJNP:
|
case iJO: case iJNO: case iJP: case iJNP:
|
||||||
case iJCXZ:
|
case iJCXZ:
|
||||||
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
|
pBB = newBB(pBB, start, ip, TWO_BRANCH, 2, pProc);
|
||||||
CondJumps:
|
CondJumps:
|
||||||
//start = ip + 1;
|
start = ip + 1;
|
||||||
iStart = ++iICODE(pIcode);
|
pBB->edges[0].ip = (dword)start;
|
||||||
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
|
/* This is for jumps off into nowhere */
|
||||||
/* This is for jumps off into nowhere */
|
if (pIcode->ic.ll.flg & NO_LABEL)
|
||||||
if ( ll->testFlags(NO_LABEL) )
|
pBB->numOutEdges--;
|
||||||
{
|
else
|
||||||
pBB->edges.pop_back();
|
pBB->edges[1].ip = pIcode->ic.ll.immed.op;
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
pBB->edges[1].ip = ll->src().getImm2();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||||
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
|
pBB = newBB(pBB, start, ip, LOOP_NODE, 2, pProc);
|
||||||
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
|
goto CondJumps;
|
||||||
goto CondJumps;
|
|
||||||
|
|
||||||
case iJMPF: case iJMP:
|
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 = newBB(pBB, start, ip, MULTI_BRANCH,
|
||||||
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
|
pIcode->ic.ll.caseTbl.numEntries, pProc);
|
||||||
for (i = 0; i < ll->caseTbl2.size(); i++)
|
for (i = 0; i < pIcode->ic.ll.caseTbl.numEntries; i++)
|
||||||
pBB->edges[i].ip = ll->caseTbl2[i];
|
pBB->edges[i].ip = pIcode->ic.ll.caseTbl.entries[i];
|
||||||
hasCase = true;
|
pProc->hasCase = TRUE;
|
||||||
}
|
}
|
||||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
else if ((pIcode->ic.ll.flg & (I | NO_LABEL)) == I) {
|
||||||
{
|
pBB = newBB(pBB, start, ip, ONE_BRANCH, 1, pProc);
|
||||||
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
|
pBB->edges[0].ip = pIcode->ic.ll.immed.op;
|
||||||
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
|
}
|
||||||
|
else
|
||||||
|
newBB(pBB, start, ip, NOWHERE_NODE, 0, pProc);
|
||||||
|
start = ip + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
pBB->edges[0].ip = ll->src().getImm2();
|
case iCALLF: case iCALL:
|
||||||
}
|
{ PPROC p = pIcode->ic.ll.immed.proc.proc;
|
||||||
else
|
if (p)
|
||||||
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
||||||
iStart = ++iICODE(pIcode);
|
else
|
||||||
break;
|
i = 1;
|
||||||
|
pBB = newBB(pBB, start, ip, CALL_NODE, i, pProc);
|
||||||
|
start = ip + 1;
|
||||||
|
if (i)
|
||||||
|
pBB->edges[0].ip = (dword)start;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case iCALLF: case iCALL:
|
case iRET: case iRETF:
|
||||||
{
|
newBB(pBB, start, ip, RETURN_NODE, 0, pProc);
|
||||||
Function * p = ll->src().proc.proc;
|
start = ip + 1;
|
||||||
if (p)
|
break;
|
||||||
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
|
||||||
else
|
|
||||||
i = 1;
|
|
||||||
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
|
|
||||||
iStart = ++iICODE(pIcode);//start = ip + 1;
|
|
||||||
if (i)
|
|
||||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iRET: case iRETF:
|
default:
|
||||||
//BB::Create(start, ip, RETURN_NODE, 0, this);
|
/* Check for exit to DOS */
|
||||||
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
|
if (pIcode->ic.ll.flg & TERMINATES)
|
||||||
iStart = ++iICODE(pIcode);
|
{
|
||||||
break;
|
pBB = newBB(pBB, start, ip, TERMINATE_NODE, 0, pProc);
|
||||||
|
start = ip + 1;
|
||||||
|
}
|
||||||
|
/* Check for a fall through */
|
||||||
|
else if (pProc->Icode.GetFirstIcode()[ip + 1].ic.ll.flg & (TARGET | CASE))
|
||||||
|
{
|
||||||
|
pBB = newBB(pBB, start, ip, FALL_NODE, 1, pProc);
|
||||||
|
start = ip + 1;
|
||||||
|
pBB->edges[0].ip = (dword)start;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
/* Convert list of BBs into a graph */
|
||||||
/* Check for exit to DOS */
|
for (pBB = cfg.next; pBB; pBB = pBB->next)
|
||||||
iICODE next1=++iICODE(pIcode);
|
{
|
||||||
if ( ll->testFlags(TERMINATES) )
|
for (i = 0; i < pBB->numOutEdges; i++)
|
||||||
{
|
{
|
||||||
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
|
ip = pBB->edges[i].ip;
|
||||||
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
|
if (ip >= SYNTHESIZED_MIN)
|
||||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
fatalError (INVALID_SYNTHETIC_BB);
|
||||||
}
|
else
|
||||||
/* Check for a fall through */
|
{
|
||||||
else if (next1 != Icode.end())
|
for (psBB = cfg.next; psBB; psBB = psBB->next)
|
||||||
{
|
if (psBB->start == ip)
|
||||||
if (next1->ll()->testFlags(TARGET | CASE))
|
{
|
||||||
{
|
pBB->edges[i].BBptr = psBB;
|
||||||
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
|
psBB->numInEdges++;
|
||||||
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
|
break;
|
||||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
}
|
||||||
pBB->addOutEdge(iStart->loc_ip);
|
if (! psBB)
|
||||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
fatalError(NO_BB, ip, pProc->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
return cfg.next;
|
||||||
}
|
|
||||||
}
|
|
||||||
auto iter=heldBBs.begin();
|
|
||||||
/* Convert list of BBs into a graph */
|
|
||||||
for (; iter!=heldBBs.end(); ++iter)
|
|
||||||
{
|
|
||||||
pBB = *iter;
|
|
||||||
for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++)
|
|
||||||
{
|
|
||||||
uint32_t ip = pBB->edges[edeg_idx].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)
|
|
||||||
{
|
|
||||||
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++)
|
|
||||||
{
|
|
||||||
if (BITMAP(c, BM_CODE))
|
|
||||||
{
|
|
||||||
icod.ll()->setFlags(IMPURE);
|
|
||||||
flg |= IMPURE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* newBB - Allocate new BB and link to end of list
|
* 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
|
* freeCFG - Deallocates a cfg
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void Function::freeCFG()
|
void freeCFG(PBB cfg)
|
||||||
{
|
{
|
||||||
for(BB *p : heldBBs)
|
PBB pBB;
|
||||||
{
|
|
||||||
delete p;
|
for (pBB = cfg; pBB; pBB = cfg) {
|
||||||
}
|
if (pBB->inEdges)
|
||||||
|
free(pBB->inEdges);
|
||||||
|
if (pBB->edges)
|
||||||
|
free(pBB->edges);
|
||||||
|
cfg = pBB->next;
|
||||||
|
free(pBB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* compressCFG - Remove redundancies and add in-edge information
|
* compressCFG - Remove redundancies and add in-edge information
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void Function::compressCFG()
|
void compressCFG(PPROC pProc)
|
||||||
{
|
{ PBB pBB, pNxt;
|
||||||
BB *pNxt;
|
Int ip, first=0, last, i;
|
||||||
int ip, first=0, last;
|
|
||||||
|
|
||||||
/* First pass over BB list removes redundant jumps of the form
|
/* First pass over BB list removes redundant jumps of the form
|
||||||
* (Un)Conditional -> Unconditional jump */
|
* (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 ||
|
||||||
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
|
pBB->nodeType == TWO_BRANCH))
|
||||||
continue;
|
for (i = 0; i < pBB->numOutEdges; i++)
|
||||||
for (TYPEADR_TYPE &edgeRef : pBB->edges)
|
{
|
||||||
{
|
ip = pBB->start + pBB->length - 1;
|
||||||
ip = pBB->rbegin()->loc_ip;
|
pNxt = rmJMP(pProc, ip, pBB->edges[i].BBptr);
|
||||||
pNxt = edgeRef.BBptr->rmJMP(ip, edgeRef.BBptr);
|
|
||||||
|
|
||||||
if (not pBB->edges.empty()) /* Might have been clobbered */
|
if (pBB->numOutEdges) /* Might have been clobbered */
|
||||||
{
|
{
|
||||||
edgeRef.BBptr = pNxt;
|
pBB->edges[i].BBptr = pNxt;
|
||||||
assert(pBB->back().loc_ip==ip);
|
pProc->Icode.SetImmediateOp(ip, (dword)pNxt->start);
|
||||||
pBB->back().ll()->SetImmediateOp((uint32_t)pNxt->begin()->loc_ip);
|
}
|
||||||
//Icode[ip].SetImmediateOp((uint32_t)pNxt->begin());
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next is a depth-first traversal merging any FALL_NODE or
|
/* Next is a depth-first traversal merging any FALL_NODE or
|
||||||
* ONE_BRANCH that fall through to a node with that as their only
|
* ONE_BRANCH that fall through to a node with that as their only
|
||||||
* in-edge. */
|
* in-edge. */
|
||||||
m_cfg.front()->mergeFallThrough(Icode);
|
mergeFallThrough(pProc, pProc->cfg);
|
||||||
|
|
||||||
/* Remove redundant BBs created by the above compressions
|
/* Remove redundant BBs created by the above compressions
|
||||||
* and allocate in-edge arrays as required. */
|
* and allocate in-edge arrays as required. */
|
||||||
stats.numBBaft = stats.numBBbef;
|
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;
|
pNxt = pBB->next;
|
||||||
if (pBB->inEdges.empty())
|
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;
|
pBB->index = UN_INIT;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete pBB;
|
if (pBB->numOutEdges)
|
||||||
stats.numBBaft--;
|
free(pBB->edges);
|
||||||
}
|
free(pBB);
|
||||||
}
|
stats.numBBaft--;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
pBB->inEdgeCount = pBB->inEdges.size();
|
else
|
||||||
}
|
{
|
||||||
}
|
pBB->inEdgeCount = pBB->numInEdges;
|
||||||
|
pBB->inEdges = (PBB*)allocMem(pBB->numInEdges * sizeof(PBB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate storage for dfsLast[] array */
|
/* Allocate storage for dfsLast[] array */
|
||||||
numBBs = stats.numBBaft;
|
pProc->numBBs = stats.numBBaft;
|
||||||
m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *))
|
pProc->dfsLast = (PBB*)allocMem(pProc->numBBs * sizeof(PBB));
|
||||||
|
|
||||||
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
|
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
|
||||||
last = numBBs - 1;
|
last = pProc->numBBs - 1;
|
||||||
m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
|
dfsNumbering(pProc->cfg, pProc->dfsLast, &first, &last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* rmJMP - If BB addressed is just a JMP it is replaced with its target
|
* 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)
|
while (pBB->nodeType == ONE_BRANCH && pBB->length == 1) {
|
||||||
{
|
if (pBB->traversed != marker) {
|
||||||
if (pBB->traversed != marker)
|
pBB->traversed = marker;
|
||||||
{
|
if (--pBB->numInEdges)
|
||||||
pBB->traversed = (eDFS)marker;
|
pBB->edges[0].BBptr->numInEdges++;
|
||||||
pBB->inEdges.pop_back();
|
else
|
||||||
if (not pBB->inEdges.empty())
|
{
|
||||||
{
|
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||||
pBB->edges[0].BBptr->inEdges.push_back((BB *)nullptr);
|
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pBB->front().ll()->setFlags(NO_CODE);
|
|
||||||
pBB->front().invalidate(); //pProc->Icode.SetLlInvalid(pBB->begin(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
pBB = pBB->edges[0].BBptr;
|
pBB = pBB->edges[0].BBptr;
|
||||||
}
|
}
|
||||||
else
|
else { /* We are going around in circles */
|
||||||
{
|
pBB->nodeType = NOWHERE_NODE;
|
||||||
/* We are going around in circles */
|
pProc->Icode.GetIcode(pBB->start)->ic.ll.immed.op = (dword)pBB->start;
|
||||||
pBB->nodeType = NOWHERE_NODE;
|
pProc->Icode.SetImmediateOp(pBB->start, (dword)pBB->start);
|
||||||
pBB->front().ll()->replaceSrc(LLOperand::CreateImm2(pBB->front().loc_ip));
|
do {
|
||||||
//pBB->front().ll()->src.immed.op = pBB->front().loc_ip;
|
pBB = pBB->edges[0].BBptr;
|
||||||
do {
|
if (! --pBB->numInEdges)
|
||||||
pBB = pBB->edges[0].BBptr;
|
{
|
||||||
pBB->inEdges.pop_back(); // was --numInedges
|
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||||
if (! pBB->inEdges.empty())
|
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||||
{
|
}
|
||||||
pBB->front().ll()->setFlags(NO_CODE);
|
} while (pBB->nodeType != NOWHERE_NODE);
|
||||||
pBB->front().invalidate();
|
|
||||||
// pProc->Icode.setFlags(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;
|
}
|
||||||
|
}
|
||||||
|
return pBB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* mergeFallThrough
|
* mergeFallThrough
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void BB::mergeFallThrough( CIcodeRec &Icode)
|
static void mergeFallThrough(PPROC pProc, PBB pBB)
|
||||||
{
|
{
|
||||||
BB * pChild;
|
PBB pChild;
|
||||||
int i;
|
Int i, ip;
|
||||||
|
|
||||||
if (!this)
|
if (pBB) {
|
||||||
{
|
while (pBB->nodeType == FALL_NODE || pBB->nodeType == ONE_BRANCH)
|
||||||
printf("mergeFallThrough on empty BB!\n");
|
{
|
||||||
}
|
pChild = pBB->edges[0].BBptr;
|
||||||
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
|
/* Jump to next instruction can always be removed */
|
||||||
{
|
if (pBB->nodeType == ONE_BRANCH)
|
||||||
pChild = edges[0].BBptr;
|
{
|
||||||
/* Jump to next instruction can always be removed */
|
ip = pBB->start + pBB->length;
|
||||||
if (nodeType == ONE_BRANCH)
|
for (i = ip; i < pChild->start
|
||||||
{
|
&& (pProc->Icode.GetLlFlag(i) & NO_CODE); i++);
|
||||||
assert(Parent==pChild->Parent);
|
if (i != pChild->start)
|
||||||
if(back().loc_ip>pChild->front().loc_ip) // back edege
|
break;
|
||||||
break;
|
pProc->Icode.SetLlFlag(ip - 1, NO_CODE);
|
||||||
auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c)
|
pProc->Icode.SetLlInvalid(ip - 1, TRUE);
|
||||||
{return not c.ll()->testFlags(NO_CODE);});
|
pBB->nodeType = FALL_NODE;
|
||||||
|
pBB->length--;
|
||||||
|
|
||||||
if (iter != pChild->begin())
|
}
|
||||||
break;
|
/* If there's no other edges into child can merge */
|
||||||
back().ll()->setFlags(NO_CODE);
|
if (pChild->numInEdges != 1)
|
||||||
back().invalidate();
|
break;
|
||||||
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)
|
|
||||||
break;
|
|
||||||
|
|
||||||
nodeType = pChild->nodeType;
|
pBB->nodeType = pChild->nodeType;
|
||||||
instructions = boost::make_iterator_range(begin(),pChild->end());
|
pBB->length = pChild->start + pChild->length - pBB->start;
|
||||||
pChild->front().ll()->clrFlags(TARGET);
|
pProc->Icode.ClearLlFlag(pChild->start, TARGET);
|
||||||
edges.swap(pChild->edges);
|
pBB->numOutEdges = pChild->numOutEdges;
|
||||||
|
free(pBB->edges);
|
||||||
|
pBB->edges = pChild->edges;
|
||||||
|
|
||||||
pChild->inEdges.clear();
|
pChild->numOutEdges = pChild->numInEdges = 0;
|
||||||
pChild->edges.clear();
|
pChild->edges = NULL;
|
||||||
}
|
}
|
||||||
traversed = DFS_MERGE;
|
pBB->traversed = DFS_MERGE;
|
||||||
|
|
||||||
/* Process all out edges recursively */
|
/* Process all out edges recursively */
|
||||||
for (i = 0; i < edges.size(); i++)
|
for (i = 0; i < pBB->numOutEdges; i++)
|
||||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
if (pBB->edges[i].BBptr->traversed != DFS_MERGE)
|
||||||
edges[i].BBptr->mergeFallThrough(Icode);
|
mergeFallThrough(pProc, pBB->edges[i].BBptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* dfsNumbering - Numbers nodes during first and last visits and determine
|
* dfsNumbering - Numbers nodes during first and last visits and determine
|
||||||
* in-edges
|
* 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;
|
PBB pChild;
|
||||||
traversed = DFS_NUM;
|
byte i;
|
||||||
dfsFirstNum = (*first)++;
|
|
||||||
|
|
||||||
/* index is being used as an index to inEdges[]. */
|
if (pBB)
|
||||||
// for (i = 0; i < edges.size(); i++)
|
{
|
||||||
for(auto edge : edges)
|
pBB->traversed = DFS_NUM;
|
||||||
{
|
pBB->dfsFirstNum = (*first)++;
|
||||||
pChild = edge.BBptr;
|
|
||||||
pChild->inEdges[pChild->index++] = this;
|
|
||||||
|
|
||||||
/* Is this the last visit? */
|
/* index is being used as an index to inEdges[]. */
|
||||||
if (pChild->index == pChild->inEdges.size())
|
for (i = 0; i < pBB->numOutEdges; i++)
|
||||||
pChild->index = UN_INIT;
|
{
|
||||||
|
pChild = pBB->edges[i].BBptr;
|
||||||
|
pChild->inEdges[pChild->index++] = pBB;
|
||||||
|
|
||||||
if (pChild->traversed != DFS_NUM)
|
/* Is this the last visit? */
|
||||||
pChild->dfsNumbering(dfsLast, first, last);
|
if (pChild->index == pChild->numInEdges)
|
||||||
}
|
pChild->index = UN_INIT;
|
||||||
dfsLastNum = *last;
|
|
||||||
dfsLast[(*last)--] = this;
|
if (pChild->traversed != DFS_NUM)
|
||||||
|
dfsNumbering(pChild, dfsLast, first, last);
|
||||||
|
}
|
||||||
|
pBB->dfsLastNum = *last;
|
||||||
|
dfsLast[(*last)--] = pBB;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
838
src/hlicode.cpp
838
src/hlicode.cpp
@ -4,631 +4,483 @@
|
|||||||
* Date: September-October 1993
|
* Date: September-October 1993
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
*/
|
*/
|
||||||
#include <cassert>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
using namespace std;
|
|
||||||
#define ICODE_DELTA 25
|
#define ICODE_DELTA 25
|
||||||
|
|
||||||
/* Masks off bits set by duReg[] */
|
/* Masks off bits set by duReg[] */
|
||||||
std::bitset<32> maskDuReg[] = { 0x00,
|
dword maskDuReg[] = { 0x00,
|
||||||
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
|
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* word regs */
|
||||||
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
|
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
|
||||||
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
|
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
|
||||||
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
|
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* byte regs */
|
||||||
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
|
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
|
||||||
0xEFFFFF, /* tmp reg */
|
0xEFFFFF, /* tmp reg */
|
||||||
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
||||||
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
|
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
|
||||||
|
|
||||||
static char buf[lineSize]; /* Line buffer for hl icode output */
|
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 */
|
/* 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()
|
void newCallHlIcode (PICODE pIcode)
|
||||||
{
|
|
||||||
//assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
|
|
||||||
}
|
|
||||||
/* Places the new HLI_CALL high-level operand in the high-level icode array */
|
/* Places the new HLI_CALL high-level operand in the high-level icode array */
|
||||||
void ICODE::newCallHl()
|
|
||||||
{
|
{
|
||||||
type = HIGH_LEVEL;
|
pIcode->type = HIGH_LEVEL;
|
||||||
hl()->opcode = HLI_CALL;
|
pIcode->ic.hl.opcode = HLI_CALL;
|
||||||
hl()->call.proc = ll()->src().proc.proc;
|
pIcode->ic.hl.oper.call.proc = pIcode->ic.ll.immed.proc.proc;
|
||||||
hl()->call.args = new STKFRAME;
|
pIcode->ic.hl.oper.call.args = (STKFRAME*)allocMem (sizeof(STKFRAME));
|
||||||
|
memset (pIcode->ic.hl.oper.call.args, 0, sizeof(STKFRAME));
|
||||||
if (ll()->src().proc.cb != 0)
|
if (pIcode->ic.ll.immed.proc.cb != 0)
|
||||||
hl()->call.args->cb = ll()->src().proc.cb;
|
pIcode->ic.hl.oper.call.args->cb = pIcode->ic.ll.immed.proc.cb;
|
||||||
else if(hl()->call.proc)
|
else
|
||||||
hl()->call.args->cb =hl()->call.proc->cbParam;
|
pIcode->ic.hl.oper.call.args->cb =pIcode->ic.hl.oper.call.proc->cbParam;
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
|
|
||||||
hl()->call.args->cb = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
|
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 */
|
* array */
|
||||||
void ICODE::setUnary(hlIcode op, COND_EXPR *_exp)
|
|
||||||
{
|
{
|
||||||
type = HIGH_LEVEL;
|
pIcode->type = HIGH_LEVEL;
|
||||||
hl()->set(op,_exp);
|
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 */
|
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
|
||||||
void ICODE::setJCond(COND_EXPR *cexp)
|
|
||||||
{
|
{
|
||||||
type = HIGH_LEVEL;
|
pIcode->type = HIGH_LEVEL;
|
||||||
hl()->set(HLI_JCOND,cexp);
|
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. */
|
* 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.
|
boolT removeDefRegi (byte regi, PICODE picode, Int thisDefIdx, LOCAL_ID *locId)
|
||||||
* If all registers
|
/* Removes the defined register regi from the lhs subtree. If all registers
|
||||||
* of this instruction are unused, the instruction is invalidated (ie. removed)
|
* of this instruction are unused, the instruction is invalidated (ie.
|
||||||
*/
|
* removed) */
|
||||||
bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
|
{ Int numDefs;
|
||||||
{
|
|
||||||
int numDefs;
|
|
||||||
|
|
||||||
numDefs = du1.numRegsDef;
|
numDefs = picode->du1.numRegsDef;
|
||||||
if (numDefs == thisDefIdx)
|
if (numDefs == thisDefIdx)
|
||||||
{
|
|
||||||
for ( ; numDefs > 0; numDefs--)
|
for ( ; numDefs > 0; numDefs--)
|
||||||
{
|
{
|
||||||
|
if ((picode->du1.idx[numDefs-1][0] != 0)||(picode->du.lastDefRegi))
|
||||||
if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (numDefs == 0)
|
if (numDefs == 0)
|
||||||
{
|
{
|
||||||
invalidate();
|
invalidateIcode (picode);
|
||||||
return true;
|
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
|
else
|
||||||
{
|
{
|
||||||
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
|
switch (picode->ic.hl.opcode) {
|
||||||
res.call.args->cb = 0;
|
case HLI_ASSIGN: removeRegFromLong (regi, locId,
|
||||||
|
picode->ic.hl.oper.asgn.lhs);
|
||||||
|
picode->du1.numRegsDef--;
|
||||||
|
picode->du.def &= maskDuReg[regi];
|
||||||
|
break;
|
||||||
|
case HLI_POP:
|
||||||
|
case HLI_PUSH: removeRegFromLong (regi, locId, picode->ic.hl.oper.exp);
|
||||||
|
picode->du1.numRegsDef--;
|
||||||
|
picode->du.def &= maskDuReg[regi];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (FALSE);
|
||||||
}
|
}
|
||||||
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:
|
void highLevelGen (PPROC pProc)
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
|
||||||
pIcode->setRegDU( rAX, eDEF);
|
|
||||||
}
|
|
||||||
res.setAsgn(lhs, rhs);
|
|
||||||
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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
|
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
|
||||||
* Note: this process should be done before data flow analysis, which
|
* Note: this process should be done before data flow analysis, which
|
||||||
* refines the HIGH_LEVEL icodes. */
|
* refines the HIGH_LEVEL icodes. */
|
||||||
void Function::highLevelGen()
|
{ Int i, /* idx into icode array */
|
||||||
{
|
numIcode; /* number of icode instructions */
|
||||||
int numIcode; /* number of icode instructions */
|
PICODE pIcode; /* ptr to current icode node */
|
||||||
iICODE pIcode; /* ptr to current icode node */
|
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
|
||||||
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
|
flags32 flg; /* icode flags */
|
||||||
uint32_t _flg; /* icode flags */
|
|
||||||
numIcode = Icode.size();
|
numIcode = pProc->Icode.GetNumIcodes();
|
||||||
for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
|
for (i = 0; i < numIcode; i++)
|
||||||
{
|
{
|
||||||
assert(numIcode==Icode.size());
|
pIcode = pProc->Icode.GetIcode(i);
|
||||||
pIcode = i; //Icode.GetIcode(i)
|
if ((pIcode->ic.ll.flg & NOT_HLL) == NOT_HLL)
|
||||||
LLInst *ll = pIcode->ll();
|
invalidateIcode (pIcode);
|
||||||
if ( ll->testFlags(NOT_HLL) )
|
if ((pIcode->type == LOW_LEVEL) && (pIcode->invalid == FALSE))
|
||||||
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 */
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
switch (ll->getOpcode())
|
|
||||||
{
|
{
|
||||||
case iADD:
|
flg = pIcode->ic.ll.flg;
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
if ((flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
|
||||||
pIcode->setAsgn(lhs, rhs);
|
if ((flg & NO_OPS) != NO_OPS) /* if there are opers */
|
||||||
break;
|
|
||||||
|
|
||||||
case iAND:
|
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
|
||||||
pIcode->setAsgn(lhs, rhs);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iCALL:
|
|
||||||
case iCALLF:
|
|
||||||
pIcode->type = HIGH_LEVEL;
|
|
||||||
pIcode->hl( ll->createCall() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iDEC:
|
|
||||||
rhs = COND_EXPR::idKte (1, 2);
|
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
|
||||||
pIcode->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);
|
if ((flg & NO_SRC) != NO_SRC) /* if there is src op */
|
||||||
pIcode->setRegDU( rAL, eDEF);
|
rhs = idCondExp (pIcode, SRC, pProc, i, pIcode, NONE);
|
||||||
|
lhs = idCondExp (pIcode, DST, pProc, i, pIcode, NONE);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
|
||||||
pIcode->setRegDU( rAX, eDEF);
|
|
||||||
}
|
|
||||||
pIcode->setAsgn(lhs, rhs);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iIMUL:
|
switch (pIcode->ic.ll.opcode) {
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
case iADD: rhs = boolCondExp (lhs, rhs, ADD);
|
||||||
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case iINC:
|
case iAND: rhs = boolCondExp (lhs, rhs, AND);
|
||||||
rhs = COND_EXPR::idKte (1, 2);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
break;
|
||||||
pIcode->setAsgn(lhs, rhs);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iLEA:
|
case iCALL:
|
||||||
rhs = COND_EXPR::unary (ADDRESSOF, rhs);
|
case iCALLF: newCallHlIcode (pIcode);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case iMOD:
|
case iDEC: rhs = idCondExpKte (1, 2);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
|
rhs = boolCondExp (lhs, rhs, SUB);
|
||||||
if ( ll->testFlags(B) )
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
{
|
break;
|
||||||
lhs = COND_EXPR::idReg (rAH, 0, &localId);
|
|
||||||
pIcode->setRegDU( rAH, eDEF);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lhs = COND_EXPR::idReg (rDX, 0, &localId);
|
|
||||||
pIcode->setRegDU( rDX, eDEF);
|
|
||||||
}
|
|
||||||
pIcode->setAsgn(lhs, rhs);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
case iDIV:
|
||||||
break;
|
case iIDIV:/* should be signed div */
|
||||||
|
rhs = boolCondExp (lhs, rhs, DIV);
|
||||||
|
if (pIcode->ic.ll.flg & B)
|
||||||
|
{
|
||||||
|
lhs = idCondExpReg (rAL, 0, &pProc->localId);
|
||||||
|
setRegDU (pIcode, rAL, E_DEF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lhs = idCondExpReg (rAX, 0, &pProc->localId);
|
||||||
|
setRegDU (pIcode, rAX, E_DEF);
|
||||||
|
}
|
||||||
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
|
break;
|
||||||
|
|
||||||
case iMUL:
|
case iIMUL: rhs = boolCondExp (lhs, rhs, MUL);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode,
|
||||||
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
NONE);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iNEG:
|
case iINC: rhs = idCondExpKte (1, 2);
|
||||||
rhs = COND_EXPR::unary (NEGATION, lhs);
|
rhs = boolCondExp (lhs, rhs, ADD);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iNOT:
|
case iLEA: rhs = unaryCondExp (ADDRESSOF, rhs);
|
||||||
rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case iOR:
|
case iMOD: rhs = boolCondExp (lhs, rhs, MOD);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
if (pIcode->ic.ll.flg & B)
|
||||||
pIcode->setAsgn(lhs, rhs);
|
{
|
||||||
break;
|
lhs = idCondExpReg (rAH, 0, &pProc->localId);
|
||||||
|
setRegDU (pIcode, rAH, E_DEF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lhs = idCondExpReg (rDX, 0, &pProc->localId);
|
||||||
|
setRegDU (pIcode, rDX, E_DEF);
|
||||||
|
}
|
||||||
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
|
break;
|
||||||
|
|
||||||
case iPOP: pIcode->setUnary(HLI_POP, lhs);
|
case iMOV: newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
|
case iMUL: rhs = boolCondExp (lhs, rhs, MUL);
|
||||||
break;
|
lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode,
|
||||||
|
NONE);
|
||||||
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
|
break;
|
||||||
|
|
||||||
case iRET:
|
case iNEG: rhs = unaryCondExp (NEGATION, lhs);
|
||||||
case iRETF: pIcode->setUnary(HLI_RET, NULL);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iSHL:
|
case iNOT: rhs = boolCondExp (NULL, rhs, NOT);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case iSAR: /* signed */
|
case iOR: rhs = boolCondExp (lhs, rhs, OR);
|
||||||
case iSHR:
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
|
break;
|
||||||
pIcode->setAsgn(lhs, rhs);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iSIGNEX: pIcode->setAsgn(lhs, rhs);
|
case iPOP: newUnaryHlIcode (pIcode, HLI_POP, lhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iSUB:
|
case iPUSH: newUnaryHlIcode (pIcode, HLI_PUSH, lhs);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
break;
|
||||||
pIcode->setAsgn(lhs, rhs);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iXCHG:
|
case iRET:
|
||||||
break;
|
case iRETF: newUnaryHlIcode (pIcode, HLI_RET, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
case iXOR:
|
case iSHL: rhs = boolCondExp (lhs, rhs, SHL);
|
||||||
rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
pIcode->setAsgn(lhs, rhs);
|
break;
|
||||||
break;
|
|
||||||
|
case iSAR: /* signed */
|
||||||
|
case iSHR: rhs = boolCondExp (lhs, rhs, SHR); /* unsigned*/
|
||||||
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iSIGNEX: newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iSUB: rhs = boolCondExp (lhs, rhs, SUB);
|
||||||
|
newAsgnHlIcode (pIcode, lhs, rhs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iXCHG:
|
||||||
|
break;
|
||||||
|
|
||||||
|
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
|
/* Modifies the given conditional operator to its inverse. This is used
|
||||||
* in if..then[..else] statements, to reflect the condition that takes the
|
* in if..then[..else] statements, to reflect the condition that takes the
|
||||||
* then part. */
|
* then part. */
|
||||||
COND_EXPR *COND_EXPR::inverse () const
|
{
|
||||||
{
|
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
|
||||||
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
|
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
|
||||||
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
|
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
|
||||||
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
|
DUMMY, DBL_OR, DBL_AND};
|
||||||
DUMMY, DBL_OR, DBL_AND};
|
if (*exp == NULL) return;
|
||||||
COND_EXPR *res=0;
|
|
||||||
if (m_type == BOOLEAN_OP)
|
|
||||||
{
|
|
||||||
switch ( 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;
|
|
||||||
|
|
||||||
case AND: case OR: case XOR: case NOT: case ADD:
|
if ((*exp)->type == BOOLEAN_OP)
|
||||||
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
{
|
||||||
return COND_EXPR::unary (NEGATION, this->clone());
|
switch ((*exp)->expr.boolExpr.op) {
|
||||||
|
case LESS_EQUAL: case LESS: case EQUAL:
|
||||||
|
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
|
||||||
|
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
|
||||||
|
break;
|
||||||
|
|
||||||
case DBL_AND: case DBL_OR:
|
case AND: case OR: case XOR: case NOT: case ADD:
|
||||||
// Binary::Create(invertop,lhs->inverse(),rhs->inverse());
|
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
||||||
res = this->clone();
|
*exp = unaryCondExp (NEGATION, *exp);
|
||||||
res->boolExpr.op = invCondOp[op()];
|
break;
|
||||||
res->boolExpr.lhs=lhs()->inverse ();
|
|
||||||
res->boolExpr.rhs=rhs()->inverse ();
|
|
||||||
return res;
|
|
||||||
} /* eos */
|
|
||||||
|
|
||||||
}
|
case DBL_AND: case DBL_OR:
|
||||||
else if (m_type == NEGATION) //TODO: memleak here
|
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
|
||||||
{
|
inverseCondOp (&(*exp)->expr.boolExpr.lhs);
|
||||||
return expr.unaryExp->clone();
|
inverseCondOp (&(*exp)->expr.boolExpr.rhs);
|
||||||
}
|
break;
|
||||||
return this->clone();
|
} /* eos */
|
||||||
/* other types are left unmodified */
|
|
||||||
|
}
|
||||||
|
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
|
/* Returns the string that represents the procedure call of tproc (ie. with
|
||||||
* actual parameters) */
|
* actual parameters) */
|
||||||
std::string writeCall (Function * tproc, STKFRAME & args, Function * pproc, int *numLoc)
|
{ Int i; /* counter of # arguments */
|
||||||
{
|
char *s, *condExp;
|
||||||
int i; /* counter of # arguments */
|
|
||||||
string condExp;
|
s = (char*)allocMem (100 * sizeof(char));
|
||||||
ostringstream ostr;
|
s[0] = '\0';
|
||||||
ostr<<tproc->name<<" (";
|
sprintf (s, "%s (", tproc->name);
|
||||||
for(const STKSYM &sym : args)
|
for (i = 0; i < args->csym; i++)
|
||||||
{
|
{
|
||||||
ostr << walkCondExpr (sym.actual, pproc, numLoc);
|
condExp = walkCondExpr (args->sym[i].actual, pproc, numLoc);
|
||||||
if((&sym)!=&(args.back()))
|
strcat (s, condExp);
|
||||||
ostr << ", ";
|
if (i < (args->csym - 1))
|
||||||
|
strcat (s, ", ");
|
||||||
}
|
}
|
||||||
ostr << ")";
|
strcat (s, ")");
|
||||||
return ostr.str();
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *writeJcond (HLTYPE h, PPROC pProc, Int *numLoc)
|
||||||
/* Displays the output of a HLI_JCOND icode. */
|
/* Displays the output of a HLI_JCOND icode. */
|
||||||
char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
|
{ char *e;
|
||||||
{
|
|
||||||
assert(h.expr());
|
|
||||||
memset (buf, ' ', sizeof(buf));
|
memset (buf, ' ', sizeof(buf));
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
strcat (buf, "if ");
|
strcat (buf, "if ");
|
||||||
COND_EXPR *inverted=h.expr()->inverse();
|
inverseCondOp (&h.oper.exp);
|
||||||
//inverseCondOp (&h.exp);
|
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||||
std::string e = walkCondExpr (inverted, pProc, numLoc);
|
strcat (buf, e);
|
||||||
delete inverted;
|
|
||||||
strcat (buf, e.c_str());
|
|
||||||
strcat (buf, " {\n");
|
strcat (buf, " {\n");
|
||||||
return (buf);
|
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
|
/* 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
|
* when the THEN clause of an if..then..else is empty. The clause is
|
||||||
* negated and the ELSE clause is used instead. */
|
* negated and the ELSE clause is used instead. */
|
||||||
char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc)
|
{ char *e;
|
||||||
{
|
|
||||||
memset (buf, ' ', sizeof(buf));
|
memset (buf, ' ', sizeof(buf));
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
strcat (buf, "if ");
|
strcat (buf, "if ");
|
||||||
std::string e = walkCondExpr (h.expr(), pProc, numLoc);
|
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||||
strcat (buf, e.c_str());
|
strcat (buf, e);
|
||||||
strcat (buf, " {\n");
|
strcat (buf, " {\n");
|
||||||
return (buf);
|
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.
|
/* 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
|
* 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
|
* done in a separate routine to be able to support the removal of
|
||||||
* empty THEN clauses on an if..then..else. */
|
* empty THEN clauses on an if..then..else. */
|
||||||
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
|
{ char *e;
|
||||||
{
|
|
||||||
string e;
|
memset (buf, ' ', sizeof(buf));
|
||||||
ostringstream ostr;
|
buf[0] = '\0';
|
||||||
HlTypeSupport *p = get();
|
switch (h.opcode) {
|
||||||
switch (opcode)
|
case HLI_ASSIGN: e = walkCondExpr (h.oper.asgn.lhs, pProc, numLoc);
|
||||||
{
|
strcat (buf, e);
|
||||||
case HLI_ASSIGN:
|
strcat (buf, " = ");
|
||||||
return p->writeOut(pProc,numLoc);
|
e = walkCondExpr (h.oper.asgn.rhs, pProc, numLoc);
|
||||||
case HLI_CALL:
|
strcat (buf, e);
|
||||||
return p->writeOut(pProc,numLoc);
|
strcat (buf, ";\n");
|
||||||
case HLI_RET:
|
break;
|
||||||
e = p->writeOut(pProc,numLoc);
|
case HLI_CALL: e = writeCall (h.oper.call.proc, h.oper.call.args, pProc,
|
||||||
if (! e.empty())
|
numLoc);
|
||||||
ostr << "return (" << e << ");\n";
|
strcat (buf, e);
|
||||||
break;
|
strcat (buf, ";\n");
|
||||||
case HLI_POP:
|
break;
|
||||||
ostr << "HLI_POP ";
|
case HLI_RET: e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||||
ostr << p->writeOut(pProc,numLoc);
|
if (e[0] != '\0')
|
||||||
ostr << "\n";
|
{
|
||||||
break;
|
strcat (buf, "return (");
|
||||||
case HLI_PUSH:
|
strcat (buf, e);
|
||||||
ostr << "HLI_PUSH ";
|
strcat (buf, ");\n");
|
||||||
ostr << p->writeOut(pProc,numLoc);
|
}
|
||||||
ostr << "\n";
|
break;
|
||||||
break;
|
case HLI_POP: strcat (buf, "HLI_POP ");
|
||||||
|
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||||
|
strcat (buf, e);
|
||||||
|
strcat (buf, "\n");
|
||||||
|
break;
|
||||||
|
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
|
Int power2 (Int i)
|
||||||
|
/* Returns the value of 2 to the power of i */
|
||||||
//TODO: replace all >= INDEX_BX_SI with machine_x86::isRegExpression
|
{
|
||||||
|
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
|
/* Writes the registers/stack variables that are used and defined by this
|
||||||
* instruction. */
|
* instruction. */
|
||||||
void ICODE::writeDU()
|
{ static char buf[100];
|
||||||
{
|
Int i, j;
|
||||||
int my_idx = loc_ip;
|
|
||||||
|
memset (buf, ' ', sizeof(buf));
|
||||||
|
buf[0] = '\0';
|
||||||
|
for (i = 0; i < (INDEXBASE-1); i++)
|
||||||
{
|
{
|
||||||
ostringstream ostr;
|
if ((pIcode->du.def & power2(i)) != 0)
|
||||||
Machine_X86::writeRegVector(ostr,du.def);
|
{
|
||||||
if (!ostr.str().empty())
|
strcat (buf, allRegs[i]);
|
||||||
printf ("Def (reg) = %s\n", ostr.str().c_str());
|
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++)
|
||||||
{
|
{
|
||||||
ostringstream ostr;
|
if ((pIcode->du.use & power2(i)) != 0)
|
||||||
Machine_X86::writeRegVector(ostr,du.use);
|
{
|
||||||
if (!ostr.str().empty())
|
strcat (buf, allRegs[i]);
|
||||||
printf ("Use (reg) = %s\n", ostr.str().c_str());
|
strcat (buf, " ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
printf ("Use (reg) = %s\n", buf);
|
||||||
|
|
||||||
/* Print du1 chain */
|
/* Print du1 chain */
|
||||||
printf ("# regs defined = %d\n", du1.numRegsDef);
|
printf ("# regs defined = %d\n", pIcode->du1.numRegsDef);
|
||||||
for (int i = 0; i < MAX_REGS_DEF; i++)
|
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][] = ", idx, i);
|
||||||
printf ("%d: du1[%d][] = ", my_idx, i);
|
for (j = 0; j < MAX_USES; j++)
|
||||||
for(auto j : du1.idx[i].uses)
|
|
||||||
{
|
{
|
||||||
printf ("%d ", j->loc_ip);
|
if (pIcode->du1.idx[i][j] == 0)
|
||||||
|
break;
|
||||||
|
printf ("%d ", pIcode->du1.idx[i][j]);
|
||||||
}
|
}
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For HLI_CALL, print # parameter bytes */
|
/* For HLI_CALL, print # parameter bytes */
|
||||||
if (hl()->opcode == HLI_CALL)
|
if (pIcode->ic.hl.opcode == HLI_CALL)
|
||||||
printf ("# param bytes = %d\n", hl()->call.args->cb);
|
printf ("# param bytes = %d\n", pIcode->ic.hl.oper.call.args->cb);
|
||||||
printf ("\n");
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
177
src/icode.cpp
177
src/icode.cpp
@ -5,98 +5,139 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
#include "dcc.h"
|
#include "types.h" // Common types like byte, etc
|
||||||
#include "types.h" // Common types like uint8_t, etc
|
|
||||||
#include "ast.h" // Some icode types depend on these
|
#include "ast.h" // Some icode types depend on these
|
||||||
#include "icode.h"
|
#include "icode.h"
|
||||||
|
|
||||||
|
void *reallocVar(void *p, Int newsize); /* frontend.c !? */
|
||||||
#define ICODE_DELTA 25 // Amount to allocate for new chunk
|
#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()
|
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.
|
/* 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
|
* If there is need to allocate extra memory, it is done so, and
|
||||||
* the alloc variable is adjusted. */
|
* the alloc variable is adjusted. */
|
||||||
ICODE * CIcodeRec::addIcode(ICODE *pIcode)
|
|
||||||
{
|
{
|
||||||
push_back(*pIcode);
|
PICODE resIcode;
|
||||||
back().loc_ip = size()-1;
|
|
||||||
return &back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB)
|
if (numIcode == alloc)
|
||||||
{
|
|
||||||
for(ICODE &ic : rang)
|
|
||||||
{
|
{
|
||||||
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
|
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
|
||||||
replaces *pIndex with an icode index */
|
replaces *pIndex with an icode index */
|
||||||
bool CIcodeRec::labelSrch(uint32_t target, uint32_t &pIndex)
|
|
||||||
{
|
{
|
||||||
iICODE location=labelSrch(target);
|
Int i;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int getNextLabel();
|
for (i = 0; i < numIcode; i++)
|
||||||
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 */
|
|
||||||
{
|
{
|
||||||
/* Generate new label */
|
if (icode[i].ic.ll.label == target)
|
||||||
hllLabNum = getNextLabel();
|
{
|
||||||
setFlags(HLL_LABEL);
|
*pIndex = i;
|
||||||
|
return TRUE;
|
||||||
/* Node has been traversed already, so backpatch this label into
|
}
|
||||||
* the code */
|
|
||||||
cCode.code.addLabelBundle (codeIdx, hllLabNum);
|
|
||||||
}
|
}
|
||||||
cCode.appendCode( "%sgoto L%ld;\n", indentStr(indLevel), hllLabNum);
|
return FALSE;
|
||||||
stats.numHLIcode++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PICODE CIcodeRec::GetIcode(int ip)
|
||||||
|
|
||||||
bool LLOperand::isReg() const
|
|
||||||
{
|
{
|
||||||
return (regi>=rAX) && (regi<=rTMP);
|
return &icode[ip];
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1463
src/idioms.cpp
1463
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
469
src/locident.cpp
469
src/locident.cpp
@ -5,324 +5,330 @@
|
|||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include "locident.h"
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
|
#include <string.h>
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define LOCAL_ID_DELTA 25
|
#define LOCAL_ID_DELTA 25
|
||||||
#define IDX_ARRAY_DELTA 5
|
#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.
|
/* Creates a new identifier node of type t and returns it.
|
||||||
* Arguments: locSym : local long symbol table
|
* Arguments: locSym : local long symbol table
|
||||||
* t : type of LONG identifier
|
* t : type of LONG identifier
|
||||||
* f : frame where this variable is located
|
* f : frame where this variable is located
|
||||||
* ix : index into icode array where this var is used */
|
* ix : index into icode array where this var is used */
|
||||||
void LOCAL_ID::newIdent(hlType t, frameType f)
|
|
||||||
{
|
{
|
||||||
ID newid(t,f);
|
if (locSym->csym == locSym->alloc)
|
||||||
id_arr.push_back(newid);
|
{
|
||||||
|
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
|
/* Creates a new register identifier node of TYPE_BYTE_(UN)SIGN or
|
||||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
* 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 */
|
/* Check for entry in the table */
|
||||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
|
for (idx = 0; idx < locSym->csym; idx++)
|
||||||
return ((el.type == t) && (el.id.regi == regi));
|
{
|
||||||
});
|
if ((locSym->id[idx].type == t) &&
|
||||||
if(found!=id_arr.end())
|
(locSym->id[idx].id.regi == regi))
|
||||||
return found-id_arr.begin();
|
return (idx);
|
||||||
|
}
|
||||||
|
|
||||||
/* Not in table, create new identifier */
|
/* Not in table, create new identifier */
|
||||||
newIdent (t, REG_FRAME);
|
newIdent (locSym, t, REG_FRAME);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.regi = regi;
|
locSym->id[idx].id.regi = regi;
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void flagByteWordId (LOCAL_ID *locsym, Int off)
|
||||||
/* Flags the entry associated with the offset off to illegal, as this
|
/* Flags the entry associated with the offset off to illegal, as this
|
||||||
* offset is part of a long stack variable.
|
* offset is part of a long stack variable.
|
||||||
* Note: it is easier enough to remove this entry by moving the rest of
|
* 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
|
* the array 1 position. The problem is that indexes into this
|
||||||
* array have already been saved in several positions; therefore,
|
* array have already been saved in several positions; therefore,
|
||||||
* flagging this entry as illegal is all that can be done. */
|
* flagging this entry as illegal is all that can be done. */
|
||||||
void LOCAL_ID::flagByteWordId (int off)
|
{ Int idx;
|
||||||
{
|
|
||||||
int idx;
|
for (idx = 0; idx < locsym->csym; 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())
|
|
||||||
{
|
{
|
||||||
printf("No entry to flag as invalid in LOCAL_ID::flagByteWordId \n");
|
if (((locsym->id[idx].type == TYPE_WORD_SIGN) ||
|
||||||
return;
|
(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
|
/* Creates a new stack identifier node of TYPE_BYTE_(UN)SIGN or
|
||||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
* 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 */
|
/* Check for entry in the table */
|
||||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
|
for (idx = 0; idx < locSym->csym; idx++)
|
||||||
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
|
{
|
||||||
return true;
|
if ((locSym->id[idx].id.bwId.off == off) &&
|
||||||
return false;
|
(locSym->id[idx].id.bwId.regOff == regOff))
|
||||||
});
|
return (idx);
|
||||||
if(found!=id_arr.end())
|
}
|
||||||
return found-id_arr.begin(); //return Index to found element
|
|
||||||
|
|
||||||
/* Not in table, create new identifier */
|
/* Not in table, create new identifier */
|
||||||
newIdent (t, STK_FRAME);
|
newIdent (locSym, t, STK_FRAME);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.bwId.regOff = regOff;
|
locSym->id[idx].id.bwId.regOff = regOff;
|
||||||
id_arr[idx].id.bwId.off = off;
|
locSym->id[idx].id.bwId.off = off;
|
||||||
return (idx);
|
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
|
/* 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
|
* entry; otherwise creates a new global identifier node of type
|
||||||
* TYPE_WORD_(UN)SIGN and returns the index to this new entry.
|
* TYPE_WORD_(UN)SIGN and returns the index to this new entry.
|
||||||
* Arguments: locSym : ptr to the local symbol table
|
* Arguments: locSym : ptr to the local symbol table
|
||||||
* seg: segment value for global variable
|
* seg: segment value for global variable
|
||||||
* off: offset from segment
|
* off: offset from segment
|
||||||
* regi: indexed register into global variable
|
* regi: indexed register into global variable
|
||||||
* ix: index into icode array
|
* ix: index into icode array
|
||||||
* t: HIGH_LEVEL type */
|
* 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 */
|
/* 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 */
|
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||||
(id_arr[idx].id.bwGlb.seg == seg) &&
|
(locSym->id[idx].id.bwGlb.seg == seg) &&
|
||||||
(id_arr[idx].id.bwGlb.off == off) &&
|
(locSym->id[idx].id.bwGlb.off == off) &&
|
||||||
(id_arr[idx].id.bwGlb.regi == regi))
|
(locSym->id[idx].id.bwGlb.regi == regi))
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not in the table, create new identifier */
|
/* Not in the table, create new identifier */
|
||||||
newIdent (t, GLB_FRAME);
|
newIdent (locSym, t, GLB_FRAME);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.bwGlb.seg = seg;
|
locSym->id[idx].id.bwGlb.seg = seg;
|
||||||
id_arr[idx].id.bwGlb.off = off;
|
locSym->id[idx].id.bwGlb.off = off;
|
||||||
id_arr[idx].id.bwGlb.regi = regi;
|
locSym->id[idx].id.bwGlb.regi = regi;
|
||||||
return (idx);
|
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
|
/* 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
|
* entry; otherwise creates a new register identifier node of type
|
||||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||||
int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
|
{ Int idx;
|
||||||
{
|
|
||||||
size_t idx;
|
|
||||||
//iICODE ix_;
|
|
||||||
/* Check for entry in the table */
|
/* 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 */
|
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||||
(entry.id.longId.h == regH) &&
|
(locSym->id[idx].id.longId.h == regH) &&
|
||||||
(entry.id.longId.l == regL))
|
(locSym->id[idx].id.longId.l == regL))
|
||||||
{
|
{
|
||||||
/* Check for occurrence in the list */
|
/* Check for occurrence in the list */
|
||||||
if (entry.idx.inList(ix_))
|
if (inList (&locSym->id[idx].idx, ix))
|
||||||
return (idx);
|
return (idx);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Insert icode index in list */
|
/* Insert icode index in list */
|
||||||
entry.idx.push_back(ix_);
|
insertIdx (&locSym->id[idx].idx, ix);
|
||||||
//entry.idx.insert(ix_);
|
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not in the table, create new identifier */
|
/* Not in the table, create new identifier */
|
||||||
newIdent (t, REG_FRAME);
|
newIdent (locSym, t, REG_FRAME);
|
||||||
id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_);
|
insertIdx (&locSym->id[locSym->csym-1].idx, ix);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.longId.h = regH;
|
locSym->id[idx].id.longId.h = regH;
|
||||||
id_arr[idx].id.longId.l = regL;
|
locSym->id[idx].id.longId.l = regL;
|
||||||
return (idx);
|
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
|
/* 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
|
* entry; otherwise creates a new global identifier node of type
|
||||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
* 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)
|
{ Int idx;
|
||||||
{
|
|
||||||
size_t idx;
|
|
||||||
|
|
||||||
/* Check for entry in the table */
|
/* 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 */
|
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
(locSym->id[idx].id.longGlb.seg == seg) &&
|
||||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
(locSym->id[idx].id.longGlb.offH == offH) &&
|
||||||
(id_arr[idx].id.longGlb.offL == offL))
|
(locSym->id[idx].id.longGlb.offL == offL))
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not in the table, create new identifier */
|
/* Not in the table, create new identifier */
|
||||||
newIdent (t, GLB_FRAME);
|
newIdent (locSym, t, GLB_FRAME);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.longGlb.seg = seg;
|
locSym->id[idx].id.longGlb.seg = seg;
|
||||||
id_arr[idx].id.longGlb.offH = offH;
|
locSym->id[idx].id.longGlb.offH = offH;
|
||||||
id_arr[idx].id.longGlb.offL = offL;
|
locSym->id[idx].id.longGlb.offL = offL;
|
||||||
return (idx);
|
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
|
/* 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
|
* entry; otherwise creates a new global identifier node of type
|
||||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
* 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)
|
{ Int idx;
|
||||||
{
|
|
||||||
size_t idx;
|
|
||||||
|
|
||||||
/* Check for entry in the table */
|
/* 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 */
|
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
(locSym->id[idx].id.longGlb.seg == seg) &&
|
||||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
(locSym->id[idx].id.longGlb.offH == offH) &&
|
||||||
(id_arr[idx].id.longGlb.offL == offL) &&
|
(locSym->id[idx].id.longGlb.offL == offL) &&
|
||||||
(id_arr[idx].id.longGlb.regi == regi))
|
(locSym->id[idx].id.longGlb.regi == regi))
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not in the table, create new identifier */
|
/* Not in the table, create new identifier */
|
||||||
newIdent (t, GLB_FRAME);
|
newIdent (locSym, t, GLB_FRAME);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.longGlb.seg = seg;
|
locSym->id[idx].id.longGlb.seg = seg;
|
||||||
id_arr[idx].id.longGlb.offH = offH;
|
locSym->id[idx].id.longGlb.offH = offH;
|
||||||
id_arr[idx].id.longGlb.offL = offL;
|
locSym->id[idx].id.longGlb.offL = offL;
|
||||||
id_arr[idx].id.longGlb.regi = regi;
|
locSym->id[idx].id.longGlb.regi = regi;
|
||||||
return (idx);
|
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.
|
/* Creates a new stack identifier node of type TYPE_LONG_(UN)SIGN.
|
||||||
* Returns the index to this entry. */
|
* Returns the index to this entry. */
|
||||||
int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
|
{ Int idx;
|
||||||
{
|
|
||||||
size_t idx;
|
|
||||||
|
|
||||||
/* Check for entry in the table */
|
/* 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) &&
|
if ((locSym->id[idx].type == t) &&
|
||||||
(id_arr[idx].id.longStkId.offH == offH) &&
|
(locSym->id[idx].id.longStkId.offH == offH) &&
|
||||||
(id_arr[idx].id.longStkId.offL == offL))
|
(locSym->id[idx].id.longStkId.offL == offL))
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not in the table; flag as invalid offH and offL */
|
/* Not in the table; flag as invalid offH and offL */
|
||||||
flagByteWordId (offH);
|
flagByteWordId (locSym, offH);
|
||||||
flagByteWordId (offL);
|
flagByteWordId (locSym, offL);
|
||||||
|
|
||||||
/* Create new identifier */
|
/* Create new identifier */
|
||||||
newIdent (t, STK_FRAME);
|
newIdent (locSym, t, STK_FRAME);
|
||||||
idx = id_arr.size() - 1;
|
idx = locSym->csym - 1;
|
||||||
id_arr[idx].id.longStkId.offH = offH;
|
locSym->id[idx].id.longStkId.offH = offH;
|
||||||
id_arr[idx].id.longStkId.offL = offL;
|
locSym->id[idx].id.longStkId.offL = offL;
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Returns the index to an appropriate long identifier.
|
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
|
* Note: long constants should be checked first and stored as a long integer
|
||||||
* number in an expression record. */
|
* number in an expression record. */
|
||||||
int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset)
|
{ Int idx;
|
||||||
{
|
PMEM pmH, pmL;
|
||||||
size_t idx;
|
|
||||||
const LLOperand *pmH, *pmL;
|
|
||||||
LLInst &p_ll(*pIcode->ll());
|
|
||||||
if (f == LOW_FIRST)
|
if (f == LOW_FIRST)
|
||||||
{
|
{
|
||||||
pmL = p_ll.get(sd);
|
pmL = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||||
pmH = atOffset.get(sd);
|
pmH = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
|
||||||
}
|
}
|
||||||
else /* HIGH_FIRST */
|
else /* HIGH_FIRST */
|
||||||
{
|
{
|
||||||
pmL = atOffset.get(sd);
|
pmH = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||||
pmH = p_ll.get(sd);
|
pmL = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pmL->regi == 0) /* global variable */
|
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)
|
if (f == HIGH_FIRST)
|
||||||
pIcode->setRegDU( pmL->regi, du); /* low part */
|
setRegDU (pIcode, pmL->regi, du); /* low part */
|
||||||
else
|
else
|
||||||
pIcode->setRegDU( pmH->regi, du); /* high part */
|
setRegDU (pIcode, pmH->regi, du); /* high part */
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (pmL->off) { /* offset */
|
else if (pmL->off) { /* offset */
|
||||||
if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */
|
if ((pmL->seg == rSS) && (pmL->regi == INDEXBASE + 6)) /* idx on bp */
|
||||||
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
|
idx = newLongStkId (locSym, TYPE_LONG_SIGN, pmH->off, pmL->off);
|
||||||
else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */
|
else if ((pmL->seg == rDS) && (pmL->regi == INDEXBASE + 7)) /* bx */
|
||||||
{ /* glb var indexed on bx */
|
{ /* glb var indexed on bx */
|
||||||
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
|
idx = newLongIdxId (locSym, pmH->segValue, pmH->off, pmL->off,
|
||||||
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
|
rBX, ix, TYPE_LONG_SIGN);
|
||||||
pIcode->setRegDU( rBX, eUSE);
|
setRegDU (pIcode, rBX, E_USE);
|
||||||
}
|
}
|
||||||
else /* idx <> bp, bx */
|
else /* idx <> bp, bx */
|
||||||
printf ("long not supported, idx <> bp\n");
|
printf ("long not supported, idx <> bp\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
||||||
printf ("long not supported, idx && no off\n");
|
printf ("long not supported, idx && no off\n");
|
||||||
|
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
/* Checks whether the long stack identifier is equivalent to the source or
|
||||||
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
|
* 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.
|
* icodes at present). If so, returns the rhs and lhs of this instruction.
|
||||||
@ -330,38 +336,36 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
|||||||
* pIcode : ptr to first LOW_LEVEL icode instruction
|
* pIcode : ptr to first LOW_LEVEL icode instruction
|
||||||
* i : idx into local identifier table for longId
|
* i : idx into local identifier table for longId
|
||||||
* idx : idx into icode array
|
* idx : idx into icode array
|
||||||
* pProc : ptr to current procedure record
|
* pProc : ptr to current procedure record
|
||||||
* rhs, lhs : return expressions if successful. */
|
* rhs, lhs : return expressions if successful. */
|
||||||
boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
|
{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */
|
||||||
{
|
|
||||||
/* pointers to LOW_LEVEL icodes */
|
|
||||||
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
|
|
||||||
|
|
||||||
pmHdst = &pIcode->ll()->dst;
|
pmHdst = &pIcode->ic.ll.dst;
|
||||||
pmLdst = &atOffset.dst;
|
pmLdst = &(pIcode+off)->ic.ll.dst;
|
||||||
pmHsrc = &pIcode->ll()->src();
|
pmHsrc = &pIcode->ic.ll.src;
|
||||||
pmLsrc = &atOffset.src();
|
pmLsrc = &(pIcode+off)->ic.ll.src;
|
||||||
|
|
||||||
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
||||||
{
|
{
|
||||||
asgn.lhs = COND_EXPR::idLongIdx (i);
|
*lhs = idCondExpLongIdx (i);
|
||||||
|
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
|
||||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
*rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
|
||||||
{
|
idx, E_USE, off);
|
||||||
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
return (TRUE);
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
||||||
{
|
{
|
||||||
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
*lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
|
||||||
asgn.rhs = COND_EXPR::idLongIdx (i);
|
E_DEF, off);
|
||||||
return true;
|
*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
|
/* Checks whether the long stack identifier is equivalent to the source or
|
||||||
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
|
* 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.
|
* icodes at present). If so, returns the rhs and lhs of this instruction.
|
||||||
@ -369,47 +373,42 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro
|
|||||||
* pIcode : ptr to first LOW_LEVEL icode instruction
|
* pIcode : ptr to first LOW_LEVEL icode instruction
|
||||||
* i : idx into local identifier table for longId
|
* i : idx into local identifier table for longId
|
||||||
* idx : idx into icode array
|
* idx : idx into icode array
|
||||||
* pProc : ptr to current procedure record
|
* pProc : ptr to current procedure record
|
||||||
* rhs, lhs : return expressions if successful. */
|
* rhs, lhs : return expressions if successful. */
|
||||||
boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
|
{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */
|
||||||
Function * pProc, Assignment &asgn, LLInst &atOffset)
|
|
||||||
{
|
|
||||||
/* pointers to LOW_LEVEL icodes */
|
|
||||||
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
|
|
||||||
|
|
||||||
pmHdst = &pIcode->ll()->dst;
|
pmHdst = &pIcode->ic.ll.dst;
|
||||||
pmLdst = &atOffset.dst;
|
pmLdst = &(pIcode+off)->ic.ll.dst;
|
||||||
pmHsrc = &pIcode->ll()->src();
|
pmHsrc = &pIcode->ic.ll.src;
|
||||||
pmLsrc = &atOffset.src();
|
pmLsrc = &(pIcode+off)->ic.ll.src;
|
||||||
|
|
||||||
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
|
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
|
||||||
{
|
{
|
||||||
asgn.lhs = COND_EXPR::idLongIdx (i);
|
*lhs = idCondExpLongIdx (i);
|
||||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
|
||||||
{
|
*rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
|
||||||
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
idx, E_USE, off);
|
||||||
}
|
return (TRUE);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
|
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
|
||||||
{
|
{
|
||||||
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
|
*lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
|
||||||
asgn.rhs = COND_EXPR::idLongIdx (i);
|
E_DEF, off);
|
||||||
return true;
|
*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
|
/* Given an index into the local identifier table for a long register
|
||||||
* variable, determines whether regi is the high or low part, and returns
|
* variable, determines whether regi is the high or low part, and returns
|
||||||
* the other part */
|
* 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) ||
|
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
|
||||||
(id->type == TYPE_LONG_UNSIGN)))
|
(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)
|
else if (id->id.longId.l == regi)
|
||||||
return (id->id.longId.h);
|
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
|
/* Checks if the registers regL and regH have been used independently in
|
||||||
* the local identifier table. If so, macros for these registers are
|
* the local identifier table. If so, macros for these registers are
|
||||||
* placed in the local identifier table, as these registers belong to a
|
* placed in the local identifier table, as these registers belong to a
|
||||||
* long register identifier. */
|
* long register identifier. */
|
||||||
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
|
{ Int i;
|
||||||
{
|
ID *id;
|
||||||
for (ID &rid : id_arr)
|
|
||||||
{
|
for (i = 0; i < locid->csym; i++)
|
||||||
if (rid.typeBitsize()!=16)
|
{
|
||||||
continue;
|
id = &locid->id[i];
|
||||||
if ( (rid.id.regi != regL) and (rid.id.regi != regH) )
|
if ((id->type == TYPE_WORD_SIGN) || (id->type == TYPE_WORD_UNSIGN))
|
||||||
continue;
|
{
|
||||||
// otherwise at least 1 is ok
|
if (id->id.regi == regL)
|
||||||
rid.name = name;
|
{
|
||||||
rid.hasMacro = true;
|
strcpy (id->name, name);
|
||||||
rid.illegal = true;
|
strcpy (id->macro, "LO");
|
||||||
if (rid.id.regi == regL)
|
id->hasMacro = TRUE;
|
||||||
{
|
id->illegal = TRUE;
|
||||||
strcpy (rid.macro, "LO");
|
}
|
||||||
}
|
else if (id->id.regi == regH)
|
||||||
else // if (rid.id.regi == regH)
|
{
|
||||||
{
|
strcpy (id->name, name);
|
||||||
strcpy (rid.macro, "HI");
|
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)));
|
|
||||||
}
|
|
||||||
1483
src/parser.cpp
1483
src/parser.cpp
File diff suppressed because it is too large
Load Diff
397
src/perfhlib.cpp
397
src/perfhlib.cpp
@ -11,21 +11,32 @@
|
|||||||
|
|
||||||
/* Private data structures */
|
/* 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 short *g; /* g[] */
|
||||||
|
|
||||||
static int numEdges; /* An edge counter */
|
static int numEdges; /* An edge counter */
|
||||||
//static bool *visited; /* Array of bools: whether visited */
|
static bool *visited; /* Array of bools: whether visited */
|
||||||
|
|
||||||
/* Private prototypes */
|
/* Private prototypes */
|
||||||
static void initGraph(void);
|
static void initGraph(void);
|
||||||
static void addToGraph(int e, int v1, int v2);
|
static void addToGraph(int e, int v1, int v2);
|
||||||
static bool isCycle(void);
|
static bool isCycle(void);
|
||||||
static void duplicateKeys(int v1, int v2);
|
static void duplicateKeys(int v1, int v2);
|
||||||
PatternHasher g_pattern_hasher;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||||
int _NumVert)
|
int _NumVert)
|
||||||
{
|
{
|
||||||
/* These parameters are stored in statics so as to obviate the need for
|
/* 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;
|
NumVert = _NumVert;
|
||||||
|
|
||||||
/* Allocate the variable sized tables etc */
|
/* Allocate the variable sized tables etc */
|
||||||
T1base = new uint16_t [EntryLen * SetSize];
|
if ((T1base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
|
||||||
T2base = new uint16_t [EntryLen * SetSize];
|
{
|
||||||
graphNode = new int [NumEntry*2 + 1];
|
goto BadAlloc;
|
||||||
graphNext = new int [NumEntry*2 + 1];
|
}
|
||||||
graphFirst = new int [NumVert + 1];
|
if ((T2base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
|
||||||
g = new short [NumVert + 1];
|
{
|
||||||
// visited = new bool [NumVert + 1];
|
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;
|
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 */
|
/* Free the storage for variable sized tables etc */
|
||||||
delete [] T1base;
|
if (T1base) free(T1base);
|
||||||
delete [] T2base;
|
if (T2base) free(T2base);
|
||||||
delete [] graphNode;
|
if (graphNode) free(graphNode);
|
||||||
delete [] graphNext;
|
if (graphNext) free(graphNext);
|
||||||
delete [] graphFirst;
|
if (graphFirst) free(graphFirst);
|
||||||
delete [] g;
|
if (g) free(g);
|
||||||
// delete [] visited;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
int j;
|
||||||
|
|
||||||
u = 0;
|
u = 0;
|
||||||
@ -86,18 +381,68 @@ int PatternHasher::hash(uint8_t *string)
|
|||||||
return (g[u] + g[v]) % NumEntry;
|
return (g[u] + g[v]) % NumEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t * PatternHasher::readT1(void)
|
word *
|
||||||
|
readT1(void)
|
||||||
{
|
{
|
||||||
return T1base;
|
return T1base;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t *PatternHasher::readT2(void)
|
word *
|
||||||
|
readT2(void)
|
||||||
{
|
{
|
||||||
return T2base;
|
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
|
||||||
|
|||||||
619
src/procs.cpp
619
src/procs.cpp
@ -5,382 +5,409 @@
|
|||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <cassert>
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include "project.h"
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
extern Project g_proj;
|
|
||||||
/* Static indentation buffer */
|
/* 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] =
|
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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Inserts an outEdge at the current callGraph pointer if the newProc does
|
static void insertArc (PCALL_GRAPH pcallGraph, PPROC newProc)
|
||||||
|
/* Inserts an outEdge at the current callGraph pointer if the newProc does
|
||||||
* not exist. */
|
* not exist. */
|
||||||
void CALL_GRAPH::insertArc (ilFunction newProc)
|
{ CALL_GRAPH *pcg;
|
||||||
{
|
Int i;
|
||||||
CALL_GRAPH *pcg;
|
|
||||||
|
|
||||||
|
|
||||||
/* Check if procedure already exists */
|
/* Check if procedure already exists */
|
||||||
auto res=std::find_if(outEdges.begin(),outEdges.end(),[newProc](CALL_GRAPH *e) {return e->proc==newProc;});
|
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||||
if(res!=outEdges.end())
|
if (pcallGraph->outEdges[i]->proc == newProc)
|
||||||
return;
|
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 */
|
/* Include new arc */
|
||||||
pcg = new CALL_GRAPH;
|
pcg = allocStruc(CALL_GRAPH);
|
||||||
|
memset (pcg, 0, sizeof(CALL_GRAPH));
|
||||||
pcg->proc = newProc;
|
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. */
|
/* 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);
|
insertArc (pcallGraph, callee);
|
||||||
return true;
|
return (TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; i < outEdges.size(); i++)
|
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||||
if (outEdges[i]->insertCallGraph (caller, callee))
|
if (insertCallGraph (pcallGraph->outEdges[i], caller, callee))
|
||||||
return true;
|
return (TRUE);
|
||||||
return (false);
|
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
|
/* Displays the current node of the call graph, and invokes recursively on
|
||||||
* the nodes the procedure invokes. */
|
* 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());
|
printf ("%s%s\n", indent(indIdx), pcallGraph->proc->name);
|
||||||
for (i = 0; i < outEdges.size(); i++)
|
for (i = 0; i < pcallGraph->numOutEdges; i++)
|
||||||
outEdges[i]->writeNodeCallGraph (indIdx + 1);
|
writeNodeCallGraph (pcallGraph->outEdges[i], indIdx + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void writeCallGraph (PCALL_GRAPH pcallGraph)
|
||||||
/* Writes the header and invokes recursive procedure */
|
/* Writes the header and invokes recursive procedure */
|
||||||
void CALL_GRAPH::write()
|
{
|
||||||
{
|
|
||||||
printf ("\nCall Graph:\n");
|
printf ("\nCall Graph:\n");
|
||||||
writeNodeCallGraph (0);
|
writeNodeCallGraph (pcallGraph, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Routines to support arguments
|
* Routines to support arguments
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
|
void newRegArg (PPROC pproc, PICODE picode, PICODE ticode)
|
||||||
/* Updates the argument table by including the register(s) (ie. lhs of
|
/* Updates the argument table by including the register(s) (ie. lhs of
|
||||||
* picode) and the actual expression (ie. rhs of picode).
|
* picode) and the actual expression (ie. rhs of picode).
|
||||||
* Note: register(s) are only included once in the table. */
|
* Note: register(s) are only included once in the table. */
|
||||||
void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
|
{ COND_EXPR *lhs;
|
||||||
{
|
PSTKFRAME ps, ts;
|
||||||
COND_EXPR *lhs;
|
ID *id;
|
||||||
STKFRAME * call_args_stackframe, *target_stackframe;
|
Int i, tidx;
|
||||||
const ID *id;
|
boolT regExist;
|
||||||
int tidx;
|
condId type;
|
||||||
boolT regExist;
|
PPROC tproc;
|
||||||
condId type;
|
byte regL, regH; /* Registers involved in arguments */
|
||||||
Function * tproc;
|
|
||||||
eReg regL, regH; /* Registers involved in arguments */
|
|
||||||
|
|
||||||
/* Flag ticode as having register arguments */
|
/* Flag ticode as having register arguments */
|
||||||
tproc = ticode->hl()->call.proc;
|
tproc = ticode->ic.hl.oper.call.proc;
|
||||||
tproc->flg |= REG_ARGS;
|
tproc->flg |= REG_ARGS;
|
||||||
|
|
||||||
/* Get registers and index into target procedure's local list */
|
/* Get registers and index into target procedure's local list */
|
||||||
call_args_stackframe = ticode->hl()->call.args;
|
ps = ticode->ic.hl.oper.call.args;
|
||||||
target_stackframe = &tproc->args;
|
ts = &tproc->args;
|
||||||
lhs = picode->hl()->asgn.lhs;
|
lhs = picode->ic.hl.oper.asgn.lhs;
|
||||||
type = lhs->expr.ident.idType;
|
type = lhs->expr.ident.idType;
|
||||||
if (type == REGISTER)
|
if (type == REGISTER)
|
||||||
|
{
|
||||||
|
regL = pproc->localId.id[lhs->expr.ident.idNode.regiIdx].id.regi;
|
||||||
|
if (regL < rAL)
|
||||||
|
tidx = newByteWordRegId (&tproc->localId, TYPE_WORD_SIGN, regL);
|
||||||
|
else
|
||||||
|
tidx = newByteWordRegId (&tproc->localId, TYPE_BYTE_SIGN, regL);
|
||||||
|
}
|
||||||
|
else if (type == LONG_VAR)
|
||||||
|
{
|
||||||
|
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 (i = 0; i < ts->csym; i++)
|
||||||
|
{
|
||||||
|
if (type == REGISTER)
|
||||||
|
{
|
||||||
|
if ((ts->sym[i].regs != NULL) &&
|
||||||
|
(ts->sym[i].regs->expr.ident.idNode.regiIdx == tidx))
|
||||||
|
{
|
||||||
|
regExist = TRUE;
|
||||||
|
i = ts->csym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == LONG_VAR)
|
||||||
|
{
|
||||||
|
if ((ts->sym[i].regs != NULL) &&
|
||||||
|
(ts->sym[i].regs->expr.ident.idNode.longIdx == tidx))
|
||||||
|
{
|
||||||
|
regExist = TRUE;
|
||||||
|
i = ts->csym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do ts (formal arguments) */
|
||||||
|
if (regExist == FALSE)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ts->sym[ts->csym].type = TYPE_WORD_SIGN;
|
||||||
|
ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, WORD_REG);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ts->sym[ts->csym].type = TYPE_BYTE_SIGN;
|
||||||
|
ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, BYTE_REG);
|
||||||
|
}
|
||||||
|
sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym);
|
||||||
|
}
|
||||||
|
else if (type == LONG_VAR)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->csym++;
|
||||||
|
ts->numArgs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do ps (actual arguments) */
|
||||||
|
if (ps->csym == ps->alloc)
|
||||||
{
|
{
|
||||||
regL = id_arr[lhs->expr.ident.idNode.regiIdx].id.regi;
|
ps->alloc += 5;
|
||||||
if (regL < rAL)
|
ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
|
||||||
tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL);
|
memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM));
|
||||||
else
|
|
||||||
tidx = tproc->localId.newByteWordReg(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*/);
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
/* Check if register argument already on the formal argument list */
|
/* Mask off high and low register(s) in picode */
|
||||||
regExist = false;
|
switch (type) {
|
||||||
for(STKSYM &tgt_sym : *target_stackframe)
|
case REGISTER:
|
||||||
{
|
id = &pproc->localId.id[lhs->expr.ident.idNode.regiIdx];
|
||||||
if( tgt_sym.regs == NULL ) // both REGISTER and LONG_VAR require this precondition
|
picode->du.def &= maskDuReg[id->id.regi];
|
||||||
continue;
|
if (id->id.regi < rAL)
|
||||||
if (type == REGISTER)
|
ps->sym[ps->csym].type = TYPE_WORD_SIGN;
|
||||||
{
|
else
|
||||||
if ( tgt_sym.regs->expr.ident.idNode.regiIdx == tidx )
|
ps->sym[ps->csym].type = TYPE_BYTE_SIGN;
|
||||||
{
|
break;
|
||||||
regExist = true;
|
case LONG_VAR:
|
||||||
}
|
id = &pproc->localId.id[lhs->expr.ident.idNode.longIdx];
|
||||||
}
|
picode->du.def &= maskDuReg[id->id.longId.h];
|
||||||
else if (type == LONG_VAR)
|
picode->du.def &= maskDuReg[id->id.longId.l];
|
||||||
{
|
ps->sym[ps->csym].type = TYPE_LONG_SIGN;
|
||||||
if ( tgt_sym.regs->expr.ident.idNode.longIdx == tidx )
|
break;
|
||||||
{
|
}
|
||||||
regExist = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(regExist == true)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do ts (formal arguments) */
|
ps->csym++;
|
||||||
if (regExist == false)
|
ps->numArgs++;
|
||||||
{
|
|
||||||
STKSYM newsym;
|
|
||||||
|
|
||||||
newsym.setArgName(target_stackframe->size());
|
|
||||||
|
|
||||||
if (type == REGISTER)
|
|
||||||
{
|
|
||||||
if (regL < rAL)
|
|
||||||
{
|
|
||||||
newsym.type = TYPE_WORD_SIGN;
|
|
||||||
newsym.regs = COND_EXPR::idRegIdx(tidx, WORD_REG);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newsym.type = TYPE_BYTE_SIGN;
|
|
||||||
newsym.regs = COND_EXPR::idRegIdx(tidx, BYTE_REG);
|
|
||||||
}
|
|
||||||
tproc->localId.id_arr[tidx].name = newsym.name;
|
|
||||||
}
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
target_stackframe->push_back(newsym);
|
|
||||||
target_stackframe->numArgs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do ps (actual arguments) */
|
|
||||||
STKSYM newsym;
|
|
||||||
newsym.setArgName(call_args_stackframe->size());
|
|
||||||
newsym.actual = picode->hl()->asgn.rhs;
|
|
||||||
newsym.regs = lhs;
|
|
||||||
/* Mask off high and low register(s) in picode */
|
|
||||||
switch (type) {
|
|
||||||
case REGISTER:
|
|
||||||
id = &id_arr[lhs->expr.ident.idNode.regiIdx];
|
|
||||||
picode->du.def &= maskDuReg[id->id.regi];
|
|
||||||
if (id->id.regi < rAL)
|
|
||||||
newsym.type = TYPE_WORD_SIGN;
|
|
||||||
else
|
|
||||||
newsym.type = TYPE_BYTE_SIGN;
|
|
||||||
break;
|
|
||||||
case LONG_VAR:
|
|
||||||
id = &id_arr[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;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
call_args_stackframe->push_back(newsym);
|
|
||||||
call_args_stackframe->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.
|
* list.
|
||||||
* @return true if it was a near call that made use of a segment register.
|
* Returns: TRUE if it was a near call that made use of a segment register.
|
||||||
* false elsewhere
|
* FALSE elsewhere */
|
||||||
*/
|
{ PSTKFRAME ps;
|
||||||
bool CallType::newStkArg(COND_EXPR *exp, llIcode opcode, Function * pproc)
|
byte regi;
|
||||||
{
|
|
||||||
uint8_t 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))
|
|
||||||
{
|
|
||||||
regi = pproc->localId.id_arr[exp->expr.ident.idNode.regiIdx].id.regi;
|
|
||||||
if ((regi >= rES) && (regi <= rDS))
|
|
||||||
if (opcode == iCALLF)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Place register argument on the argument list */
|
/* Check for far procedure call, in which case, references to segment
|
||||||
STKSYM newsym;
|
* registers are not be considered another parameter (i.e. they are
|
||||||
newsym.actual = exp;
|
* long references to another segment) */
|
||||||
args->push_back(newsym);
|
if (exp)
|
||||||
args->numArgs++;
|
{
|
||||||
return false;
|
if ((exp->type == IDENTIFIER) && (exp->expr.ident.idType == REGISTER))
|
||||||
|
{
|
||||||
|
regi = pproc->localId.id[exp->expr.ident.idNode.regiIdx].id.regi;
|
||||||
|
if ((regi >= rES) && (regi <= rDS))
|
||||||
|
if (opcode == iCALLF)
|
||||||
|
return (FALSE);
|
||||||
|
else
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Place register argument on the argument list */
|
||||||
|
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
|
/* Places the actual argument exp in the position given by pos in the
|
||||||
* argument list of picode. */
|
* argument list of picode. */
|
||||||
void CallType::placeStkArg (COND_EXPR *exp, int pos)
|
{ PSTKFRAME ps;
|
||||||
{
|
|
||||||
(*args)[pos].actual = exp;
|
|
||||||
(*args)[pos].setArgName(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
COND_EXPR *CallType::toId()
|
ps = picode->ic.hl.oper.call.args;
|
||||||
{
|
ps->sym[pos].actual = exp;
|
||||||
return COND_EXPR::idFunc( proc, args);
|
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
|
/* Checks to determine whether the expression (actual argument) has the
|
||||||
* same type as the given type (from the procedure's formal list). If not,
|
* same type as the given type (from the procedure's formal list). If not,
|
||||||
* the actual argument gets modified */
|
* the actual argument gets modified */
|
||||||
void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
|
{ hlType actType;
|
||||||
{
|
Int offset, offL;
|
||||||
PROG &prog(Project::get()->prog);
|
|
||||||
hlType actType;
|
|
||||||
int offset, offL;
|
|
||||||
|
|
||||||
if (exp == NULL)
|
if (exp == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
actType = exp-> expType (pproc);
|
actType = expType (exp, pproc);
|
||||||
if (((actType == forType) || (exp->m_type != IDENTIFIER)))
|
if ((actType != forType) && (exp->type == IDENTIFIER))
|
||||||
return;
|
{
|
||||||
switch (forType)
|
switch (forType) {
|
||||||
{
|
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
|
||||||
case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
|
case TYPE_LONG_UNSIGN: case TYPE_RECORD:
|
||||||
case TYPE_LONG_UNSIGN: case TYPE_RECORD:
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_PTR:
|
case TYPE_PTR:
|
||||||
case TYPE_CONST:
|
case TYPE_CONST:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_STR:
|
case TYPE_STR:
|
||||||
switch (actType) {
|
switch (actType) {
|
||||||
case TYPE_CONST:
|
case TYPE_CONST:
|
||||||
/* It's an offset into image where a string is
|
/* It's an offset into image where a string is
|
||||||
* found. Point to the string. */
|
* found. Point to the string. */
|
||||||
offL = exp->expr.ident.idNode.kte.kte;
|
offL = exp->expr.ident.idNode.kte.kte;
|
||||||
if (prog.fCOM)
|
if (prog.fCOM)
|
||||||
offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
|
offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
|
||||||
else
|
else
|
||||||
offset = (pproc->state.r[rDS]<<4) + offL;
|
offset = (pproc->state.r[rDS]<<4) + offL;
|
||||||
exp->expr.ident.idNode.strIdx = offset;
|
exp->expr.ident.idNode.strIdx = offset;
|
||||||
exp->expr.ident.idType = STRING;
|
exp->expr.ident.idType = STRING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_PTR:
|
case TYPE_PTR:
|
||||||
/* It's a pointer to a char rather than a pointer to
|
/* It's a pointer to a char rather than a pointer to
|
||||||
* an integer */
|
* an integer */
|
||||||
/***HERE - modify the type ****/
|
/***HERE - modify the type ****/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_WORD_SIGN:
|
case TYPE_WORD_SIGN:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} /* eos */
|
} /* eos */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void adjustForArgType (PSTKFRAME pstkFrame, Int numArg, hlType actType)
|
||||||
/* Determines whether the formal argument has the same type as the given
|
/* Determines whether the formal argument has the same type as the given
|
||||||
* type (type of the actual argument). If not, the formal argument is
|
* type (type of the actual argument). If not, the formal argument is
|
||||||
* changed its type */
|
* changed its type */
|
||||||
void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
|
{ hlType forType;
|
||||||
{
|
PSTKSYM psym, nsym;
|
||||||
hlType forType;
|
Int off, i;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Find stack offset for this argument */
|
/* Find stack offset for this argument */
|
||||||
off = m_minOff;
|
off = pstkFrame->minOff;
|
||||||
i=0;
|
for (i = 0; i < numArg; i++)
|
||||||
for(STKSYM &s : *this) // walk formal arguments upto numArg_
|
off += pstkFrame->sym[i].size;
|
||||||
{
|
|
||||||
if(i>=numArg_)
|
|
||||||
break;
|
|
||||||
off+=s.size;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find formal argument */
|
/* Find formal argument */
|
||||||
//psym = &at(numArg_);
|
if (numArg < pstkFrame->csym)
|
||||||
//i = numArg_;
|
{
|
||||||
//auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;});
|
psym = &pstkFrame->sym[numArg];
|
||||||
auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {s.label==off;});
|
i = numArg;
|
||||||
if(iter==end()) // symbol not found
|
while ((i < pstkFrame->csym) && (psym->off != off))
|
||||||
return;
|
{
|
||||||
psym = &(*iter);
|
psym++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (numArg == pstkFrame->csym)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* If formal argument does not exist, do not create new ones, just
|
||||||
|
* ignore actual argument */
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
forType = psym->type;
|
forType = psym->type;
|
||||||
if (forType != actType_)
|
if (forType != actType)
|
||||||
{
|
{
|
||||||
switch (actType_) {
|
switch (actType) {
|
||||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||||
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
|
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
|
case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
|
||||||
if ((forType == TYPE_WORD_UNSIGN) ||
|
if ((forType == TYPE_WORD_UNSIGN) ||
|
||||||
(forType == TYPE_WORD_SIGN) ||
|
(forType == TYPE_WORD_SIGN) ||
|
||||||
(forType == TYPE_UNKNOWN))
|
(forType == TYPE_UNKNOWN))
|
||||||
{
|
{
|
||||||
/* Merge low and high */
|
/* Merge low and high */
|
||||||
psym->type = actType_;
|
psym->type = actType;
|
||||||
psym->size = 4;
|
psym->size = 4;
|
||||||
nsym = psym + 1;
|
nsym = psym + 1;
|
||||||
nsym->macro = "HI";
|
sprintf (nsym->macro, "HI");
|
||||||
psym->macro = "LO";
|
sprintf (psym->macro, "LO");
|
||||||
nsym->hasMacro = true;
|
nsym->hasMacro = TRUE;
|
||||||
psym->hasMacro = true;
|
psym->hasMacro = TRUE;
|
||||||
nsym->name = psym->name;
|
sprintf (nsym->name, "%s", psym->name);
|
||||||
nsym->invalid = true;
|
nsym->invalid = TRUE;
|
||||||
numArgs--;
|
pstkFrame->numArgs--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_PTR:
|
case TYPE_PTR:
|
||||||
case TYPE_CONST:
|
case TYPE_CONST:
|
||||||
case TYPE_STR:
|
case TYPE_STR:
|
||||||
break;
|
break;
|
||||||
} /* eos */
|
} /* eos */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
911
src/proplong.cpp
911
src/proplong.cpp
File diff suppressed because it is too large
Load Diff
@ -3,388 +3,418 @@
|
|||||||
* constructs an equivalent reducible graph if one is not found.
|
* constructs an equivalent reducible graph if one is not found.
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef __BORLAND__
|
||||||
|
#include <alloc.h>
|
||||||
|
#else
|
||||||
#include <malloc.h> /* For free() */
|
#include <malloc.h> /* For free() */
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static int numInt; /* Number of intervals */
|
static Int numInt; /* Number of intervals */
|
||||||
|
|
||||||
|
|
||||||
#define nonEmpty(q) (q != NULL)
|
#define nonEmpty(q) (q != NULL)
|
||||||
/* Returns whether the queue q is empty or not */
|
/* Returns whether the queue q is empty or not */
|
||||||
bool trivialGraph(BB *G)
|
|
||||||
{
|
#define trivialGraph(G) (G->numOutEdges == 0)
|
||||||
return G->edges.empty();
|
|
||||||
}
|
|
||||||
/* Returns whether the graph is a trivial graph or not */
|
/* 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
|
/* Returns the first element in the queue Q, and removes this element
|
||||||
* from the list. Q is not an empty queue. */
|
* from the list. Q is not an empty queue. */
|
||||||
static BB *firstOfQueue (queue &Q)
|
{ queue *elim;
|
||||||
{
|
BB *first;
|
||||||
assert(!Q.empty());
|
|
||||||
BB *res=Q.front();
|
elim = *Q; /* Pointer to first node */
|
||||||
Q.pop_front();
|
first = (*Q)->node; /* First element */
|
||||||
return res;
|
*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
|
/* 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. */
|
* in this queue. Returns the queue node just appended. */
|
||||||
queue::iterator appendQueue (queue &Q, BB *node)
|
{ queue *pq, *l;
|
||||||
{
|
|
||||||
auto iter=std::find(Q.begin(),Q.end(),node);
|
pq = allocStruc(queue);
|
||||||
if(iter!=Q.end())
|
pq->node = node;
|
||||||
return iter;
|
pq->next = NULL;
|
||||||
Q.push_back(node);
|
|
||||||
iter=Q.end();
|
if (Q)
|
||||||
--iter;
|
if (*Q)
|
||||||
return iter;
|
{
|
||||||
|
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
|
/* Returns the next unprocessed node of the interval list (pointed to by
|
||||||
* pI->currNode). Removes this element logically from the list, by updating
|
* pI->currNode). Removes this element logically from the list, by updating
|
||||||
* the currNode pointer to the next unprocessed element. */
|
* the currNode pointer to the next unprocessed element. */
|
||||||
BB *interval::firstOfInt ()
|
{ queue *pq;
|
||||||
{
|
|
||||||
auto pq = currNode;
|
pq = pI->currNode;
|
||||||
if (pq == nodes.end())
|
if (pq == NULL)
|
||||||
return 0;
|
return (NULL);
|
||||||
++currNode;
|
pI->currNode = pq->next;
|
||||||
return *pq;
|
return (pq->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Appends node @node to the end of the interval list @pI, updates currNode
|
static queue *appendNodeInt (queue *pqH, BB *node, interval *pI)
|
||||||
* if necessary, and removes the node from the header list @pqH if it is
|
/* Appends node node to the end of the interval list I, updates currNode
|
||||||
* there. The interval header information is placed in the field
|
* 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.
|
* node->inInterval.
|
||||||
* Note: nodes are added to the interval list in interval order (which
|
* Note: nodes are added to the interval list in interval order (which
|
||||||
* topsorts the dominance relation). */
|
* topsorts the dominance relation). */
|
||||||
static void appendNodeInt (queue &pqH, BB *node, interval *pI)
|
{ queue *pq, /* Pointer to current node of the list */
|
||||||
{
|
*prev; /* Pointer to previous node in the list */
|
||||||
queue::iterator pq; /* Pointer to current node of the list */
|
|
||||||
|
|
||||||
/* Append node if it is not already in the interval 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 */
|
/* Update currNode if necessary */
|
||||||
if (pI->currNode == pI->nodes.end())
|
if (pI->currNode == NULL)
|
||||||
pI->currNode = pq;
|
pI->currNode = pq;
|
||||||
|
|
||||||
/* Check header list for occurrence of node, if found, remove it
|
/* Check header list for occurrence of node, if found, remove it
|
||||||
* and decrement number of out-edges from this interval. */
|
* 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);
|
prev = pqH;
|
||||||
if(found_iter!=pqH.end())
|
for (pq = prev; pq && pq->node != node; pq = pq->next)
|
||||||
{
|
prev = pq;
|
||||||
pI->numOutEdges -= (uint8_t)(*found_iter)->inEdges.size() - 1;
|
if (pq == prev)
|
||||||
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 */
|
/* Update interval header information for this basic block */
|
||||||
node->inInterval = pI;
|
node->inInterval = pI;
|
||||||
|
|
||||||
|
return (pqH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Finds the intervals of graph derivedGi->Gi and places them in the list
|
static void findIntervals (derSeq *derivedGi)
|
||||||
|
/* Finds the intervals of graph derivedGi->Gi and places them in the list
|
||||||
* of intervals derivedGi->Ii.
|
* of intervals derivedGi->Ii.
|
||||||
* Algorithm by M.S.Hecht. */
|
* Algorithm by M.S.Hecht. */
|
||||||
void derSeq_Entry::findIntervals (Function *c)
|
{ interval *pI, /* Interval being processed */
|
||||||
{
|
*J; /* ^ last interval in derivedGi->Ii */
|
||||||
interval *pI, /* Interval being processed */
|
BB *h, /* Node being processed */
|
||||||
*J; /* ^ last interval in derivedGi->Ii */
|
*header, /* Current interval's header node */
|
||||||
BB *h, /* Node being processed */
|
*succ; /* Successor basic block */
|
||||||
*header, /* Current interval's header node */
|
Int i; /* Counter */
|
||||||
*succ; /* Successor basic block */
|
queue *H; /* Queue of possible header nodes */
|
||||||
int i; /* Counter */
|
boolT first = TRUE; /* First pass through the loop */
|
||||||
queue H; /* Queue of possible header nodes */
|
|
||||||
boolT first = true; /* First pass through the loop */
|
|
||||||
|
|
||||||
appendQueue (H, Gi); /* H = {first node of G} */
|
H = appendQueue (NULL, derivedGi->Gi); /* H = {first node of G} */
|
||||||
Gi->beenOnH = true;
|
derivedGi->Gi->beenOnH = TRUE;
|
||||||
Gi->reachingInt = BB::Create(0,"",c); /* ^ empty BB */
|
derivedGi->Gi->reachingInt = allocStruc(BB); /* ^ empty BB */
|
||||||
|
memset (derivedGi->Gi->reachingInt, 0, sizeof(BB));
|
||||||
|
|
||||||
/* Process header nodes list H */
|
/* Process header nodes list H */
|
||||||
while (!H.empty())
|
while (nonEmpty (H))
|
||||||
{
|
{
|
||||||
header = firstOfQueue (H);
|
header = firstOfQueue (&H);
|
||||||
pI = new interval;
|
pI = allocStruc(interval);
|
||||||
pI->numInt = (uint8_t)numInt++;
|
memset (pI, 0, sizeof(interval));
|
||||||
if (first) /* ^ to first interval */
|
pI->numInt = (byte)numInt++;
|
||||||
Ii = J = pI;
|
if (first) /* ^ to first interval */
|
||||||
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 */
|
/* Process all nodes in the current interval list */
|
||||||
while ((h = pI->firstOfInt()) != NULL)
|
while ((h = firstOfInt (pI)) != NULL)
|
||||||
{
|
{
|
||||||
/* Check all immediate successors of h */
|
/* 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 = h->edges[i].BBptr;
|
||||||
succ->inEdgeCount--;
|
succ->inEdgeCount--;
|
||||||
|
|
||||||
if (succ->reachingInt == NULL) /* first visit */
|
if (succ->reachingInt == NULL) /* first visit */
|
||||||
{
|
{
|
||||||
succ->reachingInt = header;
|
succ->reachingInt = header;
|
||||||
if (succ->inEdgeCount == 0)
|
if (succ->inEdgeCount == 0)
|
||||||
appendNodeInt (H, succ, pI);
|
H = appendNodeInt (H, succ, pI);
|
||||||
else if (! succ->beenOnH) /* out edge */
|
else if (! succ->beenOnH) /* out edge */
|
||||||
{
|
{
|
||||||
appendQueue (H, succ);
|
appendQueue (&H, succ);
|
||||||
succ->beenOnH = true;
|
succ->beenOnH = TRUE;
|
||||||
pI->numOutEdges++;
|
pI->numOutEdges++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* node has been visited before */
|
else /* node has been visited before */
|
||||||
if (succ->inEdgeCount == 0)
|
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);
|
if (succ != header)
|
||||||
}
|
H = appendNodeInt (H, succ, pI);
|
||||||
else /* out edge */
|
}
|
||||||
pI->numOutEdges++;
|
else /* out edge */
|
||||||
}
|
pI->numOutEdges++;
|
||||||
else if (succ != header && succ->beenOnH)
|
}
|
||||||
pI->numOutEdges++;
|
else if (succ != header && succ->beenOnH)
|
||||||
|
pI->numOutEdges++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link interval I to list of intervals */
|
/* Link interval I to list of intervals */
|
||||||
if (! first)
|
if (! first)
|
||||||
{
|
{
|
||||||
J->next = pI;
|
J->next = pI;
|
||||||
J = pI;
|
J = pI;
|
||||||
}
|
}
|
||||||
else /* first interval */
|
else /* first interval */
|
||||||
first = false;
|
first = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Displays the intervals of the graph Gi. */
|
|
||||||
static void displayIntervals (interval *pI)
|
static void displayIntervals (interval *pI)
|
||||||
{
|
/* Displays the intervals of the graph Gi. */
|
||||||
|
{ queue *nodePtr;
|
||||||
|
|
||||||
while (pI)
|
while (pI)
|
||||||
{
|
{
|
||||||
printf (" Interval #: %ld\t#OutEdges: %ld\n", pI->numInt, pI->numOutEdges);
|
nodePtr = pI->nodes;
|
||||||
for(BB *node : pI->nodes)
|
printf (" Interval #: %ld\t#OutEdges: %ld\n",
|
||||||
{
|
pI->numInt, pI->numOutEdges);
|
||||||
if (node->correspInt == NULL) /* real BBs */
|
|
||||||
printf (" Node: %ld\n", node->begin()->loc_ip);
|
while (nodePtr)
|
||||||
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);
|
||||||
pI = pI->next;
|
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. */
|
/* Allocates space for a new derSeq node. */
|
||||||
static derSeq_Entry *newDerivedSeq()
|
{ derSeq *pder;
|
||||||
{
|
|
||||||
return new derSeq_Entry;
|
pder = allocStruc(derSeq);
|
||||||
|
memset (pder, 0, sizeof(derSeq));
|
||||||
|
return (pder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void freeQueue (queue **q)
|
||||||
/* Frees the storage allocated for the queue q*/
|
/* Frees the storage allocated for the queue q*/
|
||||||
static void freeQueue (queue &q)
|
{ queue *queuePtr;
|
||||||
{
|
|
||||||
q.clear();
|
for (queuePtr = *q; queuePtr; queuePtr = *q)
|
||||||
|
{
|
||||||
|
*q = (*q)->next;
|
||||||
|
free (queuePtr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Frees the storage allocated for the interval pI */
|
|
||||||
static void freeInterval (interval **pI)
|
static void freeInterval (interval **pI)
|
||||||
{
|
/* Frees the storage allocated for the interval pI */
|
||||||
interval *Iptr;
|
{ interval *Iptr;
|
||||||
|
|
||||||
while (*pI)
|
while (*pI)
|
||||||
{
|
{
|
||||||
(*pI)->nodes.clear();
|
freeQueue (&((*pI)->nodes));
|
||||||
Iptr = *pI;
|
Iptr = *pI;
|
||||||
*pI = (*pI)->next;
|
*pI = (*pI)->next;
|
||||||
delete (Iptr);
|
free (Iptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Frees the storage allocated by the derived sequence structure, except
|
void freeDerivedSeq(derSeq *derivedG)
|
||||||
|
/* Frees the storage allocated by the derived sequence structure, except
|
||||||
* for the original graph cfg (derivedG->Gi). */
|
* for the original graph cfg (derivedG->Gi). */
|
||||||
void freeDerivedSeq(derSeq &derivedG)
|
{ derSeq *derivedGi;
|
||||||
{
|
|
||||||
derivedG.clear();
|
while (derivedG)
|
||||||
}
|
{
|
||||||
derSeq_Entry::~derSeq_Entry()
|
freeInterval (&(derivedG->Ii));
|
||||||
{
|
if (derivedG->Gi->nodeType == INTERVAL_NODE)
|
||||||
freeInterval (&Ii);
|
freeCFG (derivedG->Gi);
|
||||||
// if(Gi && Gi->nodeType == INTERVAL_NODE)
|
derivedGi = derivedG;
|
||||||
// freeCFG (Gi);
|
derivedG = derivedG->next;
|
||||||
|
free (derivedGi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finds the next order graph of derivedGi->Gi according to its intervals
|
|
||||||
|
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. */
|
* (derivedGi->Ii), and places it in derivedGi->next->Gi. */
|
||||||
bool Function::nextOrderGraph (derSeq &derivedGi)
|
{ interval *Ii; /* Interval being processed */
|
||||||
{
|
BB *BBnode, /* New basic block of intervals */
|
||||||
interval *Ii; /* Interval being processed */
|
*curr, /* BB being checked for out edges */
|
||||||
BB *BBnode, /* New basic block of intervals */
|
*succ, /* Successor node */
|
||||||
*curr, /* BB being checked for out edges */
|
derInt;
|
||||||
*succ /* Successor node */
|
queue *listIi; /* List of intervals */
|
||||||
;
|
Int i, /* Index to outEdges array */
|
||||||
//queue *listIi; /* List of intervals */
|
j; /* Index to successors */
|
||||||
int i, /* Index to outEdges array */
|
boolT sameGraph; /* Boolean, isomorphic graphs */
|
||||||
j; /* Index to successors */
|
|
||||||
boolT sameGraph; /* Boolean, isomorphic graphs */
|
|
||||||
|
|
||||||
/* Process Gi's intervals */
|
/* Process Gi's intervals */
|
||||||
derSeq_Entry &prev_entry(derivedGi.back());
|
derivedGi->next = newDerivedSeq();
|
||||||
derivedGi.push_back(derSeq_Entry());
|
Ii = derivedGi->Ii;
|
||||||
derSeq_Entry &new_entry(derivedGi.back());
|
sameGraph = TRUE;
|
||||||
Ii = prev_entry.Ii;
|
derInt.next = NULL;
|
||||||
sameGraph = true;
|
BBnode = &derInt;
|
||||||
BBnode = 0;
|
|
||||||
std::vector<BB *> bbs;
|
|
||||||
while (Ii)
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
bbs.push_back(BB::Create(-1, -1, INTERVAL_NODE, Ii->numOutEdges, this));
|
|
||||||
BBnode = bbs.back();
|
|
||||||
BBnode->correspInt = Ii;
|
|
||||||
const queue &listIi(Ii->nodes);
|
|
||||||
|
|
||||||
/* Check for more than 1 interval */
|
while (Ii) {
|
||||||
if (sameGraph && (listIi.size()>1))
|
i = 0;
|
||||||
sameGraph = false;
|
BBnode = newBB (BBnode, -1, -1, INTERVAL_NODE, Ii->numOutEdges, NULL);
|
||||||
|
BBnode->correspInt = Ii;
|
||||||
|
listIi = Ii->nodes;
|
||||||
|
|
||||||
/* Find out edges */
|
/* Check for more than 1 interval */
|
||||||
|
if (sameGraph && listIi->next)
|
||||||
|
sameGraph = FALSE;
|
||||||
|
|
||||||
if (BBnode->edges.size() > 0)
|
/* Find out edges */
|
||||||
{
|
if (BBnode->numOutEdges > 0)
|
||||||
for(BB *curr : listIi)
|
while (listIi) {
|
||||||
{
|
curr = listIi->node;
|
||||||
for (j = 0; j < curr->edges.size(); j++)
|
for (j = 0; j < curr->numOutEdges; j++) {
|
||||||
{
|
succ = curr->edges[j].BBptr;
|
||||||
succ = curr->edges[j].BBptr;
|
if (succ->inInterval != curr->inInterval)
|
||||||
if (succ->inInterval != curr->inInterval)
|
BBnode->edges[i++].intPtr = succ->inInterval;
|
||||||
BBnode->edges[i++].intPtr = succ->inInterval;
|
}
|
||||||
}
|
listIi = listIi->next;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Next interval */
|
/* Next interval */
|
||||||
Ii = Ii->next;
|
Ii = Ii->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert list of pointers to intervals into a real graph.
|
/* Convert list of pointers to intervals into a real graph.
|
||||||
* Determines the number of in edges to each new BB, and places it
|
* Determines the number of in edges to each new BB, and places it
|
||||||
* in numInEdges and inEdgeCount for later interval processing. */
|
* in numInEdges and inEdgeCount for later interval processing. */
|
||||||
curr = new_entry.Gi = bbs.front();
|
curr = derivedGi->next->Gi = derInt.next;
|
||||||
for(BB *curr : bbs)
|
while (curr) {
|
||||||
{
|
for (i = 0; i < curr->numOutEdges; i++) {
|
||||||
for(TYPEADR_TYPE &edge : curr->edges)
|
BBnode = derivedGi->next->Gi; /* BB of an interval */
|
||||||
{
|
while (BBnode && curr->edges[i].intPtr != BBnode->correspInt)
|
||||||
BBnode = new_entry.Gi; /* BB of an interval */
|
BBnode = BBnode->next;
|
||||||
auto iter= std::find_if(bbs.begin(),bbs.end(),
|
if (BBnode) {
|
||||||
[&edge](BB *node)->bool { return edge.intPtr==node->correspInt;});
|
curr->edges[i].BBptr = BBnode;
|
||||||
if(iter==bbs.end())
|
BBnode->numInEdges++;
|
||||||
fatalError (INVALID_INT_BB);
|
BBnode->inEdgeCount++;
|
||||||
edge.BBptr = *iter;
|
}
|
||||||
(*iter)->inEdges.push_back((BB *)nullptr);
|
else
|
||||||
(*iter)->inEdgeCount++;
|
fatalError (INVALID_INT_BB);
|
||||||
}
|
}
|
||||||
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
return (boolT)(! sameGraph);
|
return (boolT)(! sameGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static byte findDerivedSeq (derSeq *derivedGi)
|
||||||
/* Finds the derived sequence of the graph derivedG->Gi (ie. cfg).
|
/* Finds the derived sequence of the graph derivedG->Gi (ie. cfg).
|
||||||
* Constructs the n-th order graph and places all the intermediate graphs
|
* Constructs the n-th order graph and places all the intermediate graphs
|
||||||
* in the derivedG list sequence. */
|
* 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 = derivedGi->Gi;
|
||||||
Gi = iter->Gi;
|
|
||||||
while (! trivialGraph (Gi))
|
while (! trivialGraph (Gi))
|
||||||
{
|
{
|
||||||
/* Find the intervals of Gi and place them in derivedGi->Ii */
|
/* 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 */
|
/* Create Gi+1 and check if it is equivalent to Gi */
|
||||||
if (! nextOrderGraph (derivedGi))
|
if (! nextOrderGraph (derivedGi))
|
||||||
break;
|
break;
|
||||||
++iter;
|
|
||||||
Gi = iter->Gi;
|
derivedGi = derivedGi->next;
|
||||||
stats.nOrder++;
|
Gi = derivedGi->Gi;
|
||||||
|
stats.nOrder++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! trivialGraph (Gi))
|
if (! trivialGraph (Gi))
|
||||||
{
|
{
|
||||||
++iter;
|
freeDerivedSeq(derivedGi->next); /* remove Gi+1 */
|
||||||
derivedGi.erase(iter,derivedGi.end()); /* remove Gi+1 */
|
derivedGi->next = NULL;
|
||||||
// freeDerivedSeq(derivedGi->next);
|
return FALSE;
|
||||||
// derivedGi->next = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
derivedGi.back().findIntervals (this);
|
findIntervals (derivedGi);
|
||||||
return true;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void nodeSplitting (BB *G)
|
||||||
/* Converts the irreducible graph G into an equivalent reducible one, by
|
/* Converts the irreducible graph G into an equivalent reducible one, by
|
||||||
* means of node splitting. */
|
* means of node splitting. */
|
||||||
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 */
|
/* 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");
|
printf ("\nDerived Sequence Intervals\n");
|
||||||
derSeq::iterator iter=this->begin();
|
while (derGi)
|
||||||
while (iter!=this->end())
|
|
||||||
{
|
{
|
||||||
printf ("\nIntervals for G%lX\n", n++);
|
printf ("\nIntervals for G%lX\n", n++);
|
||||||
displayIntervals (iter->Ii);
|
displayIntervals (derGi->Ii);
|
||||||
++iter;
|
derGi = derGi->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void checkReducibility (PPROC pProc, derSeq **derivedG)
|
||||||
/* Checks whether the control flow graph, cfg, is reducible or not.
|
/* Checks whether the control flow graph, cfg, is reducible or not.
|
||||||
* If it is not reducible, it is converted into an equivalent reducible
|
* If it is not reducible, it is converted into an equivalent reducible
|
||||||
* graph by node splitting. The derived sequence of graphs built from cfg
|
* graph by node splitting. The derived sequence of graphs built from cfg
|
||||||
* are returned in the pointer *derivedG.
|
* are returned in the pointer *derivedG.
|
||||||
*/
|
*/
|
||||||
derSeq * Function::checkReducibility()
|
{ byte reducible; /* Reducible graph flag */
|
||||||
{
|
|
||||||
derSeq * der_seq;
|
|
||||||
uint8_t reducible; /* Reducible graph flag */
|
|
||||||
|
|
||||||
numInt = 1; /* reinitialize no. of intervals*/
|
numInt = 1; /* reinitialize no. of intervals*/
|
||||||
stats.nOrder = 1; /* nOrder(cfg) = 1 */
|
stats.nOrder = 1; /* nOrder(cfg) = 1 */
|
||||||
der_seq = new derSeq;
|
*derivedG = newDerivedSeq();
|
||||||
der_seq->resize(1);
|
(*derivedG)->Gi = pProc->cfg;
|
||||||
der_seq->back().Gi = m_cfg.front();
|
reducible = findDerivedSeq(*derivedG);
|
||||||
reducible = findDerivedSeq(*der_seq);
|
|
||||||
|
|
||||||
if (! reducible)
|
if (! reducible) {
|
||||||
{
|
pProc->flg |= GRAPH_IRRED;
|
||||||
flg |= GRAPH_IRRED;
|
nodeSplitting (pProc->cfg);
|
||||||
nodeSplitting (m_cfg);
|
|
||||||
}
|
}
|
||||||
return der_seq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1282
src/scanner.cpp
1282
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
|
/* 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
|
look up by name or by value. Pointers are used for the duplicated symbolic
|
||||||
name to save space. Both tables have the same structure.
|
name to save space. Both tables have the same structure.
|
||||||
The hash tables automatically expand when they get 90% full; they are
|
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.)
|
Linear probing is used, due to the difficulty of implementing (e.g.)
|
||||||
quadratic probing with a variable table size.
|
quadratic probing with a variable table size.
|
||||||
*/
|
*/
|
||||||
#include <cstdio>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdlib>
|
#include <stdio.h>
|
||||||
#include <cstring>
|
#include <stdlib.h>
|
||||||
#include <unordered_map>
|
#include <string.h>
|
||||||
#include "dcc.h"
|
#include "dcc.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
|
||||||
#define TABLESIZE 16 /* Number of entries added each expansion */
|
#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 STRTABSIZE 256 /* Size string table is inc'd by */
|
||||||
#define NIL ((uint16_t)-1)
|
#define NIL ((word)-1)
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
|
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 char *pStrTab; /* Pointer to the current string table */
|
||||||
static int strTabNext; /* Next free index into pStrTab */
|
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 */
|
static tableType curTableType; /* Which table is current */
|
||||||
struct TABLEINFO_TYPE
|
typedef struct _tableInfo
|
||||||
{
|
{
|
||||||
TABLEINFO_TYPE()
|
SYMTABLE *symTab;
|
||||||
{
|
SYMTABLE *valTab;
|
||||||
symTab=valTab=0;
|
word numEntry;
|
||||||
}
|
word tableSize;
|
||||||
//void deleteVal(uint32_t symOff, Function *symProc, boolT bSymToo);
|
} TABLEINFO_TYPE;
|
||||||
void create(tableType type);
|
|
||||||
void destroy();
|
|
||||||
private:
|
|
||||||
|
|
||||||
SYMTABLE *symTab; /* Pointer to the symbol hashed table */
|
TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
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" */
|
/* 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)
|
void createSymTables(void)
|
||||||
{
|
{
|
||||||
/* Initilise the comment table */
|
/* Initilise the comment table */
|
||||||
/* NB - there is no symbol hashed 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 */
|
/* 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;
|
curTableType = Label;
|
||||||
|
|
||||||
/* Now the string table */
|
/* Now the string table */
|
||||||
strTabNext = 0;
|
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;
|
curTableType = Label;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectTable(tableType tt)
|
void
|
||||||
|
selectTable(tableType tt)
|
||||||
{
|
{
|
||||||
if (curTableType == tt)
|
if (curTableType == tt) return; /* Nothing to do */
|
||||||
return; /* Nothing to do */
|
|
||||||
currentTabInfo = tableInfo[tt];
|
symTab = tableInfo[tt].symTab;
|
||||||
|
valTab = tableInfo[tt].valTab;
|
||||||
|
numEntry = tableInfo[tt].numEntry;
|
||||||
|
tableSize= tableInfo[tt].tableSize;
|
||||||
curTableType = tt;
|
curTableType = tt;
|
||||||
}
|
}
|
||||||
void TABLEINFO_TYPE::destroy()
|
|
||||||
{
|
|
||||||
delete [] symTab; // The symbol hashed label table
|
|
||||||
delete [] valTab; // And the value hashed label table
|
|
||||||
}
|
|
||||||
void destroySymTables(void)
|
void destroySymTables(void)
|
||||||
{
|
{
|
||||||
selectTable(Label);
|
selectTable(Label);
|
||||||
currentTabInfo.destroy();
|
free(symTab); /* The symbol hashed label table */
|
||||||
|
free(valTab); /* And the value hashed label table */
|
||||||
selectTable(Comment);
|
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
|
/* Hash the symbolic name */
|
||||||
* if necessary (0 means no update necessary). */
|
word symHash(char *name, word *pre)
|
||||||
void SYMTAB::updateSymType (uint32_t symbol,const TypeContainer &tc)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
auto iter=findByLabel(symbol);
|
word h = 0;
|
||||||
if(iter==end())
|
char ch;
|
||||||
return;
|
|
||||||
iter->type = tc.m_type;
|
|
||||||
if (tc.m_size != 0)
|
|
||||||
iter->size = tc.m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Creates an entry in the global symbol table (symtab) if the variable
|
for (i=0; i < (int)strlen(name); i++)
|
||||||
* 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())
|
|
||||||
{
|
{
|
||||||
if(iter->size<size)
|
ch = name[i];
|
||||||
iter->size = size;
|
h = (h << 2) ^ ch;
|
||||||
inserted_new=false;
|
h += (ch >> 2) + (ch << 5);
|
||||||
return &(*iter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New symbol, not in symbol table */
|
*pre = h; /* Pre modulo hash value */
|
||||||
SYM v;
|
return h % tableSize; /* Post modulo hash value */
|
||||||
char buf[32]={};
|
}
|
||||||
sprintf (buf, "var%05X", operand);
|
|
||||||
v.name = buf;
|
/* Hash the symOff and symProc fields */
|
||||||
v.label = operand;
|
/* Note: for the time being, there no use is made of the symProc field */
|
||||||
v.size = size;
|
word
|
||||||
v.type = TypeContainer::defaultTypeForSize(size);
|
valHash(dword symOff, PPROC symProc, word *pre)
|
||||||
if (duFlag == eDuVal::USE) /* must already have init value */
|
{
|
||||||
|
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;
|
/* Table is full. Expand it */
|
||||||
v.duVal.val =1;
|
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
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Probe further */
|
||||||
|
j = (j+1) % tableSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == h)
|
||||||
|
{
|
||||||
|
printf("enterSym: val table overflow!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
push_back(v);
|
|
||||||
inserted_new=true;
|
/* Now enter into the symbol hashed table as well, if reqd */
|
||||||
return (&back());
|
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();
|
|
||||||
}
|
|
||||||
208
src/udm.cpp
208
src/udm.cpp
@ -4,104 +4,154 @@
|
|||||||
* that just plays with abstract cfg's and intervals and such like.
|
* that just plays with abstract cfg's and intervals and such like.
|
||||||
* (C) Cristina Cifuentes
|
* (C) Cristina Cifuentes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <list>
|
|
||||||
#include <cassert>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "dcc.h"
|
|
||||||
#include "disassem.h"
|
|
||||||
#include "project.h"
|
|
||||||
|
|
||||||
extern Project g_proj;
|
#include "dcc.h"
|
||||||
static void displayCFG(Function * pProc);
|
#include <stdio.h>
|
||||||
static void displayDfs(BB * pBB);
|
|
||||||
|
static void displayCFG(PPROC pProc);
|
||||||
|
static void displayDfs(PBB pBB);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* udm
|
* 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)
|
void udm(void)
|
||||||
{
|
{ PPROC pProc;
|
||||||
|
derSeq *derivedG;
|
||||||
|
|
||||||
/* Build the control flow graph, find idioms, and convert low-level
|
/* Build the control flow graph, find idioms, and convert low-level
|
||||||
* icodes to high-level ones */
|
* icodes to high-level ones */
|
||||||
Disassembler ds(2);
|
for (pProc = pLastProc; pProc; pProc = pProc->prev)
|
||||||
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
|
{
|
||||||
{
|
|
||||||
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
|
/* Data flow analysis - eliminate condition codes, extraneous registers
|
||||||
* and intermediate instructions. Find expressions by forward
|
* and intermediate instructions. Find expressions by forward
|
||||||
* substitution algorithm */
|
* substitution algorithm */
|
||||||
std::bitset<32> live_regs;
|
dataFlow (pProcList, 0);
|
||||||
g_proj.pProcList.front().dataFlow (live_regs);
|
|
||||||
|
|
||||||
/* Control flow analysis - structuring algorithm */
|
/* 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
|
* displayCFG - Displays the Basic Block list
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void Function::displayCFG()
|
static void displayCFG(PPROC pProc)
|
||||||
{
|
{
|
||||||
printf("\nBasic Block List - Proc %s", name.c_str());
|
Int i;
|
||||||
for (BB *pBB : m_cfg)
|
PBB pBB;
|
||||||
{
|
|
||||||
pBB->display();
|
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