Compare commits

...

1 Commits

Author SHA1 Message Date
nemerle
2a59d07ef2 Orignal dcc code
Only 2 differences with original release:
  add return type to main
  int disassem.cpp popPosStack() add cast to intptr_t
2015-05-28 17:17:26 +02:00
74 changed files with 12192 additions and 12457 deletions

View File

@ -1,7 +1,7 @@
PROJECT(dcc_original)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
OPTION(dcc_build_tests "Enable unit tests." OFF)
#OPTION(dcc_build_tests "Enable unit tests." OFF)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS)
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
@ -14,25 +14,24 @@ ENDIF()
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
FIND_PACKAGE(LLVM)
FIND_PACKAGE(Boost)
IF(dcc_build_tests)
FIND_PACKAGE(GMock)
ENDIF()
#FIND_PACKAGE(LLVM)
#FIND_PACKAGE(Boost)
#IF(dcc_build_tests)
# FIND_PACKAGE(GMock)
#ENDIF()
ADD_SUBDIRECTORY(3rd_party)
#ADD_SUBDIRECTORY(3rd_party)
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support)
#llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support)
INCLUDE_DIRECTORIES(
3rd_party/libdisasm
# 3rd_party/libdisasm
include
include/idioms
${Boost_INCLUDE_DIRS}
${LLVM_INCLUDE_DIRS}
# include/idioms
# ${Boost_INCLUDE_DIRS}
# ${LLVM_INCLUDE_DIRS}
)
set(dcc_SOURCES
src/dcc.cpp
src/ast.cpp
src/backend.cpp
src/bundle.cpp
@ -40,75 +39,47 @@ set(dcc_SOURCES
src/comwrite.cpp
src/control.cpp
src/dataflow.cpp
src/dcc.cpp
src/disassem.cpp
src/error.cpp
src/fixwild.cpp
src/frontend.cpp
src/graph.cpp
src/hlicode.cpp
src/machine_x86.cpp
src/icode.cpp
src/idioms.cpp
src/idioms/idiom1.cpp
src/idioms/arith_idioms.cpp
src/idioms/call_idioms.cpp
src/idioms/epilogue_idioms.cpp
src/idioms/mov_idioms.cpp
src/idioms/neg_idioms.cpp
src/idioms/shift_idioms.cpp
src/idioms/xor_idioms.cpp
src/locident.cpp
src/parser.cpp
src/perfhlib.cpp
src/procs.cpp
src/project.cpp
src/Procedure.cpp
src/proplong.cpp
src/reducible.cpp
src/scanner.cpp
src/symtab.cpp
src/udm.cpp
src/BasicBlock.cpp
)
set(dcc_HEADERS
include/ast.h
include/bundle.h
include/BinaryImage.h
include/dcc.h
include/disassem.h
include/dosdcc.h
include/error.h
include/graph.h
include/hlicode.h
include/machine_x86.h
include/icode.h
include/idioms/idiom.h
include/idioms/idiom1.h
include/idioms/arith_idioms.h
include/idioms/call_idioms.h
include/idioms/epilogue_idioms.h
include/idioms/mov_idioms.h
include/idioms/neg_idioms.h
include/idioms/shift_idioms.h
include/idioms/xor_idioms.h
include/locident.h
include/perfhlib.h
include/project.h
include/scanner.h
include/state.h
include/symtab.h
include/types.h
include/Procedure.h
include/StackFrame.h
include/BasicBlock.h
)
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
if(dcc_build_tests)
ADD_SUBDIRECTORY(src)
endif()
#TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
#if(dcc_build_tests)
#ADD_SUBDIRECTORY(src)
#endif()

View File

@ -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;
};

View File

@ -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 */
};

View File

@ -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
};

View File

@ -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;
};

View File

@ -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);
};

View File

@ -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);
};

View File

@ -4,12 +4,9 @@
* Date: September 1993
* (C) Cristina Cifuentes
*/
#pragma once
#include <cstring>
#include <list>
#include "Enums.h"
#include <boost/range.hpp>
static const int operandSize=20;
#define operandSize 20
/* The following definitions and types define the Conditional Expression
* attributed syntax tree, as defined by the following EBNF:
CondExp ::= CondTerm AND CondTerm | CondTerm
@ -18,160 +15,123 @@ static const int operandSize=20;
Identifier ::= globalVar | register | localVar | parameter | constant
op ::= <= | < | = | != | > | >=
*/
/* 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;
struct STKFRAME;
struct LOCAL_ID;
struct ICODE;
struct LLInst;
struct ID;
typedef std::list<ICODE>::iterator iICODE;
typedef boost::iterator_range<iICODE> rICODE;
#include "IdentType.h"
/* Conditional Expression enumeration nodes and operators */
typedef enum {
BOOLEAN_OP, /* condOps */
NEGATION, /* not (2's complement) */
ADDRESSOF, /* addressOf (&) */
DEREFERENCE, /* contents of (*) */
IDENTIFIER, /* {register | local | param | constant | global} */
/* The following are only available to C programs */
POST_INC, /* ++ (post increment) */
POST_DEC, /* -- (post decrement) */
PRE_INC, /* ++ (pre increment) */
PRE_DEC, /* -- (pre decrement) */
} condNodeType;
typedef enum {
GLOB_VAR, /* global variable */
REGISTER, /* register */
LOCAL_VAR, /* negative disp */
PARAM, /* positive disp */
GLOB_VAR_IDX, /* indexed global variable *//*** should merge w/glob-var*/
CONSTANT, /* constant */
STRING, /* string */
LONG_VAR, /* long variable */
FUNCTION, /* function */
OTHER /* other **** tmp solution */
} condId;
typedef enum {
/* For conditional expressions */
LESS_EQUAL = 0, /* <= */
LESS, /* < */
EQUAL, /* == */
NOT_EQUAL, /* != */
GREATER, /* > */
GREATER_EQUAL, /* >= */
/* For general expressions */
AND, /* & */
OR, /* | */
XOR, /* ^ */
NOT, /* ~ */ /* 1's complement */
ADD, /* + */
SUB, /* - */
MUL, /* * */
DIV, /* / */
SHR, /* >> */
SHL, /* << */
MOD, /* % */
DBL_AND, /* && */
DBL_OR, /* || */
DUMMY, /* */
} condOp;
/* High-level BOOLEAN conditions for iJB..iJNS icodes */
static 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 */
struct COND_EXPR
{
protected:
struct /* for BOOLEAN_OP */
{
condOp op;
COND_EXPR *lhs;
COND_EXPR *rhs;
} boolExpr;
public:
condNodeType m_type; /* Conditional Expression Node Type */
typedef struct _condExpr {
condNodeType type; /* Conditional Expression Node Type */
union _exprNode { /* Different cond expr nodes */
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
IDENTTYPE ident; /* for IDENTIFIER */
} expr;
COND_EXPR *lhs()
{
assert(m_type==BOOLEAN_OP);
return boolExpr.lhs;
}
const COND_EXPR *lhs() const
{
assert(m_type==BOOLEAN_OP);
return boolExpr.lhs;
}
COND_EXPR *rhs()
{
assert(m_type==BOOLEAN_OP);
return boolExpr.rhs;
}
const COND_EXPR *rhs() const
{
assert(m_type==BOOLEAN_OP);
return boolExpr.rhs;
}
condOp op() const { return boolExpr.op;}
public:
static COND_EXPR *idRegIdx(int idx, regType reg_type);
static COND_EXPR *idKte(uint32_t kte, uint8_t size);
static COND_EXPR *idLoc(int off, LOCAL_ID *localId);
static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
static COND_EXPR *idLongIdx(int idx);
static COND_EXPR *idOther(eReg seg, eReg regi, int16_t off);
static COND_EXPR *idParam(int off, const STKFRAME *argSymtab);
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr);
static COND_EXPR *idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
static COND_EXPR *idFunc(Function *pproc, STKFRAME *args);
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
static COND_EXPR * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
static COND_EXPR *boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op);
static bool insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx);
static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
public:
virtual COND_EXPR *clone() const;
void release();
void changeBoolOp(condOp newOp);
COND_EXPR(const COND_EXPR &other)
{
m_type=other.m_type;
expr=other.expr;
boolExpr=other.boolExpr;
}
COND_EXPR(condNodeType t=UNKNOWN_OP) : m_type(t)
{
memset(&expr,0,sizeof(_exprNode));
memset(&boolExpr,0,sizeof(boolExpr));
struct { /* for BOOLEAN_OP */
condOp op;
struct _condExpr *lhs;
struct _condExpr *rhs;
} boolExpr;
struct _condExpr *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
IDENTTYPE ident; /* for IDENTIFIER */
} expr;
} COND_EXPR;
}
virtual ~COND_EXPR() {}
public:
virtual COND_EXPR *inverse() const; // return new COND_EXPR that is invarse of this
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
virtual hlType expType(Function *pproc) const;
};
struct BinaryOperator : public COND_EXPR
{
condOp m_op;
COND_EXPR *m_lhs;
COND_EXPR *m_rhs;
BinaryOperator(condOp o)
{
m_op = o;
m_lhs=m_rhs=nullptr;
}
static BinaryOperator *Create(condOp o,COND_EXPR *l,COND_EXPR *r);
static BinaryOperator *CreateAdd(COND_EXPR *l,COND_EXPR *r);
virtual COND_EXPR *inverse();
virtual COND_EXPR *clone();
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym);
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
/* Sequence of conditional expression data type */
/*** NOTE: not used at present ****/
typedef struct _condExpSeq {
COND_EXPR *expr;
struct _condExpSeq *next;
} SEQ_COND_EXPR;
COND_EXPR *lhs()
{
assert(m_type==BOOLEAN_OP);
return m_lhs;
}
const COND_EXPR *lhs() const
{
assert(m_type==BOOLEAN_OP);
return m_lhs;
}
COND_EXPR *rhs()
{
assert(m_type==BOOLEAN_OP);
return m_rhs;
}
const COND_EXPR *rhs() const
{
assert(m_type==BOOLEAN_OP);
return m_rhs;
}
condOp op() const { return m_op;}
/* Changes the boolean conditional operator at the root of this expression */
void op(condOp o) { m_op=o;}
};
struct UnaryOperator : public COND_EXPR
{
condOp op;
COND_EXPR *unaryExp;
virtual COND_EXPR *inverse();
virtual COND_EXPR *clone();
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
static UnaryOperator *Create(condNodeType t, COND_EXPR *sub_expr)
{
UnaryOperator *newExp = new UnaryOperator();
newExp->m_type=t;
newExp->unaryExp = sub_expr;
return (newExp);
}
};
struct GlobalVariable : public COND_EXPR
{
static COND_EXPR *Create(int16_t segValue, int16_t off);
};
struct Constant : public COND_EXPR
{};

View File

@ -4,39 +4,28 @@
* Purpose: Module to handle the bundle type (array of pointers to strings).
* (C) Cristina Cifuentes
****************************************************************************/
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
struct strTable : std::vector<std::string>
{
/* Returns the next available index into the table */
size_t nextIdx() {return size();}
public:
void addLabelBundle(int idx, int label);
};
struct bundle
{
public:
void appendCode(const char *format, ...);
void appendCode(const std::string &s);
void appendDecl(const char *format, ...);
void appendDecl(const std::string &);
void init()
{
decl.clear();
code.clear();
}
#include <stdio.h>
typedef struct {
Int numLines; /* Number of lines in the table */
Int allocLines; /* Number of lines allocated in the table */
char **str; /* Table of strings */
} strTable;
typedef struct {
strTable decl; /* Declarations */
strTable code; /* C code */
int current_indent;
};
} bundle;
#define lineSize 360 /* 3 lines in the mean time */
//void newBundle (bundle *procCode);
void writeBundle (std::ostream &ios, bundle procCode);
void newBundle (bundle *procCode);
void appendStrTab (strTable *strTab, char *format, ...);
Int nextBundleIdx (strTable *strTab);
void addLabelBundle (strTable *strTab, Int idx, Int label);
void writeBundle (FILE *fp, bundle procCode);
void freeBundle (bundle *procCode);

View File

@ -2,15 +2,8 @@
* dcc project general header
* (C) Cristina Cifuentes, Mike van Emmerik
****************************************************************************/
#pragma once
//TODO: Remove boolT
#include <llvm/ADT/ilist.h>
#include <utility>
#include <algorithm>
#include <bitset>
#include "Enums.h"
#include "types.h"
#include "ast.h"
#include "icode.h"
@ -18,31 +11,134 @@
#include "error.h"
#include "graph.h"
#include "bundle.h"
#include "Procedure.h"
#include "BasicBlock.h"
struct Project;
/* SYMBOL TABLE */
typedef struct {
char name[10]; /* New name for this variable */
dword label; /* physical address (20 bit) */
Int size; /* maximum size */
flags32 flg; /* SEG_IMMED, IMPURE, WORD_OFF */
hlType type; /* probable type */
word duVal; /* DEF, USE, VAL */
} SYM;
typedef SYM *PSYM;
typedef struct {
Int csym; /* No. of symbols in table */
Int alloc; /* Allocation */
PSYM sym; /* Symbols */
} SYMTAB;
typedef SYMTAB *PSYMTAB;
/* STACK FRAME */
typedef struct {
COND_EXPR *actual; /* Expression tree of actual parameter */
COND_EXPR *regs; /* For register arguments only */
int16 off; /* Immediate off from BP (+:args, -:params) */
byte regOff; /* Offset is a register (e.g. SI, DI) */
Int size; /* Size */
hlType type; /* Probable type */
word duVal; /* DEF, USE, VAL */
boolT hasMacro; /* This type needs a macro */
char macro[10]; /* Macro name */
char name[10]; /* Name for this symbol/argument */
boolT invalid; /* Boolean: invalid entry in formal arg list*/
} STKSYM;
typedef STKSYM *PSTKSYM;
typedef struct _STKFRAME {
Int csym; /* No. of symbols in table */
Int alloc; /* Allocation */
PSTKSYM sym; /* Symbols */
int16 minOff; /* Initial offset in stack frame*/
int16 maxOff; /* Maximum offset in stack frame*/
Int cb; /* Number of bytes in arguments */
Int numArgs; /* No. of arguments in the table*/
} STKFRAME;
typedef STKFRAME *PSTKFRAME;
/* PROCEDURE NODE */
typedef struct _proc {
dword procEntry; /* label number */
char name[SYMLEN]; /* Meaningful name for this proc */
STATE state; /* Entry state */
Int depth; /* Depth at which we found it - for printing */
flags32 flg; /* Combination of Icode & Proc flags */
int16 cbParam; /* Probable no. of bytes of parameters */
STKFRAME args; /* Array of arguments */
LOCAL_ID localId; /* Local identifiers */
ID retVal; /* Return value - identifier */
/* Icodes and control flow graph */
CIcodeRec Icode; /* Object with ICODE records */
PBB cfg; /* Ptr. to BB list/CFG */
PBB *dfsLast; /* Array of pointers to BBs in dfsLast
* (reverse postorder) order */
Int numBBs; /* Number of BBs in the graph cfg */
boolT hasCase; /* Procedure has a case node */
/* For interprocedural live analysis */
dword liveIn; /* Registers used before defined */
dword liveOut; /* Registers that may be used in successors */
boolT liveAnal; /* Procedure has been analysed already */
/* Double-linked list */
struct _proc *next;
struct _proc *prev;
} PROCEDURE;
typedef PROCEDURE *PPROC;
/* CALL GRAPH NODE */
struct CALL_GRAPH
{
ilFunction proc; /* Pointer to procedure in pProcList */
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
public:
void write();
CALL_GRAPH() : outEdges(0)
{
}
public:
void writeNodeCallGraph(int indIdx);
bool insertCallGraph(ilFunction caller, ilFunction callee);
bool insertCallGraph(Function *caller, ilFunction callee);
void insertArc(ilFunction newProc);
};
//#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
//extern std::list<Function> pProcList;
//extern FunctionListType pProcList;
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
typedef struct _callGraph {
PPROC proc; /* Pointer to procedure in pProcList */
Int numOutEdges; /* # of out edges (ie. # procs invoked) */
Int numAlloc; /* # of out edges allocated */
struct _callGraph **outEdges; /* array of out edges */
} CALL_GRAPH;
typedef CALL_GRAPH *PCALL_GRAPH;
#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
extern PPROC pProcList; /* Pointer to the head of the procedure list */
extern PPROC pLastProc; /* Pointer to last node of the proc list */
extern PCALL_GRAPH callGraph; /* Pointer to the head of the call graph */
extern bundle cCode; /* Output C procedure's declaration and code */
/* Procedure FLAGS */
#define PROC_BADINST 0x000100 /* Proc contains invalid or 386 instruction */
#define PROC_IJMP 0x000200 /* Proc incomplete due to indirect jmp */
#define PROC_ICALL 0x000400 /* Proc incomplete due to indirect call */
#define PROC_HLL 0x001000 /* Proc is likely to be from a HLL */
#define CALL_PASCAL 0x002000 /* Proc uses Pascal calling convention */
#define CALL_C 0x004000 /* Proc uses C calling convention */
#define CALL_UNKNOWN 0x008000 /* Proc uses unknown calling convention */
#define PROC_NEAR 0x010000 /* Proc exits with near return */
#define PROC_FAR 0x020000 /* Proc exits with far return */
#define GRAPH_IRRED 0x100000 /* Proc generates an irreducible graph */
#define SI_REGVAR 0x200000 /* SI is used as a stack variable */
#define DI_REGVAR 0x400000 /* DI is used as a stack variable */
#define PROC_IS_FUNC 0x800000 /* Proc is a function */
#define REG_ARGS 0x1000000 /* Proc has registers as arguments */
#define PROC_VARARG 0x2000000 /* Proc has variable arguments */
#define PROC_OUTPUT 0x4000000 /* C for this proc has been output */
#define PROC_RUNTIME 0x8000000 /* Proc is part of the runtime support */
#define PROC_ISLIB 0x10000000 /* Proc is a library function */
#define PROC_ASM 0x20000000 /* Proc is an intrinsic assembler routine */
#define PROC_IS_HLL 0x40000000 /* Proc has HLL prolog code */
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
/* duVal FLAGS */
#define DEF 0x0010 /* Variable was first defined than used */
#define USE 0x0100 /* Variable was first used than defined */
#define VAL 0x1000 /* Variable has an initial value. 2 cases:
* 1. When variable is used first (ie. global)
* 2. When a value is moved into the variable
* for the first time. */
#define USEVAL 0x1100 /* Use and Val */
/**** Global variables ****/
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
@ -55,95 +151,174 @@ typedef struct { /* Command line option flags */
unsigned Map : 1;
unsigned Stats : 1;
unsigned Interact : 1; /* Interactive mode */
unsigned Calls : 1; /* Follow register indirect calls */
char filename[80]; /* The input filename */
unsigned Calls : 1; /* Follow register indirect calls */
char filename[80]; /* The input filename */
} OPTION;
extern OPTION option; /* Command line options */
extern SYMTAB symtab; /* Global symbol table */
#include "BinaryImage.h"
extern std::bitset<32> duReg[30]; /* def/use bits for registers */
typedef struct { /* Loaded program image parameters */
int16 initCS;
int16 initIP; /* These are initial load values */
int16 initSS; /* Probably not of great interest */
int16 initSP;
boolT fCOM; /* Flag set if COM program (else EXE)*/
Int cReloc; /* No. of relocation table entries */
dword *relocTable; /* Ptr. to relocation table */
byte *map; /* Memory bitmap ptr */
Int cProcs; /* Number of procedures so far */
Int offMain; /* The offset of the main() proc */
word segMain; /* The segment of the main() proc */
boolT bSigs; /* True if signatures loaded */
Int cbImage; /* Length of image in bytes */
byte *Image; /* Allocated by loader to hold entire
* program image */
} PROG;
//extern uint32_t duReg[30]; /* def/use bits for registers */
extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */
extern PROG prog; /* Loaded program image parameters */
extern char condExp[200]; /* Conditional expression buffer */
extern char callBuf[100]; /* Function call buffer */
extern dword duReg[30]; /* def/use bits for registers */
extern dword maskDuReg[30]; /* masks off du bits for regs */
/* Registers used by icode instructions */
static char *allRegs[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
"si", "di", "es", "cs", "ss", "ds",
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
"tmp"};
/* Memory map states */
enum eAreaType
{
BM_UNKNOWN = 0, /* Unscanned memory */
BM_DATA = 1, /* Data */
BM_CODE = 2, /* Code */
BM_IMPURE = 3 /* Used as Data and Code*/
};
#define BM_UNKNOWN 0 /* Unscanned memory */
#define BM_DATA 1 /* Data */
#define BM_CODE 2 /* Code */
#define BM_IMPURE 3 /* Used as Data and Code*/
/* Intermediate instructions statistics */
struct STATS
{
int numBBbef; /* number of basic blocks initially */
int numBBaft; /* number of basic blocks at the end */
int nOrder; /* n-th order */
int numLLIcode; /* number of low-level Icode instructions */
int numHLIcode; /* number of high-level Icode instructions */
int totalLL; /* total number of low-level Icode insts */
int totalHL; /* total number of high-level Icod insts */
};
typedef struct {
Int numBBbef; /* number of basic blocks initially */
Int numBBaft; /* number of basic blocks at the end */
Int nOrder; /* n-th order */
Int numLLIcode; /* number of low-level Icode instructions */
Int numHLIcode; /* number of high-level Icode instructions */
Int totalLL; /* total number of low-level Icode insts */
Int totalHL; /* total number of high-level Icod insts */
} STATS;
extern STATS stats; /* Icode statistics */
/**** Global function prototypes ****/
class DccFrontend
{
void LoadImage(Project &proj);
void parse(Project &proj);
std::string m_fname;
public:
DccFrontend(const std::string &fname) : m_fname(fname)
{
}
bool FrontEnd(); /* frontend.c */
};
void FrontEnd(char *filename, PCALL_GRAPH *); /* frontend.c */
void *allocMem(Int cb); /* frontend.c */
void *reallocVar(void *p, Int newsize); /* frontend.c */
void udm(void); /* udm.c */
void freeCFG(BB * cfg); /* graph.c */
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
char *cChar(uint8_t c); /* backend.c */
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
void parse (CALL_GRAPH * *); /* parser.c */
int strSize (uint8_t *, char); /* parser.c */
//void disassem(int pass, Function * pProc); /* disassem.c */
void interactDis(Function * initProc, int initIC); /* disassem.c */
bool JmpInst(llIcode opcode); /* idioms.c */
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
PBB createCFG(PPROC pProc); /* graph.c */
void compressCFG(PPROC pProc); /* graph.c */
void freeCFG(PBB cfg); /* graph.c */
PBB newBB(PBB, Int, Int, byte, Int, PPROC); /* graph.c */
void BackEnd(char *filename, PCALL_GRAPH); /* backend.c */
char *cChar(byte c); /* backend.c */
Int scan(dword ip, PICODE p); /* scanner.c */
void parse (PCALL_GRAPH *); /* parser.c */
boolT labelSrch(PICODE pIc, Int n, dword tg, Int *pIdx); /* parser.c */
void setState(PSTATE state, word reg, int16 value); /* parser.c */
Int strSize (byte *, char); /* parser.c */
void disassem(Int pass, PPROC pProc); /* disassem.c */
void interactDis(PPROC initProc, Int initIC); /* disassem.c */
void bindIcodeOff (PPROC); /* idioms.c */
void lowLevelAnalysis (PPROC pProc); /* idioms.c */
void propLong (PPROC pproc); /* proplong.c */
boolT JmpInst(llIcode opcode); /* idioms.c */
void checkReducibility(PPROC pProc, derSeq **derG); /* reducible.c */
queue *appendQueue(queue **Q, BB *node); /* reducible.c */
void freeDerivedSeq(derSeq *derivedG); /* reducible.c */
void displayDerivedSeq(derSeq *derG); /* reducible.c */
void structure(PPROC pProc, derSeq *derG); /* control.c */
void compoundCond (PPROC); /* control.c */
void dataFlow(PPROC pProc, dword liveOut); /* dataflow.c */
void writeIntComment (PICODE icode, char *s); /* comwrite.c */
void writeProcComments (PPROC pProc, strTable *sTab); /* comwrite.c */
void checkStartup(PSTATE pState); /* chklib.c */
void SetupLibCheck(void); /* chklib.c */
void CleanupLibCheck(void); /* chklib.c */
bool LibCheck(Function &p); /* chklib.c */
boolT LibCheck(PPROC p); /* chklib.c */
/* Exported functions from procs.c */
boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction);
void adjustActArgType (COND_EXPR *, hlType, Function *);
boolT insertCallGraph (PCALL_GRAPH, PPROC, PPROC);
void writeCallGraph (PCALL_GRAPH);
void newRegArg (PPROC, PICODE, PICODE);
boolT newStkArg (PICODE, COND_EXPR *, llIcode, PPROC);
void allocStkArgs (PICODE, Int);
void placeStkArg (PICODE, COND_EXPR *, Int);
void adjustActArgType (COND_EXPR *, hlType, PPROC);
void adjustForArgType (PSTKFRAME, Int, hlType);
/* Exported functions from ast.c */
std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, int *);
int hlTypeSize (const COND_EXPR *, Function *);
//hlType expType (const COND_EXPR *, Function *);
COND_EXPR *boolCondExp (COND_EXPR *lhs, COND_EXPR *rhs, condOp op);
COND_EXPR *unaryCondExp (condNodeType, COND_EXPR *exp);
COND_EXPR *idCondExpGlob (int16 segValue, int16 off);
COND_EXPR *idCondExpReg (byte regi, flags32 flg, LOCAL_ID *);
COND_EXPR *idCondExpRegIdx (Int idx, regType);
COND_EXPR *idCondExpLoc (Int off, LOCAL_ID *);
COND_EXPR *idCondExpParam (Int off, PSTKFRAME argSymtab);
COND_EXPR *idCondExpKte (dword kte, byte);
COND_EXPR *idCondExpLong (LOCAL_ID *, opLoc, PICODE, hlFirst, Int idx, operDu,
Int);
COND_EXPR *idCondExpLongIdx (Int);
COND_EXPR *idCondExpFunc (PPROC, PSTKFRAME);
COND_EXPR *idCondExpOther (byte seg, byte regi, int16 off);
COND_EXPR *idCondExpID (ID *, LOCAL_ID *, Int);
COND_EXPR *idCondExp (PICODE, opLoc, PPROC, Int i, PICODE duIcode, operDu);
COND_EXPR *copyCondExp (COND_EXPR *);
void removeRegFromLong (byte, LOCAL_ID *, COND_EXPR *);
char *walkCondExpr (COND_EXPR *exp, PPROC pProc, Int *);
condId idType (PICODE pIcode, opLoc sd);
Int hlTypeSize (COND_EXPR *, PPROC);
hlType expType (COND_EXPR *, PPROC);
void setRegDU (PICODE, byte regi, operDu);
void copyDU (PICODE, PICODE, operDu, operDu);
void changeBoolCondExpOp (COND_EXPR *, condOp);
boolT insertSubTreeReg (COND_EXPR *, COND_EXPR **, byte, LOCAL_ID *);
boolT insertSubTreeLongReg (COND_EXPR *, COND_EXPR **, Int);
void freeCondExpr (COND_EXPR *exp);
COND_EXPR *concatExps (SEQ_COND_EXPR *, COND_EXPR *, condNodeType);
void initExpStk();
void pushExpStk (COND_EXPR *);
COND_EXPR *popExpStk();
Int numElemExpStk();
boolT emptyExpStk();
/* Exported functions from hlicode.c */
std::string writeCall (Function *, STKFRAME &, Function *, int *);
char *writeJcond (const HLTYPE &, Function *, int *);
char *writeJcondInv (HLTYPE, Function *, int *);
void newAsgnHlIcode (PICODE, COND_EXPR *, COND_EXPR *);
void newCallHlIcode (PICODE);
void newUnaryHlIcode (PICODE, hlIcode, COND_EXPR *);
void newJCondHlIcode (PICODE, COND_EXPR *);
void invalidateIcode (PICODE);
boolT removeDefRegi (byte, PICODE, Int, LOCAL_ID *);
void highLevelGen (PPROC);
char *writeCall (PPROC, PSTKFRAME, PPROC, Int *);
char *write1HlIcode (HLTYPE, PPROC, Int *);
char *writeJcond (HLTYPE, PPROC, Int *);
char *writeJcondInv (HLTYPE, PPROC, Int *);
Int power2 (Int);
void writeDU (PICODE, Int);
void inverseCondOp (COND_EXPR **);
/* Exported funcions from locident.c */
boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
eReg otherLongRegi(eReg, int, LOCAL_ID *);
Int newByteWordRegId (LOCAL_ID *, hlType t, byte regi);
Int newByteWordStkId (LOCAL_ID *, hlType t, Int off, byte regOff);
Int newIntIdxId (LOCAL_ID *, int16 seg, int16 off, byte regi, Int, hlType);
Int newLongRegId (LOCAL_ID *, hlType t, byte regH, byte regL, Int idx);
Int newLongStkId (LOCAL_ID *, hlType t, Int offH, Int offL);
Int newLongId (LOCAL_ID *, opLoc sd, PICODE, hlFirst, Int idx, operDu, Int);
boolT checkLongEq (LONG_STKID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **,
COND_EXPR **, Int);
boolT checkLongRegEq (LONGID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **,
COND_EXPR **, Int);
byte otherLongRegi (byte, Int, LOCAL_ID *);
void insertIdx (IDX_ARRAY *, Int);
void propLongId (LOCAL_ID *, byte, byte, char *);
extern const char *indentStr(int level);

View File

@ -2,32 +2,7 @@
* dcc project disassembler header
* (C) Mike van Emmerik
****************************************************************************/
#pragma once
#include <sstream>
#include <fstream>
#include <vector>
#include "bundle.h"
struct LLInst;
struct Disassembler
{
protected:
int pass;
int g_lab;
//bundle &cCode;
std::ofstream m_fp;
std::vector<std::string> m_decls;
std::vector<std::string> m_code;
public:
Disassembler(int _p) : pass(_p)
{
g_lab=0;
}
public:
void disassem(Function *ppProc);
void disassem(Function *ppProc, int i);
void dis1Line(LLInst &inst, int loc_ip, int pass);
};
/* Definitions for extended keys (first key is zero) */
#define EXT 0x100 /* "Extended" flag */

View File

@ -5,34 +5,34 @@
**************************************************************************/
/* Type definitions for intel 80x86 architecture */
typedef unsigned int uint16_t; /* 16 bits */
typedef unsigned char uint8_t; /* 8 bits */
typedef unsigned int Word; /* 16 bits */
typedef unsigned char Byte; /* 8 bits */
typedef union {
unsigned long dW;
uint16_t wL, wH; /* 2 words */
Word wL, wH; /* 2 words */
} Dword; /* 32 bits */
/* Structure to access high and low bits of a uint8_t or uint16_t variable */
/* Structure to access high and low bits of a Byte or Word variable */
typedef struct {
/* low uint8_t */
uint16_t lowBitWord : 1;
uint16_t filler1 : 6;
uint16_t highBitByte : 1;
/* high uint8_t */
uint16_t lowBitByte : 1;
uint16_t filler2 : 6;
uint16_t highBitWord : 1;
/* low byte */
Word lowBitWord : 1;
Word filler1 : 6;
Word highBitByte : 1;
/* high byte */
Word lowBitByte : 1;
Word filler2 : 6;
Word highBitWord : 1;
} wordBits;
/* Low and high bits of a uint8_t or uint16_t variable */
/* Low and high bits of a Byte or Word variable */
#define lowBit(a) ((wordBits)(a).lowBitWord)
#define highBitByte(a) ((wordBits)(a).highBitByte)
#define lowBitByte(a) ((wordBits)(a).lowBitByte)
#define highBit(a) (sizeof(a) == sizeof(uint16_t) ? \
#define highBit(a) (sizeof(a) == sizeof(Word) ? \
((wordBits)(a).highBitWord):\
((wordBits)(a).highBitByte))
/* uint16_t register variables */
/* Word register variables */
#define ax regs.x.ax
#define bx regs.x.bx
#define cx regs.x.cx
@ -52,7 +52,7 @@ typedef struct {
#define carry regs.x.cflags
#define overF regs.x.flags /***** check *****/
/* uint8_t register variables */
/* Byte register variables */
#define ah regs.h.ah
#define al regs.h.al
#define bh regs.h.bh
@ -64,8 +64,8 @@ typedef struct {
/* High and low words of a Dword */
#define highWord(w) (*((uint16_t*)&(w) + 1))
#define lowWord(w) ((uint16_t)(w))
#define highWord(w) (*((Word*)&(w) + 1))
#define lowWord(w) ((Word)(w))
#define MAXByte 0xFF
#define MAXWord 0xFFFF
@ -74,4 +74,7 @@ typedef struct {
#define MAXSignWord 0x7FFF
#define MINSignWord 0x8001
/* Booleans */
#define TRUE 1
#define FALSE 0

View File

@ -2,35 +2,32 @@
* Error codes
* (C) Cristina Cifuentes
****************************************************************************/
#pragma once
/* These definitions refer to errorMessage in error.c */
enum eErrorId
{
NO_ERR =0,
USAGE,
INVALID_ARG,
INVALID_OPCODE,
INVALID_386OP,
FUNNY_SEGOVR,
FUNNY_REP,
CANNOT_OPEN,
CANNOT_READ,
MALLOC_FAILED,
NEWEXE_FORMAT,
NO_BB,
INVALID_SYNTHETIC_BB,
INVALID_INT_BB,
IP_OUT_OF_RANGE,
DEF_NOT_FOUND,
JX_NOT_DEF,
NOT_DEF_USE,
REPEAT_FAIL,
WHILE_FAIL
};
#define USAGE 0
#define INVALID_ARG 1
#define INVALID_OPCODE 2
#define INVALID_386OP 3
#define FUNNY_SEGOVR 4
#define FUNNY_REP 5
#define CANNOT_OPEN 6
#define CANNOT_READ 7
#define MALLOC_FAILED 8
#define NEWEXE_FORMAT 9
#define NO_BB 10
#define INVALID_SYNTHETIC_BB 11
#define INVALID_INT_BB 12
#define IP_OUT_OF_RANGE 13
#define DEF_NOT_FOUND 14
#define JX_NOT_DEF 15
#define NOT_DEF_USE 16
#define REPEAT_FAIL 17
#define WHILE_FAIL 18
void fatalError(eErrorId errId, ...);
void reportError(eErrorId errId, ...);
void fatalError(Int errId, ...);
void reportError(Int errId, ...);

View File

@ -2,49 +2,37 @@
* CFG, BB and interval related definitions
* (C) Cristina Cifuentes
****************************************************************************/
#pragma once
#include <list>
#include <vector>
struct Function;
/* Types of basic block nodes */
/* Real basic blocks: type defined according to their out-edges */
enum eBBKind
{
ONE_BRANCH = 0, /* unconditional branch */
TWO_BRANCH = 1, /* conditional branch */
MULTI_BRANCH=2, /* case branch */
FALL_NODE=3, /* fall through */
RETURN_NODE=4, /* procedure/program return */
CALL_NODE=5, /* procedure call */
LOOP_NODE=6, /* loop instruction */
REP_NODE=7, /* repeat instruction */
INTERVAL_NODE=8, /* contains interval list */
#define ONE_BRANCH 0 /* unconditional branch */
#define TWO_BRANCH 1 /* conditional branch */
#define MULTI_BRANCH 2 /* case branch */
#define FALL_NODE 3 /* fall through */
#define RETURN_NODE 4 /* procedure/program return */
#define CALL_NODE 5 /* procedure call */
#define LOOP_NODE 6 /* loop instruction */
#define REP_NODE 7 /* repeat instruction */
#define INTERVAL_NODE 8 /* contains interval list */
TERMINATE_NODE=11, /* Exit to DOS */
NOWHERE_NODE=12 /* No outedges going anywhere */
};
#define TERMINATE_NODE 11 /* Exit to DOS */
#define NOWHERE_NODE 12 /* No outedges going anywhere */
/* Depth-first traversal constants */
enum eDFS
{
DFS_NONE,
DFS_DISP=1, /* Display graph pass */
DFS_MERGE=2, /* Merge nodes pass */
DFS_NUM=3, /* DFS numbering pass */
DFS_CASE=4, /* Case pass */
DFS_ALPHA=5, /* Alpha code generation*/
DFS_JMP=9 /* rmJMP pass - must be largest flag */
};
#define DFS_DISP 1 /* Display graph pass */
#define DFS_MERGE 2 /* Merge nodes pass */
#define DFS_NUM 3 /* DFS numbering pass */
#define DFS_CASE 4 /* Case pass */
#define DFS_ALPHA 5 /* Alpha code generation*/
#define DFS_JMP 9 /* rmJMP pass - must be largest flag */
/* Control flow analysis constants */
enum eNodeHeaderType
{
NO_TYPE=0, /* node is not a loop header*/
WHILE_TYPE=1, /* node is a while header */
REPEAT_TYPE=2, /* node is a repeat header */
ENDLESS_TYPE=3 /* endless loop header */
};
#define NO_TYPE 0 /* node is not a loop header*/
#define WHILE_TYPE 1 /* node is a while header */
#define REPEAT_TYPE 2 /* node is a repeat header */
#define ENDLESS_TYPE 3 /* endless loop header */
/* Uninitialized values for certain fields */
#define NO_NODE MAX /* node has no associated node */
@ -55,47 +43,90 @@ enum eNodeHeaderType
#define ELSE 1 /* else edge */
/* 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 */
struct BB;
/* Interval structure */
typedef std::list<BB *> queue;
struct interval
/* Interval structure */
typedef struct _queueNode {
struct _BB *node; /* Ptr to basic block */
struct _queueNode *next;
} queue;
typedef struct _intNode {
byte numInt; /* # of the interval */
byte numOutEdges; /* Number of out edges */
queue *nodes; /* Nodes of the interval*/
queue *currNode; /* Current node */
struct _intNode *next; /* Next interval */
} interval;
typedef union
{
uint8_t numInt; /* # of the interval */
uint8_t numOutEdges; /* Number of out edges */
queue nodes; /* Nodes of the interval*/
queue::iterator currNode; /* Current node */
interval *next; /* Next interval */
BB *firstOfInt();
interval()
{
numInt=numOutEdges=0;
currNode=nodes.end();
next=0;
}
};
dword ip; /* Out edge icode address */
struct _BB *BBptr; /* Out edge pointer to next BB */
interval *intPtr; /* Out edge ptr to next interval*/
} TYPEADR_TYPE;
/* Basic block (BB) node definition */
typedef struct _BB {
byte nodeType; /* Type of node */
Int traversed; /* Boolean: traversed yet? */
Int start; /* First instruction offset */
Int length; /* No. of instructions this BB */
Int numHlIcodes; /* No. of high-level icodes */
flags32 flg; /* BB flags */
/* In edges and out edges */
Int numInEdges; /* Number of in edges */
struct _BB **inEdges; /* Array of ptrs. to in edges */
Int numOutEdges; /* Number of out edges */
TYPEADR_TYPE *edges; /* Array of ptrs. to out edges */
/* For interval construction */
Int beenOnH; /* #times been on header list H */
Int inEdgeCount; /* #inEdges (to find intervals) */
struct _BB *reachingInt; /* Reaching interval header */
interval *inInterval; /* Node's interval */
/* For derived sequence construction */
interval *correspInt; /* Corresponding interval in
* derived graph Gi-1 */
/* For live register analysis
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
dword liveUse; /* LiveUse(b) */
dword def; /* Def(b) */
dword liveIn; /* LiveIn(b) */
dword liveOut; /* LiveOut(b) */
/* For structuring analysis */
Int dfsFirstNum; /* DFS #: first visit of node */
Int dfsLastNum; /* DFS #: last visit of node */
Int immedDom; /* Immediate dominator (dfsLast
* index) */
Int ifFollow; /* node that ends the if */
Int loopType; /* Type of loop (if any) */
Int latchNode; /* latching node of the loop */
Int numBackEdges; /* # of back edges */
Int loopHead; /* most nested loop head to which
* this node belongs (dfsLast) */
Int loopFollow; /* node that follows the loop */
Int caseHead; /* most nested case to which this
node belongs (dfsLast) */
Int caseTail; /* tail node for the case */
Int index; /* Index, used in several ways */
struct _BB *next; /* Next (list link) */
} BB;
typedef BB *PBB;
/* Derived Sequence structure */
struct derSeq_Entry
{
BB * Gi; /* Graph pointer */
interval * Ii; /* Interval list of Gi */
derSeq_Entry() : Gi(0),Ii(0)
{
}
~derSeq_Entry();
public:
void findIntervals(Function *c);
};
class derSeq : public std::list<derSeq_Entry>
{
public:
void display();
};
void freeDerivedSeq(derSeq &derivedG); /* reducible.c */
typedef struct _derivedNode {
BB *Gi; /* Graph pointer */
interval *Ii; /* Interval list of Gi */
struct _derivedNode *next; /* Next derived graph */
} derSeq;

View File

@ -6,8 +6,16 @@
/* High level icodes opcodes - def in file icode.h */
struct HLICODE
{
/*typedef enum {
HLI_ASSIGN,
INC,
DEC,
HLI_JCOND,
} hlIcode; */
typedef struct {
hlIcode opcode; /* hlIcode opcode */
union { /* different operands */
struct {
@ -17,4 +25,12 @@ struct HLICODE
COND_EXPR *exp; /* for HLI_JCOND, INC, DEC */
} oper; /* operand */
boolT valid; /* has a valid hlIcode */
};
} HLICODE;
typedef struct {
Int numIcodes; /* No. of hlIcode reocrds written */
Int numAlloc; /* No. of hlIcode records allocated */
HLICODE *hlIcode; /* Array of high-level icodes */
} HLICODEREC;

View File

@ -2,489 +2,367 @@
* I-code related definitions
* (C) Cristina Cifuentes
****************************************************************************/
#pragma once
#include <memory>
#include <vector>
#include <list>
#include <bitset>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <llvm/CodeGen/MachineInstr.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/Value.h>
#include <llvm/Instruction.h>
#include <boost/range.hpp>
#include "libdis.h"
#include "Enums.h"
/* LOW_LEVEL icode flags */
#define B 0x000001 /* Byte operands (value implicitly used) */
#define I 0x000002 /* Immed. source */
#define NOT_HLL 0x000004 /* Not HLL inst. */
#define FLOAT_OP 0x000008 /* ESC or WAIT */
#define SEG_IMMED 0x000010 /* Number is relocated segment value */
#define IMPURE 0x000020 /* Instruction modifies code */
#define WORD_OFF 0x000040 /* Inst has word offset ie.could be address */
#define TERMINATES 0x000080 /* Instruction terminates program */
#define CASE 0x000100 /* Label as case part of switch */
#define SWITCH 0x000200 /* Treat indirect JMP as switch stmt */
#define TARGET 0x000400 /* Jump target */
#define SYNTHETIC 0x000800 /* Synthetic jump instruction */
#define NO_LABEL 0x001000 /* Immed. jump cannot be linked to a label */
#define NO_CODE 0x002000 /* Hole in Icode array */
#define SYM_USE 0x004000 /* Instruction uses a symbol */
#define SYM_DEF 0x008000 /* Instruction defines a symbol */
#define NO_SRC 0x010000 /* Opcode takes no source */
#define NO_OPS 0x020000 /* Opcode takes no operands */
#define IM_OPS 0x040000 /* Opcode takes implicit operands */
#define SRC_B 0x080000 /* Source operand is byte (dest is word) */
#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */
#define HLL_LABEL 0x100000 /* Icode has a high level language label */
#define IM_DST 0x200000 /* Implicit DST for opcode (SIGNEX) */
#define IM_SRC 0x400000 /* Implicit SRC for opcode (dx:ax) */
#define IM_TMP_DST 0x800000 /* Implicit rTMP DST for opcode (DIV/IDIV) */
#define JMP_ICODE 0x1000000 /* Jmp dest immed.op converted to icode index */
#define JX_LOOP 0x2000000 /* Cond jump is part of loop conditional exp */
#define REST_STK 0x4000000 /* Stack needs to be restored after CALL */
/* Parser flags */
#define TO_REG 0x000100 /* rm is source */
#define S 0x000200 /* sign extend */
#define OP386 0x000400 /* 386 op-code */
#define NSP 0x000800 /* NOT_HLL if SP is src or dst */
#define ICODEMASK 0xFF00FF /* Masks off parser flags */
/* LOW_LEVEL icode, DU flag bits */
#define Cf 1
#define Sf 2
#define Zf 4
#define Df 8
/* Machine registers */
#define rAX 1 /* These are numbered relative to real 8086 */
#define rCX 2
#define rDX 3
#define rBX 4
#define rSP 5
#define rBP 6
#define rSI 7
#define rDI 8
#define rES 9
#define rCS 10
#define rSS 11
#define rDS 12
#define rAL 13
#define rCL 14
#define rDL 15
#define rBL 16
#define rAH 17
#define rCH 18
#define rDH 19
#define rBH 20
#define rTMP 21 /* temp register for DIV/IDIV/MOD */
#define INDEXBASE 22 /* Indexed modes go from INDEXBASE to
* INDEXBASE+7 */
/* Byte and Word registers */
static char *byteReg[9] = {"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh", "tmp" };
static char *wordReg[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
"si", "di", "es", "cs", "ss", "ds",
"", "", "", "", "", "", "", "", "tmp"};
#include "state.h" // State depends on INDEXBASE, but later need STATE
//enum condId;
/* Types of icodes */
typedef enum {
NOT_SCANNED = 0, /* not even scanned yet */
LOW_LEVEL, /* low-level icode */
HIGH_LEVEL /* high-level icode */
} icodeType;
struct LOCAL_ID;
struct BB;
struct Function;
struct STKFRAME;
struct CIcodeRec;
struct ICODE;
struct bundle;
typedef std::list<ICODE>::iterator iICODE;
typedef std::list<ICODE>::reverse_iterator riICODE;
typedef boost::iterator_range<iICODE> rCODE;
extern std::bitset<32> duReg[30];
/* uint8_t and uint16_t registers */
/* LOW_LEVEL icode opcodes */
typedef enum {
iCBW, /* 0 */
iAAA,
iAAD,
iAAM,
iAAS,
iADC,
iADD,
iAND,
iBOUND,
iCALL,
iCALLF, /* 10 */
iCLC,
iCLD,
iCLI,
iCMC,
iCMP,
iCMPS,
iREPNE_CMPS,
iREPE_CMPS,
iDAA,
iDAS, /* 20 */
iDEC,
iDIV,
iENTER,
iESC,
iHLT,
iIDIV,
iIMUL,
iIN,
iINC,
iINS, /* 30 */
iREP_INS,
iINT,
iIRET,
iJB,
iJBE,
iJAE,
iJA,
iJE,
iJNE,
iJL, /* 40 */
iJGE,
iJLE,
iJG,
iJS,
iJNS,
iJO,
iJNO,
iJP,
iJNP,
iJCXZ, /* 50 */
iJMP,
iJMPF,
iLAHF,
iLDS,
iLEA,
iLEAVE,
iLES,
iLOCK,
iLODS,
iREP_LODS, /* 60 */
iLOOP,
iLOOPE,
iLOOPNE,
iMOV, /* 64 */
iMOVS,
iREP_MOVS,
iMUL, /* 67 */
iNEG,
iNOT,
iOR, /* 70 */
iOUT,
iOUTS,
iREP_OUTS,
iPOP,
iPOPA,
iPOPF,
iPUSH,
iPUSHA,
iPUSHF,
iRCL, /* 80 */
iRCR,
iROL,
iROR,
iRET, /* 84 */
iRETF,
iSAHF,
iSAR,
iSHL,
iSHR,
iSBB, /* 90 */
iSCAS,
iREPNE_SCAS,
iREPE_SCAS,
iSIGNEX,
iSTC,
iSTD,
iSTI,
iSTOS,
iREP_STOS,
iSUB, /* 100 */
iTEST,
iWAIT,
iXCHG,
iXLAT,
iXOR,
iINTO,
iNOP,
iREPNE,
iREPE,
iMOD, /* 110 */
} llIcode;
/* HIGH_LEVEL icodes opcodes */
typedef enum {
HLI_ASSIGN, /* := */
HLI_CALL, /* Call procedure */
HLI_JCOND, /* Conditional jump */
HLI_RET, /* Return from procedure */
/* pseudo high-level icodes */
HLI_POP, /* Pop expression */
HLI_PUSH, /* Push expression */
} hlIcode;
/* Operand is defined, used or both flag */
typedef enum {
DEF, /* Operand is defined */
USE, /* Operand is used */
USE_DEF, /* Operand is used and defined */
NONE, /* No operation is required on this operand */
} operDu;
// I can't believe these are necessary!
#define E_DEF (operDu)DEF
#define E_USE (operDu)USE
#define E_NONE (operDu)NONE
#define E_USE_DEF (operDu)USE_DEF
/* Def/use of flags - low 4 bits represent flags */
struct DU
{
uint8_t d;
uint8_t u;
};
typedef struct {
byte d;
byte u;
} DU;
typedef DU *PDU;
/* Def/Use of registers and stack variables */
typedef struct {
dword def; /* For Registers: position in dword is reg index*/
dword lastDefRegi;/* Bit set if last def of this register in BB */
dword use; /* For Registers: position in dword is reg index*/
}DU_ICODE;
/* Definition-use chain for level 1 (within a basic block) */
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
#define MAX_REGS_DEF 2 /* 2 regs def'd for long-reg vars */
#define MAX_USES 5
typedef struct {
Int numRegsDef; /* # registers defined by this inst */
byte regi[MAX_REGS_DEF]; /* registers defined by this inst */
Int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
} DU1;
struct COND_EXPR;
struct HlTypeSupport
{
//hlIcode opcode; /* hlIcode opcode */
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
virtual std::string writeOut(Function *pProc, int *numLoc)=0;
protected:
void performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree);
};
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 */
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;
eReg seg; /* CS, DS, ES, SS */
eReg segOver; /* CS, DS, ES, SS if segment override */
int16_t segValue; /* Value of segment seg during analysis */
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
int16_t off; /* memory address offset */
uint32_t opz; /* idx of immed src op */
//union {/* Source operand if (flg & I) */
struct { /* Call & # actual arg bytes */
Function *proc; /* pointer to target proc (for CALL(F))*/
int cb; /* # actual arg bytes */
} proc;
LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0)
{
proc.proc=0;
proc.cb=0;
}
int64_t getImm2() const {return opz;}
void SetImmediateOp(uint32_t dw)
{
opz=dw;
}
eReg getReg2() {return regi;}
bool isReg() const;
static LLOperand CreateImm2(int64_t Val)
{
LLOperand Op;
//Op.Kind = kImmediate;
//Op.ImmVal = Val;
Op.opz = Val;
return Op;
}
static LLOperand CreateReg2(unsigned Val)
{
LLOperand Op;
// Op.Kind = kRegister;
// Op.RegVal = Reg;
Op.regi = (eReg)Val;
return Op;
}
void addProcInformation(int param_count,uint32_t call_conv);
};
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
hlIcode opcode; /* hlIcode opcode */
union { /* different operands */
struct { /* for HLI_ASSIGN */
COND_EXPR *lhs;
COND_EXPR *rhs;
} asgn;
COND_EXPR *exp; /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
struct { /* for HLI_CALL */
struct _proc *proc;
struct _STKFRAME *args; /* actual arguments */
} call;
} oper; /* operand */
} HLTYPE;
typedef struct
{
protected:
uint32_t flg; /* icode flags */
LLOperand m_src; /* source operand */
public:
int codeIdx; /* Index into cCode.code */
uint8_t numBytes; /* Number of bytes this instr */
uint32_t label; /* offset in image (20-bit adr) */
LLOperand dst; /* destination operand */
DU flagDU; /* def/use of flags */
int caseEntry;
std::vector<uint32_t> caseTbl2;
int hllLabNum; /* label # for hll codegen */
bool conditionalJump()
{
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ);
}
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
void setFlags(uint32_t flag) {flg |= flag;}
void clrFlags(uint32_t flag)
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
uint32_t getFlag() const {return flg;}
//llIcode getOpcode() const { return opcode; }
llIcode opcode; /* llIcode instruction */
byte numBytes; /* Number of bytes this instr */
flags32 flg; /* icode flags */
dword label; /* offset in image (20-bit adr) */
ICODEMEM dst; /* destination operand */
ICODEMEM src; /* source operand */
union { /* Source operand if (flg & I) */
dword op; /* idx of immed src op */
struct { /* Call & # actual arg bytes */
struct _proc *proc; /* ^ target proc (for CALL(F))*/
Int cb; /* # actual arg bytes */
} proc;
} immed;
DU flagDU; /* def/use of flags */
struct { /* Case table if op==JMP && !I */
Int numEntries; /* # entries in case table */
dword *entries; /* array of offsets */
} caseTbl;
Int hllLabNum; /* label # for hll codegen */
} LLTYPE;
uint32_t GetLlLabel() const { return label;}
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
bool match(llIcode op)
{
return (getOpcode()==op);
}
bool match(llIcode op,eReg dest)
{
return (getOpcode()==op)&&dst.regi==dest;
}
bool match(llIcode op,eReg dest,uint32_t flgs)
{
return (getOpcode()==op) and (dst.regi==dest) and testFlags(flgs);
}
bool match(llIcode op,eReg dest,eReg src_reg)
{
return (getOpcode()==op)&&(dst.regi==dest)&&(m_src.regi==src_reg);
}
bool match(eReg dest,eReg src_reg)
{
return (dst.regi==dest)&&(m_src.regi==src_reg);
}
bool match(eReg dest)
{
return (dst.regi==dest);
}
bool match(llIcode op,uint32_t flgs)
{
return (getOpcode()==op) and testFlags(flgs);
}
void set(llIcode op,uint32_t flags)
{
setOpcode(op);
flg =flags;
}
void emitGotoLabel(int indLevel);
void findJumpTargets(CIcodeRec &_pc);
void writeIntComment(std::ostringstream &s);
void dis1Line(int loc_ip, int pass);
std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false);
void flops(std::ostringstream &out);
bool isJmpInst();
HLTYPE toHighLevel(COND_EXPR *lhs, COND_EXPR *rhs, Function *func);
HLTYPE createCall();
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
{
setOpcode(0);
}
const LLOperand &src() const {return m_src;}
LLOperand &src() {return m_src;}
void replaceSrc(const LLOperand &with)
{
m_src = with;
}
void replaceSrc(eReg r)
{
m_src = LLOperand::CreateReg2(r);
}
void replaceSrc(int64_t r)
{
m_src = LLOperand::CreateImm2(r);
}
void replaceDst(const LLOperand &with)
{
dst = with;
}
void replaceDst(eReg r)
{
dst = LLOperand::CreateReg2(r);
}
ICODE *m_link;
condId idType(opLoc sd) const;
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &dst; }
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &dst; }
};
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
struct ICODE
{
// use llvm names at least
typedef BB MachineBasicBlock;
protected:
LLInst m_ll;
HLTYPE m_hl;
MachineBasicBlock * Parent; /* BB to which this icode belongs */
bool invalid; /* Has no HIGH_LEVEL equivalent */
public:
x86_insn_t insn;
template<int FLAG>
struct FlagFilter
{
bool operator()(ICODE *ic) {return ic->ll()->testFlags(FLAG);}
bool operator()(ICODE &ic) {return ic.ll()->testFlags(FLAG);}
};
template<int TYPE>
struct TypeFilter
{
bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;}
bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;}
};
template<int TYPE>
struct TypeAndValidFilter
{
bool operator()(ICODE *ic) {return (ic->type==HIGH_LEVEL)&&(ic->valid());}
bool operator()(ICODE &ic) {return (ic.type==HIGH_LEVEL)&&ic.valid();}
};
static TypeFilter<HIGH_LEVEL> select_high_level;
static TypeAndValidFilter<HIGH_LEVEL> select_valid_high_level;
/* Def/Use of registers and stack variables */
struct DU_ICODE
{
DU_ICODE()
{
def.reset();
use.reset();
lastDefRegi.reset();
}
std::bitset<32> def; // For Registers: position in bitset is reg index
std::bitset<32> use; // For Registers: position in uint32_t is reg index
std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB
void addDefinedAndUsed(eReg r)
{
def |= duReg[r];
use |= duReg[r];
typedef struct {
icodeType type; /* Icode type */
boolT invalid; /* Has no HIGH_LEVEL equivalent */
struct _BB *inBB; /* BB to which this icode belongs */
DU_ICODE du; /* Def/use regs/vars */
DU1 du1; /* du chain 1 */
Int codeIdx; /* Index into cCode.code */
struct { /* Different types of icodes */
LLTYPE ll;
HLTYPE hl; /* For HIGH_LEVEL icodes */
} ic; /* intermediate code */
} ICODE;
typedef ICODE* PICODE;
}
};
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.
class CIcodeRec : public std::list<ICODE>
// The bulk of this could well be done with a class library
class CIcodeRec
{
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);
};

View File

@ -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();
};

View File

@ -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();
};

View File

@ -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();
};

View File

@ -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;
}
};

View File

@ -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();}
};

View File

@ -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();
};

View File

@ -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();
};

View File

@ -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();
};

View File

@ -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();
};

View File

@ -5,134 +5,106 @@
* (C) Cristina Cifuentes
*/
#pragma once
#include <stdint.h>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include "types.h"
#include "Enums.h"
#include "machine_x86.h"
/* Type definition */
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
// TODO: why ?
struct COND_EXPR;
struct ICODE;
struct LLInst;
typedef std::list<ICODE>::iterator iICODE;
struct IDX_ARRAY : public std::vector<iICODE>
{
bool inList(iICODE idx)
{
return std::find(begin(),end(),idx)!=end();
}
};
typedef struct {
Int csym; /* # symbols used */
Int alloc; /* # symbols allocated */
Int *idx; /* Array of integer indexes */
} IDX_ARRAY;
/* Type definitions used in the decompiled program */
typedef enum {
TYPE_UNKNOWN = 0, /* unknown so far */
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
TYPE_BYTE_UNSIGN, /* unsigned byte */
TYPE_WORD_SIGN, /* signed word (16 bits) */
TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */
TYPE_LONG_SIGN, /* signed long (32 bits) */
TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */
TYPE_RECORD, /* record structure */
TYPE_PTR, /* pointer (32 bit ptr) */
TYPE_STR, /* string */
TYPE_CONST, /* constant (any type) */
TYPE_FLOAT, /* floating point */
TYPE_DOUBLE, /* double precision float */
} hlType;
static char *hlTypes[13] = {"", "char", "unsigned char", "int", "unsigned int",
"long", "unsigned long", "record", "int *", "char *",
"", "float", "double"};
typedef enum
{
STK_FRAME, /* For stack vars */
REG_FRAME, /* For register variables */
GLB_FRAME /* For globals */
STK_FRAME, /* For stack vars */
REG_FRAME, /* For register variables */
GLB_FRAME, /* For globals */
} frameType;
/* Enumeration to determine whether pIcode points to the high or low part
* of a long number */
typedef enum {
HIGH_FIRST, /* High value is first */
LOW_FIRST, /* Low value is first */
} hlFirst;
typedef struct
{
int16_t seg; /* segment value */
int16_t off; /* offset */
eReg regi; /* optional indexed register */
int16 seg; /* segment value */
int16 off; /* offset */
byte regi; /* optional indexed register */
} BWGLB_TYPE;
typedef struct
{ /* For TYPE_LONG_(UN)SIGN on the stack */
int offH; /* high offset from BP */
int offL; /* low offset from BP */
Int offH; /* high offset from BP */
Int offL; /* low offset from BP */
} LONG_STKID_TYPE;
struct LONGID_TYPE
typedef struct
{ /* For TYPE_LONG_(UN)SIGN registers */
eReg h; /* high register */
eReg l; /* low register */
bool srcDstRegMatch(iICODE a,iICODE b) const;
};
byte h; /* high register */
byte l; /* low register */
} LONGID_TYPE;
/* ID, LOCAL_ID */
struct ID
{
hlType type; /* Probable type */
bool illegal; /* Boolean: not a valid field any more */
//std::vector<iICODE> idx;
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
frameType loc; /* Frame location */
bool hasMacro; /* Identifier requires a macro */
char macro[10]; /* Macro for this identifier */
std::string name; /* Identifier's name */
union { /* Different types of identifiers */
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
uint8_t regOff; /* register offset (if any) */
int off; /* offset from BP */
} bwId;
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
struct { /* For TYPE_LONG_(UN)SIGN globals */
int16_t seg; /* segment value */
int16_t offH; /* offset high */
int16_t offL; /* offset low */
uint8_t regi; /* optional indexed register */
} longGlb;
struct { /* For TYPE_LONG_(UN)SIGN constants */
uint32_t h; /* high uint16_t */
uint32_t l; /* low uint16_t */
} longKte;
} id;
ID();
ID(hlType t, frameType f);
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);}
uint16_t typeBitsize() const
{
return TypeContainer::typeSize(type)*8;
}
void setLocalName(int i)
{
char buf[32];
sprintf (buf, "loc%ld", i);
name=buf;
}
};
typedef struct {
hlType type; /* Probable type */
boolT illegal;/* Boolean: not a valid field any more */
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
frameType loc; /* Frame location */
boolT hasMacro;/* Identifier requires a macro */
char macro[10];/* Macro for this identifier */
char name[20];/* Identifier's name */
union { /* Different types of identifiers */
byte regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
byte regOff; /* register offset (if any) */
Int off; /* offset from BP */
} bwId;
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(WORD)_(UN)SIGN globals */
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
LONG_STKID_TYPE longStkId;/* For TYPE_LONG_(UN)SIGN on the stack */
struct { /* For TYPE_LONG_(UN)SIGN globals */
int16 seg; /* segment value */
int16 offH; /* offset high */
int16 offL; /* offset low */
byte regi; /* optional indexed register */
} longGlb;
struct { /* For TYPE_LONG_(UN)SIGN constants */
dword h; /* high word */
dword l; /* low word */
} longKte;
} id;
} ID;
struct LOCAL_ID
{
std::vector<ID> id_arr;
protected:
int newLongIdx(int16_t seg, int16_t offH, int16_t offL, uint8_t regi, hlType t);
int newLongGlb(int16_t seg, int16_t offH, int16_t offL, hlType t);
int newLongStk(hlType t, int offH, int offL);
public:
LOCAL_ID()
{
id_arr.reserve(256);
}
// interface to allow range based iteration
std::vector<ID>::iterator begin() {return id_arr.begin();}
std::vector<ID>::iterator end() {return id_arr.end();}
int newByteWordReg(hlType t, eReg regi);
int newByteWordStk(hlType t, int off, uint8_t regOff);
int newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t);
int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_);
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, int off);
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
void newIdent(hlType t, frameType f);
void flagByteWordId(int off);
void propLongId(uint8_t regL, uint8_t regH, const char *name);
size_t csym() const {return id_arr.size();}
void newRegArg(iICODE picode, iICODE ticode) const;
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const;
void forwardSubs(COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const;
COND_EXPR *createId(const ID *retVal, iICODE ix_);
};
typedef struct {
Int csym; /* No. of symbols in the table */
Int alloc; /* No. of symbols allocated */
ID *id; /* Identifier */
} LOCAL_ID;

View File

@ -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 &regName(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> &regi)
{
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);
};

View File

@ -1,41 +1,34 @@
#pragma once
/* Perfect hashing function library. Contains functions to generate perfect
hashing functions
* (C) Mike van Emmerik
*/
//#define bool unsigned char
#define uint8_t unsigned char
#define uint16_t unsigned short
#define TRUE 1
#define FALSE 0
#define bool unsigned char
#define byte unsigned char
#define word unsigned short
/* Prototypes */
void hashParams(int NumEntry, int EntryLen, int SetSize, char SetMin,
int NumVert); /* Set the parameters for the hash table */
void hashCleanup(void); /* Frees memory allocated by hashParams() */
void map(void); /* Part 1 of creating the tables */
void assign(void); /* Part 2 of creating the tables */
int hash(byte *s); /* Hash the string to an int 0 .. NUMENTRY-1 */
word *readT1(void); /* Returns a pointer to the T1 table */
word *readT2(void); /* Returns a pointer to the T2 table */
word *readG(void); /* Returns a pointer to the g table */
/* The application must provide these functions: */
void getKey(int i, uint8_t **pKeys);/* Set *keys to point to the i+1th key */
void getKey(int i, byte **pKeys);/* Set *keys to point to the i+1th key */
void dispKey(int i); /* Display the key */
class PatternHasher
{
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
int NumEntry; /* Number of entries in the hash table (# keys) */
int EntryLen; /* Size (bytes) of each entry (size of keys) */
int SetSize; /* Size of the char set */
char SetMin; /* First char in the set */
int NumVert; /* c times NumEntry */
int *graphNode; /* The array of edges */
int *graphNext; /* Linked list of edges */
int *graphFirst;/* First edge at a vertex */
public:
uint16_t *readT1(void); /* Returns a pointer to the T1 table */
uint16_t *readT2(void); /* Returns a pointer to the T2 table */
uint16_t *readG(void); /* Returns a pointer to the g table */
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
void cleanup();
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
};
extern PatternHasher g_pattern_hasher;
/* Macro reads a LH uint16_t from the image regardless of host convention */
/* Macro reads a LH word from the image regardless of host convention */
#ifndef LH
#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
#endif

View File

@ -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;

View File

@ -1,12 +1,38 @@
#pragma once
/* Scanner functions
* (C) Cristina Cifuentes, Jeff Ledermann
*/
#include <stdint.h>
#include "error.h"
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
#define REG(x) ((uint8_t)(x & 0x38) >> 3)
struct ICODE;
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
extern eErrorId scan(uint32_t ip, ICODE &p);
static void rm(Int i);
static void modrm(Int i);
static void segrm(Int i);
static void data1(Int i);
static void data2(Int i);
static void regop(Int i);
static void segop(Int i);
static void strop(Int i);
static void escop(Int i);
static void axImp(Int i);
static void alImp(Int i);
static void axSrcIm(Int i);
static void memImp(Int i);
static void memReg0(Int i);
static void memOnly(Int i);
static void dispM(Int i);
static void dispS(Int i);
static void dispN(Int i);
static void dispF(Int i);
static void prefix(Int i);
static void immed(Int i);
static void shift(Int i);
static void arith(Int i);
static void trans(Int i);
static void const1(Int i);
static void const3(Int i);
static void none1(Int i);
static void none2(Int i);
static void checkInt(Int i);
/* Extracts reg bits from middle of mod-reg-rm byte */
#define REG(x) ((byte)(x & 0x38) >> 3)

View File

@ -2,34 +2,18 @@
* dcc project header
* (C) Cristina Cifuentes, Mike van Emmerik
****************************************************************************/
#pragma once
#include <stdint.h>
#include <cstring>
#include "machine_x86.h"
/* STATE TABLE */
struct STATE
typedef struct
{
uint32_t IP; /* Offset into Image */
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
dword IP; /* Offset into Image */
int16 r[INDEXBASE]; /* Value of segs and AX */
byte f[INDEXBASE]; /* True if r[.] has a value */
struct
{ /* For case stmt indexed reg */
uint8_t regi; /* Last conditional jump */
int16_t immed; /* Contents of the previous register */
{ /* For case stmt indexed reg */
byte regi; /* Last conditional jump */
int16 immed; /* Contents of the previous register */
} JCond;
void setState(uint16_t reg, int16_t value);
void checkStartup();
bool isKnown(eReg v) {return f[v];}
void kill(eReg v) { f[v]=false;}
STATE() : IP(0)
{
JCond.regi=0;
JCond.immed=0;
memset(r,0,sizeof(int16_t)*INDEX_BX_SI); //TODO: move this to machine_x86
memset(f,0,sizeof(uint8_t)*INDEX_BX_SI);
}
};
} STATE;
typedef STATE *PSTATE;

View File

@ -2,112 +2,42 @@
* Symbol table prototypes
* (C) Mike van Emmerik
*/
#pragma once
#include <string>
#include <stdint.h>
#include "Enums.h"
#include "types.h"
struct COND_EXPR;
struct TypeContainer;
/* * * * * * * * * * * * * * * * * */
/* Symbol table structs and protos */
/* * * * * * * * * * * * * * * * * */
struct SymbolCommon
{
std::string name; /* New name for this variable/symbol/argument */
int size; /* Size/maximum size */
hlType type; /* probable type */
eDuVal duVal; /* DEF, USE, VAL */
SymbolCommon() : size(0),type(TYPE_UNKNOWN)
{}
};
struct SYM : public SymbolCommon
{
SYM() : label(0),flg(0)
{
}
int32_t label; /* physical address (20 bit) */
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
};
/* STACK FRAME */
struct STKSYM : public SymbolCommon
typedef struct
{
COND_EXPR *actual; /* Expression tree of actual parameter */
COND_EXPR *regs; /* For register arguments only */
int16_t label; /* Immediate off from BP (+:args, -:params) */
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
bool hasMacro; /* This type needs a macro */
std::string macro; /* Macro name */
bool invalid; /* Boolean: invalid entry in formal arg list*/
STKSYM()
{
actual=regs=0;
label=0;
regOff=0;
invalid=hasMacro = false;
}
void setArgName(int i)
{
char buf[32];
sprintf (buf, "arg%d", i);
name = buf;
}
};
template<class T>
class SymbolTableCommon : public std::vector<T>
{
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
iterator findByLabel(int lab)
{
auto iter = std::find_if(this->begin(),this->end(),
[lab](T &s)->bool {return s.label==lab;});
return iter;
}
const_iterator findByLabel(int lab) const
{
auto iter = std::find_if(this->begin(),this->end(),
[lab](const T &s)->bool {return s.label==lab;});
return iter;
}
char *pSymName; /* Ptr to symbolic name or comment */
dword symOff; /* Symbol image offset */
PPROC symProc; /* Procedure pointer */
word preHash; /* Hash value before the modulo */
word postHash; /* Hash value after the modulo */
word nextOvf; /* Next entry this hash bucket, or -1 */
word prevOvf; /* Back link in Ovf chain */
} SYMTABLE;
};
/* SYMBOL TABLE */
class SYMTAB : public SymbolTableCommon<SYM>
{
public:
void updateSymType(uint32_t symbol, const TypeContainer &tc);
SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new);
};
struct Function;
struct SYMTABLE
{
std::string pSymName; /* Ptr to symbolic name or comment */
uint32_t symOff; /* Symbol image offset */
Function *symProc; /* Procedure pointer */
SYMTABLE() : symOff(0),symProc(0) {}
SYMTABLE(uint32_t _sym,Function *_proc) : symOff(_sym),symProc(_proc)
{}
bool operator == (const SYMTABLE &other) const
{
// does not yse pSymName, to ease finding by symOff/symProc combo
// in map<SYMTABLE,X>
return (symOff==other.symOff) && symProc==(other.symProc);
}
};
enum tableType /* The table types */
enum _tableType /* The table types */
{
Label=0, /* The label table */
Comment, /* The comment table */
NUM_TABLE_TYPES /* Number of entries: must be last */
};
typedef enum _tableType tableType; /* For convenience */
void createSymTables(void);
void destroySymTables(void);
boolT readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc);
void enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo);
boolT readSym (char *symName, dword *pSymOff, PPROC *pSymProc);
boolT readVal (char *symName, dword symOff, PPROC symProc);
void deleteSym(char *symName);
void deleteVal(dword symOff, PPROC symProc, boolT bSymToo);
boolT findVal(dword symOff, PPROC symProc, word *pIndex);
word symHash(char *name, word *pre);
word valHash(dword off, PPROC proc, word *pre);
void selectTable(tableType); /* Select a particular table */
char *addStrTbl(char *pStr); /* Add string to string table */

View File

@ -2,12 +2,19 @@
* dcc project general header
* (C) Cristina Cifuentes, Mike van Emmerik
****************************************************************************/
#pragma once
#include <cassert>
#include <stdint.h>
#include "Enums.h"
/**** Common definitions and macros ****/
#ifdef __MSDOS__ /* Intel: 16 bit integer */
typedef long Int; /* Int: 0x80000000..0x7FFFFFFF */
typedef unsigned long flags32; /* 32 bits */
typedef unsigned long dword; /* 32 bits */
#define MAX 0x7FFFFFFF
#else /* Unix: 32 bit integer */
typedef int Int; /* Int: 0x80000000..0x7FFFFFFF */
typedef unsigned int flags32; /* 32 bits */
typedef unsigned int dword; /* 32 bits */
#define MAX 0x7FFFFFFF
#endif
/* Type definitions used in the program */
typedef unsigned char byte; /* 8 bits */
@ -15,6 +22,14 @@ typedef unsigned short word;/* 16 bits */
typedef short int16; /* 16 bits */
typedef unsigned char boolT; /* 8 bits */
#if defined(__MSDOS__) | defined(WIN32)
#define unlink _unlink // Compiler is picky about non Ansi names
#endif
#define TRUE 1
#define FALSE 0
#define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */
/* These are for C library signature detection */
@ -24,15 +39,17 @@ typedef unsigned char boolT; /* 8 bits */
/****** MACROS *******/
/* Macro to allocate a node of size sizeof(structType). */
#define allocStruc(structType) (structType *)allocMem(sizeof(structType))
/* Macro reads a LH word from the image regardless of host convention */
/* Returns a 16 bit quantity, e.g. C000 is read into an Int as C000 */
//#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
#define LH(p) ((word)((byte *)(p))[0] + ((word)((byte *)(p))[1] << 8))
/* Macro reads a LH word from the image regardless of host convention */
/* Returns a signed quantity, e.g. C000 is read into an Int as FFFFC000 */
#define LH_SIGNED(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
#define LHS(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
/* Macro tests bit b for type t in prog.map */
#define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1)))
@ -40,68 +57,3 @@ typedef unsigned char boolT; /* 8 bits */
/* Macro to convert a segment, offset definition into a 20 bit address */
#define opAdr(seg,off) ((seg << 4) + off)
/* duVal FLAGS */
struct eDuVal
{
eDuVal()
{
def=use=val=0;
}
enum flgs
{
DEF=1,
USE=2,
VAL=4
};
int def :1; /* Variable was first defined than used */
int use :1; /* Variable was first used than defined */
int val :1; /* Variable has an initial value. 2 cases:
* 1. When variable is used first (ie. global)
* 2. When a value is moved into the variable
* for the first time. */
void setFlags(uint16_t x)
{
def = x&DEF;
use = x&USE;
val = x&VAL;
}
bool isUSE_VAL() {return use&&val;} /* Use and Val */
};
static constexpr const char * hlTypes[13] = {
"", "char", "unsigned char", "int", "unsigned int",
"long", "unsigned long", "record", "int *", "char *",
"", "float", "double"
};
struct TypeContainer
{
hlType m_type;
size_t m_size;
TypeContainer(hlType t,size_t sz) : m_type(t),m_size(sz)
{
}
static size_t typeSize(hlType t)
{
switch(t)
{
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
return 2;
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
return 1;
}
return 0;
}
static hlType defaultTypeForSize(size_t x)
{
/* Type of the symbol according to the number of bytes it uses */
static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN,
TYPE_UNKNOWN, TYPE_LONG_SIGN};
assert(x < sizeof(cbType)/sizeof(hlType));
return cbType[x];
}
static constexpr const char *typeName(hlType t)
{
return hlTypes[t];
}
};

BIN
prototypes/dcclibs.dat Normal file

Binary file not shown.

BIN
sigs/dccb2s.sig Normal file

Binary file not shown.

View File

@ -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() );
}

View File

@ -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)

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -4,40 +4,47 @@
* Purpose: Back-end module. Generates C code for each procedure.
* (C) Cristina Cifuentes
****************************************************************************/
#include <cassert>
#include <string>
#include "dcc.h"
#include "disassem.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string.h>
#include <stdio.h>
#include "project.h"
bundle cCode; /* Procedure declaration and code */
using namespace std;
/* Returns a unique index to the next label */
int getNextLabel()
bundle cCode; /* Procedure declaration and code */
/* Indentation buffer */
#define indSize 81 /* size of the indentation buffer. Each indentation
* is of 4 spaces => max. 20 indentation levels */
static char indentBuf[indSize] =
" ";
static char *indent (Int indLevel)
/* Indentation according to the depth of the statement */
{
static int labelIdx = 1; /* index of the next label */
return (labelIdx++);
return (&indentBuf[indSize-(indLevel*4)-1]);
}
static Int getNextLabel()
/* Returns a unique index to the next label */
{ static Int labelIdx = 1; /* index of the next label */
return (labelIdx++);
}
static void displayStats (PPROC pProc)
/* displays statistics on the subroutine */
void Function::displayStats ()
{
printf("\nStatistics - Subroutine %s\n", name.c_str());
printf ("Number of Icode instructions:\n");
printf (" Low-level : %4d\n", stats.numLLIcode);
if (! (flg & PROC_ASM))
{
printf (" High-level: %4d\n", stats.numHLIcode);
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
100.0) / stats.numLLIcode);
}
printf("\nStatistics - Subroutine %s\n", pProc->name);
printf ("Number of Icode instructions:\n");
printf (" Low-level : %4d\n", stats.numLLIcode);
if (! (pProc->flg & PROC_ASM))
{
printf (" High-level: %4d\n", stats.numHLIcode);
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
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
* icode for the node (pProc->Icode). The procedure is done in sequential
* order of dsfLast numbering. */
{ int i; /* index into the dfsLast array */
PBB *dfsLast; /* pointer to the dfsLast array */
{ Int i; /* index into the dfsLast array */
PBB *dfsLast; /* pointer to the dfsLast array */
dfsLast = pProc->dfsLast;
for (i = 0; i < pProc->numBBs; i++)
if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) {
pProc->Icode.icode[dfsLast[i]->start].ll()->flg |= HLL_LABEL;
pProc->Icode.icode[dfsLast[i]->start].ll()->hllLabNum = getNextLabel();
}
dfsLast = pProc->dfsLast;
for (i = 0; i < pProc->numBBs; i++)
if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) {
pProc->Icode.icode[dfsLast[i]->start].ic.ll.flg |= HLL_LABEL;
pProc->Icode.icode[dfsLast[i]->start].ic.ll.hllLabNum = getNextLabel();
}
}
#endif
char *cChar (byte c)
/* Returns the corresponding C string for the given character c. Character
* constants such as carriage return and line feed, require 2 C characters. */
char *cChar (uint8_t c)
{
static char res[3];
{ static char res[3];
switch (c) {
case 0x8: /* backspace */
sprintf (res, "\\b");
break;
case 0x9: /* horizontal tab */
sprintf (res, "\\t");
break;
case 0x0A: /* new line */
sprintf (res, "\\n");
break;
case 0x0C: /* form feed */
sprintf (res, "\\f");
break;
case 0x0D: /* carriage return */
sprintf (res, "\\r");
break;
default: /* any other character*/
sprintf (res, "%c", c);
}
return (res);
switch (c) {
case 0x8: /* backspace */
sprintf (res, "\\b");
break;
case 0x9: /* horizontal tab */
sprintf (res, "\\t");
break;
case 0x0A: /* new line */
sprintf (res, "\\n");
break;
case 0x0C: /* form feed */
sprintf (res, "\\f");
break;
case 0x0D: /* carriage return */
sprintf (res, "\\r");
break;
default: /* any other character*/
sprintf (res, "%c", c);
}
return (res);
}
static void printGlobVar (PSYM psym)
/* Prints the variable's name and initial contents on the file.
* Note: to get to the value of the variable:
* com file: prog.Image[operand]
* exe file: prog.Image[operand+0x100] */
static void printGlobVar (std::ostream &ostr,SYM * psym)
{
int j;
PROG &prog(Project::get()->prog);
uint32_t relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
{ Int j;
dword relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
char *strContents; /* initial contents of variable */
switch (psym->size)
{
case 1:
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.Image[relocOp]<<";\n";
break;
case 2:
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
break;
case 4: if (psym->type == TYPE_PTR) /* pointer */
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
else /* char */
ostr << "char\t"<<psym->name<<"[4] = \""<<
prog.Image[relocOp]<<prog.Image[relocOp+1]<<
prog.Image[relocOp+2]<<prog.Image[relocOp+3]<<";\n";
break;
default:
{
ostringstream strContents;
for (j=0; j < psym->size; j++)
strContents << cChar(prog.Image[relocOp + j]);
ostr << "char\t*"<<psym->name<<" = \""<<strContents.str()<<"\";\n";
}
}
switch (psym->size) {
case 1: appendStrTab (&cCode.decl, "byte\t%s = %ld;\n",
psym->name, prog.Image[relocOp]);
break;
case 2: appendStrTab (&cCode.decl, "word\t%s = %ld;\n",
psym->name, LH(prog.Image+relocOp));
break;
case 4: if (psym->type == TYPE_PTR) /* pointer */
appendStrTab (&cCode.decl, "word\t*%s = %ld;\n",
psym->name, LH(prog.Image+relocOp));
else /* char */
appendStrTab (&cCode.decl,
"char\t%s[4] = \"%c%c%c%c\";\n",
psym->name, prog.Image[relocOp],
prog.Image[relocOp+1], prog.Image[relocOp+2],
prog.Image[relocOp+3]);
break;
default:strContents = (char *)allocMem((psym->size*2+1) *sizeof(char));
strContents[0] = '\0';
for (j=0; j < psym->size; j++)
strcat (strContents, cChar(prog.Image[relocOp + j]));
appendStrTab (&cCode.decl, "char\t*%s = \"%s\";\n",
psym->name, strContents);
}
}
// Note: Not called at present.
static void writeGlobSymTable()
/* Writes the contents of the symbol table, along with any variable
* initialization. */
void Project::writeGlobSymTable()
{
std::ostringstream ostr;
{ Int idx;
char type[10];
PSYM pSym;
if (symtab.empty())
return;
ostr<<"/* Global variables */\n";
for (SYM &sym : symtab)
{
if (sym.duVal.isUSE_VAL()) /* first used */
printGlobVar (ostr,&sym);
else { /* first defined */
switch (sym.size) {
case 1: ostr<<"uint8_t\t"; break;
case 2: ostr<<"int\t"; break;
case 4: if (sym.type == TYPE_PTR)
ostr<<"int\t*";
else
ostr<<"char\t*";
break;
default: ostr<<"char\t*";
}
ostr<<sym.name<<";\t/* size = "<<sym.size<<" */\n";
}
}
ostr<< "\n";
cCode.appendDecl( ostr.str() );
if (symtab.csym)
{
appendStrTab (&cCode.decl, "/* Global variables */\n");
for (idx = 0; idx < symtab.csym; idx++)
{
pSym = &symtab.sym[idx];
if (symtab.sym[idx].duVal & USEVAL) /* first used */
printGlobVar (&(symtab.sym[idx]));
else { /* first defined */
switch (pSym->size) {
case 1: strcpy (type, "byte\t"); break;
case 2: strcpy (type, "int\t"); break;
case 4: if (pSym->type == TYPE_PTR)
strcpy (type, "int\t*");
else
strcpy (type, "char\t*");
break;
default: strcpy (type, "char\t*");
}
appendStrTab (&cCode.decl, "%s%s;\t/* size = %ld */\n",
type, pSym->name, pSym->size);
}
}
appendStrTab (&cCode.decl, "\n");
}
}
static void writeHeader (FILE *fp, char *fileName)
/* Writes the header information and global variables to the output C file
* fp. */
static void writeHeader (std::ostream &_ios, char *fileName)
{
PROG &prog(Project::get()->prog);
/* Write header information */
cCode.init();
cCode.appendDecl( "/*\n");
cCode.appendDecl( " * Input file\t: %s\n", fileName);
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
/* Write header information */
newBundle (&cCode);
appendStrTab (&cCode.decl, "/*\n");
appendStrTab (&cCode.decl, " * Input file\t: %s\n", fileName);
appendStrTab (&cCode.decl, " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
appendStrTab (&cCode.decl, " */\n\n#include \"dcc.h\"\n\n");
/* Write global symbol table */
/** writeGlobSymTable(); *** need to change them into locident fmt ***/
writeBundle (_ios, cCode);
freeBundle (&cCode);
/* Write global symbol table */
/** writeGlobSymTable(); *** need to change them into locident fmt ***/
writeBundle (fp, cCode);
freeBundle (&cCode);
}
static void writeBitVector (dword regi)
/* Writes the registers that are set in the bitvector */
{ Int j;
for (j = 0; j < INDEXBASE; j++)
{
if ((regi & power2(j)) != 0)
printf ("%s ", allRegs[j]);
}
}
static void emitGotoLabel (PICODE pt, Int indLevel)
/* Checks the given icode to determine whether it has a label associated
* to it. If so, a goto is emitted to this label; otherwise, a new label
* is created and a goto is also emitted.
* Note: this procedure is to be used when the label is to be backpatched
* onto code in cCode.code */
{
if (! (pt->ic.ll.flg & HLL_LABEL)) /* node hasn't got a lab */
{
/* Generate new label */
pt->ic.ll.hllLabNum = getNextLabel();
pt->ic.ll.flg |= HLL_LABEL;
/* Node has been traversed already, so backpatch this label into
* the code */
addLabelBundle (&cCode.code, pt->codeIdx, pt->ic.ll.hllLabNum);
}
appendStrTab (&cCode.code, "%sgoto L%ld;\n", indent(indLevel),
pt->ic.ll.hllLabNum);
stats.numHLIcode++;
}
// Note: Not currently called!
static void emitFwdGotoLabel (PICODE pt, Int indLevel)
/* Checks the given icode to determine whether it has a label associated
* to it. If so, a goto is emitted to this label; otherwise, a new label
* is created and a goto is also emitted.
* Note: this procedure is to be used when the label is to be forward on
* the code; that is, the target code has not been traversed yet. */
static void emitFwdGotoLabel (ICODE * pt, int indLevel)
{
if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */
{
/* Generate new label */
pt->ll()->hllLabNum = getNextLabel();
pt->ll()->setFlags(HLL_LABEL);
}
cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum);
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;
}
appendStrTab (&cCode.code, "%sgoto l%ld;\n", indent(indLevel),
pt->ic.ll.hllLabNum);
}
static void writeBB (PBB pBB, PICODE hli, Int lev, PPROC pProc, Int *numLoc)
/* Writes the code for the current basic block.
* Args: pBB: pointer to the current basic block.
* Icode: pointer to the array of icodes for current procedure.
* lev: indentation level - used for formatting. */
{ Int i, last;
char *line; /* Pointer to the HIGH-LEVEL line */
/* Save the index into the code table in case there is a later goto
* into this instruction (first instruction of the BB) */
hli[pBB->start].codeIdx = nextBundleIdx (&cCode.code);
/* Generate code for each hlicode that is not a HLI_JCOND */
for (i = pBB->start, last = i + pBB->length; i < last; i++)
if ((hli[i].type == HIGH_LEVEL) && (hli[i].invalid == FALSE))
{
line = write1HlIcode (hli[i].ic.hl, pProc, numLoc);
if (line[0] != '\0')
{
appendStrTab (&cCode.code, "%s%s", indent(lev), line);
stats.numHLIcode++;
}
if (option.verbose)
writeDU (&hli[i], i);
}
//if (hli[i].invalid)
//printf("Invalid icode: %d!\n", hli[i].invalid);
}
static void writeCode (PBB pBB, Int indLevel, PPROC pProc , Int *numLoc,
Int latchNode, Int ifFollow)
/* Recursive procedure that writes the code for the given procedure, pointed
* to by pBB.
* Parameters: pBB: pointer to the cfg.
* Icode: pointer to the Icode array for the cfg graph of the
* current procedure.
* indLevel: indentation level - used for formatting.
* numLoc: last # assigned to local variables */
{
Int follow, /* ifFollow */
loopType, /* Type of loop, if any */
nodeType; /* Type of node */
PBB succ, latch; /* Successor and latching node */
PICODE picode; /* Pointer to HLI_JCOND instruction */
char *l; /* Pointer to HLI_JCOND expression */
boolT emptyThen, /* THEN clause is empty */
repCond; /* Repeat condition for while() */
/* Check if this basic block should be analysed */
if (!pBB) return;
if ((ifFollow != UN_INIT) && (pBB == pProc->dfsLast[ifFollow]))
return;
if (pBB->traversed == DFS_ALPHA)
return;
pBB->traversed = DFS_ALPHA;
/* Check for start of loop */
repCond = FALSE;
latch = NULL;
loopType = pBB->loopType;
if (loopType)
{
latch = pProc->dfsLast[pBB->latchNode];
switch (loopType) {
case WHILE_TYPE:
picode = pProc->Icode.GetIcode(pBB->start + pBB->length - 1);
/* Check for error in while condition */
if (picode->ic.hl.opcode != HLI_JCOND)
reportError (WHILE_FAIL);
/* Check if condition is more than 1 HL instruction */
if (pBB->numHlIcodes > 1)
{
/* Write the code for this basic block */
writeBB(pBB, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
repCond = TRUE;
}
/* Condition needs to be inverted if the loop body is along
* the THEN path of the header node */
if (pBB->edges[ELSE].BBptr->dfsLastNum == pBB->loopFollow)
inverseCondOp (&picode->ic.hl.oper.exp);
appendStrTab (&cCode.code, "\n%swhile (%s) {\n", indent(indLevel),
walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc));
invalidateIcode (picode);
break;
case REPEAT_TYPE:
appendStrTab (&cCode.code, "\n%sdo {\n", indent(indLevel));
picode = pProc->Icode.GetIcode(latch->start+latch->length-1);
invalidateIcode (picode);
break;
case ENDLESS_TYPE:
appendStrTab (&cCode.code, "\n%sfor (;;) {\n", indent(indLevel));
}
stats.numHLIcode += 1;
indLevel++;
}
/* Write the code for this basic block */
if (repCond == FALSE)
writeBB (pBB, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
/* Check for end of path */
nodeType = pBB->nodeType;
if (nodeType == RETURN_NODE || nodeType == TERMINATE_NODE ||
nodeType == NOWHERE_NODE || (pBB->dfsLastNum == latchNode))
return;
/* Check type of loop/node and process code */
if (loopType) /* there is a loop */
{
if (pBB != latch) /* loop is over several bbs */
{
if (loopType == WHILE_TYPE)
{
succ = pBB->edges[THEN].BBptr;
if (succ->dfsLastNum == pBB->loopFollow)
succ = pBB->edges[ELSE].BBptr;
}
else
succ = pBB->edges[0].BBptr;
if (succ->traversed != DFS_ALPHA)
writeCode (succ, indLevel, pProc, numLoc, latch->dfsLastNum,
ifFollow);
else /* has been traversed so we need a goto */
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
}
/* Loop epilogue: generate the loop trailer */
indLevel--;
if (loopType == WHILE_TYPE)
{
/* Check if there is need to repeat other statements involved
* in while condition, then, emit the loop trailer */
if (repCond)
writeBB (pBB, pProc->Icode.GetFirstIcode(), indLevel+1, pProc, numLoc);
appendStrTab (&cCode.code, "%s} /* end of while */\n",
indent(indLevel));
}
else if (loopType == ENDLESS_TYPE)
appendStrTab (&cCode.code, "%s} /* end of loop */\n",
indent(indLevel));
else if (loopType == REPEAT_TYPE)
{
if (picode->ic.hl.opcode != HLI_JCOND)
reportError (REPEAT_FAIL);
appendStrTab (&cCode.code, "%s} while (%s);\n", indent(indLevel),
walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc));
}
/* Recurse on the loop follow */
if (pBB->loopFollow != MAX)
{
succ = pProc->dfsLast[pBB->loopFollow];
if (succ->traversed != DFS_ALPHA)
writeCode (succ, indLevel, pProc, numLoc, latchNode, ifFollow);
else /* has been traversed so we need a goto */
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
}
}
else /* no loop, process nodeType of the graph */
{
if (nodeType == TWO_BRANCH) /* if-then[-else] */
{
stats.numHLIcode++;
indLevel++;
emptyThen = FALSE;
if (pBB->ifFollow != MAX) /* there is a follow */
{
/* process the THEN part */
follow = pBB->ifFollow;
succ = pBB->edges[THEN].BBptr;
if (succ->traversed != DFS_ALPHA) /* not visited */
{
if (succ->dfsLastNum != follow) /* THEN part */
{
l = writeJcond (
pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl,
pProc, numLoc);
appendStrTab (&cCode.code, "\n%s%s", indent(indLevel-1), l);
writeCode (succ, indLevel, pProc, numLoc, latchNode,
follow);
}
else /* empty THEN part => negate ELSE part */
{
l = writeJcondInv (
pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl,
pProc, numLoc);
appendStrTab (&cCode.code, "\n%s%s", indent(indLevel-1), l);
writeCode (pBB->edges[ELSE].BBptr, indLevel, pProc, numLoc,
latchNode, follow);
emptyThen = TRUE;
}
}
else /* already visited => emit label */
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
/* process the ELSE part */
succ = pBB->edges[ELSE].BBptr;
if (succ->traversed != DFS_ALPHA) /* not visited */
{
if (succ->dfsLastNum != follow) /* ELSE part */
{
appendStrTab (&cCode.code, "%s}\n%selse {\n",
indent(indLevel-1), indent(indLevel - 1));
writeCode (succ, indLevel, pProc, numLoc, latchNode,
follow);
}
/* else (empty ELSE part) */
}
else if (! emptyThen) /* already visited => emit label */
{
appendStrTab (&cCode.code, "%s}\n%selse {\n",
indent(indLevel-1), indent(indLevel - 1));
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
}
appendStrTab (&cCode.code, "%s}\n", indent(--indLevel));
/* Continue with the follow */
succ = pProc->dfsLast[follow];
if (succ->traversed != DFS_ALPHA)
writeCode (succ, indLevel, pProc, numLoc, latchNode,
ifFollow);
}
else /* no follow => if..then..else */
{
l = writeJcond (
pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl,
pProc, numLoc);
appendStrTab (&cCode.code, "%s%s", indent(indLevel-1), l);
writeCode (pBB->edges[THEN].BBptr, indLevel, pProc, numLoc,
latchNode, ifFollow);
appendStrTab (&cCode.code, "%s}\n%selse {\n", indent(indLevel-1),
indent(indLevel - 1));
writeCode (pBB->edges[ELSE].BBptr, indLevel, pProc, numLoc,
latchNode, ifFollow);
appendStrTab (&cCode.code, "%s}\n", indent(--indLevel));
}
}
else /* fall, call, 1w */
{
succ = pBB->edges[0].BBptr; /* fall-through edge */
if (succ->traversed != DFS_ALPHA)
writeCode (succ, indLevel, pProc,numLoc, latchNode,ifFollow);
}
}
}
static void codeGen (PPROC pProc, FILE *fp)
/* Writes the procedure's declaration (including arguments), local variables,
* and invokes the procedure that writes the code of the given record *hli */
void Function::codeGen (std::ostream &fs)
{
int numLoc;
ostringstream ostr;
//STKFRAME * args; /* Procedure arguments */
//char buf[200], /* Procedure's definition */
// arg[30]; /* One argument */
BB *pBB; /* Pointer to basic block */
{ Int i, numLoc;
PSTKFRAME args; /* Procedure arguments */
char buf[200], /* Procedure's definition */
arg[30]; /* One argument */
ID *locid; /* Pointer to one local identifier */
BB *pBB; /* Pointer to basic block */
/* Write procedure/function header */
cCode.init();
if (flg & PROC_IS_FUNC) /* Function */
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" (";
newBundle (&cCode);
if (pProc->flg & PROC_IS_FUNC) /* Function */
appendStrTab (&cCode.decl, "\n%s %s (", hlTypes[pProc->retVal.type],
pProc->name);
else /* Procedure */
ostr<< "\nvoid "<<name<<" (";
appendStrTab (&cCode.decl, "\nvoid %s (", pProc->name);
/* Write arguments */
for (size_t i = 0; i < args.size(); i++)
args = &pProc->args;
memset (buf, 0, sizeof(buf));
for (i = 0; i < args->csym; i++)
{
if ( args[i].invalid )
continue;
ostr<<hlTypes[args[i].type]<<" "<<args[i].name;
if (i < (args.size() - 1))
ostr<<", ";
if (args->sym[i].invalid == FALSE)
{
sprintf (arg,"%s %s",hlTypes[args->sym[i].type], args->sym[i].name);
strcat (buf, arg);
if (i < (args->numArgs - 1))
strcat (buf, ", ");
}
}
ostr<<")\n";
strcat (buf, ")\n");
appendStrTab (&cCode.decl, "%s", buf);
/* Write comments */
writeProcComments( ostr );
/* Write comments */
writeProcComments (pProc, &cCode.decl);
/* Write local variables */
if (! (flg & PROC_ASM))
{
numLoc = 0;
for (ID &refId : localId )
{
/* Output only non-invalidated entries */
if ( refId.illegal )
continue;
if (refId.loc == REG_FRAME)
{
/* Register variables are assigned to a local variable */
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) ||
((flg & DI_REGVAR) && (refId.id.regi == rDI)))
{
refId.setLocalName(++numLoc);
ostr << "int "<<refId.name<<";\n";
}
/* 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);
}
if (! (pProc->flg & PROC_ASM))
{
locid = &pProc->localId.id[0];
numLoc = 0;
for (i = 0; i < pProc->localId.csym; i++, locid++)
{
/* Output only non-invalidated entries */
if (locid->illegal == FALSE)
{
if (locid->loc == REG_FRAME)
{
/* Register variables are assigned to a local variable */
if (((pProc->flg & SI_REGVAR) && (locid->id.regi == rSI)) ||
((pProc->flg & DI_REGVAR) && (locid->id.regi == rDI)))
{
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. */
}
cCode.appendCode( "}\n\n");
writeBundle (fs, cCode);
freeBundle (&cCode);
else if (locid->loc == STK_FRAME)
{
/* 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 */
if (option.verbose)
for (size_t i = 0; i < numBBs; i++)
{
pBB = m_dfsLast[i];
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
cout << "BB "<<i<<"\n";
cout << " Start = "<<pBB->begin()->loc_ip;
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
cout << " LiveUse = ";
Machine_X86::writeRegVector(cout,pBB->liveUse);
cout << "\n Def = ";
Machine_X86::writeRegVector(cout,pBB->def);
cout << "\n LiveOut = ";
Machine_X86::writeRegVector(cout,pBB->liveOut);
cout << "\n LiveIn = ";
Machine_X86::writeRegVector(cout,pBB->liveIn);
cout <<"\n\n";
}
if (option.verbose)
for (i = 0; i < pProc->numBBs; i++)
{
pBB = pProc->dfsLast[i];
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
printf ("BB %d\n", i);
printf (" Start = %d, end = %d\n", pBB->start, pBB->start +
pBB->length - 1);
printf (" LiveUse = ");
writeBitVector (pBB->liveUse);
printf ("\n Def = ");
writeBitVector (pBB->def);
printf ("\n LiveOut = ");
writeBitVector (pBB->liveOut);
printf ("\n LiveIn = ");
writeBitVector (pBB->liveIn);
printf ("\n\n");
}
}
static void backBackEnd (char *filename, PCALL_GRAPH pcallGraph, FILE *fp)
/* Recursive procedure. Displays the procedure's code in depth-first order
* of the call graph. */
static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &_ios)
{
{ Int i;
// IFace.Yield(); /* This is a good place to yield to other apps */
// IFace.Yield(); /* This is a good place to yield to other apps */
/* Check if this procedure has been processed already */
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
(pcallGraph->proc->flg & PROC_ISLIB))
return;
pcallGraph->proc->flg |= PROC_OUTPUT;
/* Check if this procedure has been processed already */
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
(pcallGraph->proc->flg & PROC_ISLIB))
return;
pcallGraph->proc->flg |= PROC_OUTPUT;
/* Dfs if this procedure has any successors */
for (size_t i = 0; i < pcallGraph->outEdges.size(); i++)
{
backBackEnd (filename, pcallGraph->outEdges[i], _ios);
}
/* Dfs if this procedure has any successors */
if (pcallGraph->numOutEdges > 0)
{
for (i = 0; i < pcallGraph->numOutEdges; i++)
{
backBackEnd (filename, pcallGraph->outEdges[i], fp);
}
}
/* Generate code for this procedure */
stats.numLLIcode = pcallGraph->proc->Icode.size();
stats.numHLIcode = 0;
pcallGraph->proc->codeGen (_ios);
/* Generate code for this procedure */
stats.numLLIcode = pcallGraph->proc->Icode.GetNumIcodes();
stats.numHLIcode = 0;
codeGen (pcallGraph->proc, fp);
/* Generate statistics */
if (option.Stats)
pcallGraph->proc->displayStats ();
if (! (pcallGraph->proc->flg & PROC_ASM))
{
stats.totalLL += stats.numLLIcode;
stats.totalHL += stats.numHLIcode;
}
/* Generate statistics */
if (option.Stats)
displayStats (pcallGraph->proc);
if (! (pcallGraph->proc->flg & PROC_ASM))
{
stats.totalLL += stats.numLLIcode;
stats.totalHL += stats.numHLIcode;
}
}
void BackEnd (char *fileName, PCALL_GRAPH pcallGraph)
/* Invokes the necessary routines to produce code one procedure at a time. */
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
{
std::ofstream fs; /* Output C file */
char* outName, *ext;
FILE* fp; /* Output C file */
/* Get output file name */
std::string outNam(fileName);
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
/* Get output file name */
outName = strcpy ((char*)allocMem(strlen(fileName)+1), fileName);
if ((ext = strrchr (outName, '.')) != NULL)
*ext = '\0';
strcat (outName, ".b"); /* b for beta */
/* Open output file */
fs.open(outNam);
if(!fs.is_open())
fatalError (CANNOT_OPEN, outNam.c_str());
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
/* Open output file */
fp = fopen (outName, "wt");
if (!fp)
fatalError (CANNOT_OPEN, outName);
printf ("dcc: Writing C beta file %s\n", outName);
/* Header information */
writeHeader (fs, fileName);
/* Header information */
writeHeader (fp, fileName);
/* Initialize total Icode instructions statistics */
stats.totalLL = 0;
stats.totalHL = 0;
/* Initialize total Icode instructions statistics */
stats.totalLL = 0;
stats.totalHL = 0;
/* Process each procedure at a time */
backBackEnd (fileName, pcallGraph, fs);
/* Process each procedure at a time */
backBackEnd (fileName, pcallGraph, fp);
/* Close output file */
fs.close();
printf ("dcc: Finished writing C beta file\n");
/* Close output file */
fclose (fp);
printf ("dcc: Finished writing C beta file\n");
}

View File

@ -6,89 +6,107 @@
#include "dcc.h"
#include <stdarg.h>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#define deltaProcLines 20
using namespace std;
void newBundle (bundle *procCode)
/* Allocates memory for a new bundle and initializes it to zero. */
{
memset (&(procCode->decl), 0, sizeof(strTable));
memset (&(procCode->code), 0, sizeof(strTable));
}
static void incTableSize (strTable *strTab)
/* Increments the size of the table strTab by deltaProcLines and copies all
* the strings to the new table. */
{
strTab->allocLines += deltaProcLines;
strTab->str = (char**)reallocVar (strTab->str, strTab->allocLines*sizeof(char *));
memset (&strTab->str[strTab->allocLines - deltaProcLines], 0,
deltaProcLines * sizeof(char *));
}
void appendStrTab (strTable *strTab, char *format, ...)
/* Appends the new line (in printf style) to the string table strTab. */
{ va_list args;
va_start (args, format);
if (strTab->numLines == strTab->allocLines)
{
incTableSize (strTab);
}
strTab->str[strTab->numLines] = (char *)malloc(lineSize * sizeof(char));
if (strTab->str == NULL)
{
fatalError(MALLOC_FAILED, lineSize * sizeof(char));
}
vsprintf (strTab->str[strTab->numLines], format, args);
strTab->numLines++;
va_end (args);
}
Int nextBundleIdx (strTable *strTab)
/* Returns the next available index into the table */
{
return (strTab->numLines);
}
void addLabelBundle (strTable *strTab, Int idx, Int label)
/* Adds the given label to the start of the line strTab[idx]. The first
* tab is removed and replaced by this label */
void strTable::addLabelBundle (int idx, int label)
{
char s[16];
sprintf (s, "l%d: ", label);
if(at(idx).size()<4)
at(idx)=s;
else
at(idx) = string(s)+at(idx).substr(4);
{ char s[lineSize];
sprintf (s, "l%ld: %s", label, &strTab->str[idx][4]);
strcpy (strTab->str[idx], s);
}
static void writeStrTab (FILE *fp, strTable strTab)
/* Writes the contents of the string table on the file fp. */
static void writeStrTab (std::ostream &ios, strTable &strTab)
{
for (size_t i = 0; i < strTab.size(); i++)
ios << strTab[i];
{ Int i;
for (i = 0; i < strTab.numLines; i++)
fprintf (fp, "%s", strTab.str[i]);
}
void writeBundle (FILE *fp, bundle procCode)
/* Writes the contents of the bundle (procedure code and declaration) to
* a file. */
void writeBundle (std::ostream &ios, bundle procCode)
{
writeStrTab (ios, procCode.decl);
writeStrTab (ios, procCode.code);
writeStrTab (fp, procCode.decl);
if (procCode.decl.str[procCode.decl.numLines - 1][0] != ' ')
fprintf (fp, "\n");
writeStrTab (fp, procCode.code);
}
static void freeStrTab (strTable *strTab)
/* Frees the storage allocated by the string table. */
static void freeStrTab (strTable &strTab)
{
strTab.clear();
{ Int i;
if (strTab->allocLines > 0) {
for (i = 0; i < strTab->numLines; i++)
free (strTab->str[i]);
free (strTab->str);
memset (strTab, 0, sizeof(strTable));
}
}
/* Deallocates the space taken by the bundle procCode */
void freeBundle (bundle *procCode)
/* Deallocates the space taken by the bundle procCode */
{
freeStrTab (procCode->decl);
freeStrTab (procCode->code);
}
void bundle::appendCode(const char *format,...)
{
va_list args;
char buf[lineSize]={0};
va_start (args, format);
vsprintf (buf, format, args);
code.push_back(buf);
va_end (args);
}
void bundle::appendCode(const std::string &s)
{
code.push_back(s);
}
void bundle::appendDecl(const char *format,...)
{
va_list args;
char buf[lineSize]={0};
va_start (args, format);
vsprintf (buf, format, args);
decl.push_back(buf);
va_end (args);
}
void bundle::appendDecl(const std::string &v)
{
decl.push_back(v);
freeStrTab (&(procCode->decl));
freeStrTab (&(procCode->code));
}

File diff suppressed because it is too large Load Diff

View File

@ -7,274 +7,258 @@
****************************************************************************/
#include "dcc.h"
#include "machine_x86.h"
#include <string.h>
#include <sstream>
using namespace std;
#define intSize 40
static const char *int21h[] =
{
"Terminate process",
"Character input with echo",
"Character output",
"Auxiliary input",
"Auxiliary output",
"Printer output",
"Direct console i/o",
"Unfiltered char i w/o echo",
"Character input without echo",
"Display string",
"Buffered keyboard input",
"Check input status",
"Flush input buffer and then input",
"Disk reset",
"Select disk",
"Open file",
"Close file",
"Find first file",
"Find next file",
"Delete file",
"Sequential read",
"Sequential write",
"Create file",
"Rename file",
"Reserved",
"Get current disk",
"Set DTA address",
"Get default drive data",
"Get drive data",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Random read",
"Random write",
"Get file size",
"Set relative record number",
"Set interrupt vector",
"Create new PSP",
"Random block read",
"Random block write",
"Parse filename",
"Get date",
"Set date",
"Get time",
"Set time",
"Set verify flag",
"Get DTA address",
"Get MSDOS version number",
"Terminate and stay resident",
"Reserved",
"Get or set break flag",
"Reserved",
"Get interrupt vector",
"Get drive allocation info",
"Reserved",
"Get or set country info",
"Create directory",
"Delete directory",
"Set current directory",
"Create file",
"Open file",
"Close file",
"Read file or device",
"Write file or device",
"Delete file",
"Set file pointer",
"Get or set file attributes",
"IOCTL (i/o control)",
"Duplicate handle",
"Redirect handle",
"Get current directory",
"Alloate memory block",
"Release memory block",
"Resize memory block",
"Execute program (exec)",
"Terminate process with return code",
"Get return code",
"Find first file",
"Find next file",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Get verify flag",
"Reserved",
"Rename file",
"Get or set file date & time",
"Get or set allocation strategy",
"Get extended error information",
"Create temporary file",
"Create new file",
"Lock or unlock file region",
"Reserved",
"Get machine name",
"Device redirection",
"Reserved",
"Reserved",
"Get PSP address",
"Get DBCS lead uint8_t table",
"Reserved",
"Get extended country information",
"Get or set code page",
"Set handle count",
"Commit file",
"Reserved",
"Reserved",
"Reserved",
"Extended open file"
static char *int21h[] =
{"Terminate process",
"Character input with echo",
"Character output",
"Auxiliary input",
"Auxiliary output",
"Printer output",
"Direct console i/o",
"Unfiltered char i w/o echo",
"Character input without echo",
"Display string",
"Buffered keyboard input",
"Check input status",
"Flush input buffer and then input",
"Disk reset",
"Select disk",
"Open file",
"Close file",
"Find first file",
"Find next file",
"Delete file",
"Sequential read",
"Sequential write",
"Create file",
"Rename file",
"Reserved",
"Get current disk",
"Set DTA address",
"Get default drive data",
"Get drive data",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Random read",
"Random write",
"Get file size",
"Set relative record number",
"Set interrupt vector",
"Create new PSP",
"Random block read",
"Random block write",
"Parse filename",
"Get date",
"Set date",
"Get time",
"Set time",
"Set verify flag",
"Get DTA address",
"Get MSDOS version number",
"Terminate and stay resident",
"Reserved",
"Get or set break flag",
"Reserved",
"Get interrupt vector",
"Get drive allocation info",
"Reserved",
"Get or set country info",
"Create directory",
"Delete directory",
"Set current directory",
"Create file",
"Open file",
"Close file",
"Read file or device",
"Write file or device",
"Delete file",
"Set file pointer",
"Get or set file attributes",
"IOCTL (i/o control)",
"Duplicate handle",
"Redirect handle",
"Get current directory",
"Alloate memory block",
"Release memory block",
"Resize memory block",
"Execute program (exec)",
"Terminate process with return code",
"Get return code",
"Find first file",
"Find next file",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Get verify flag",
"Reserved",
"Rename file",
"Get or set file date & time",
"Get or set allocation strategy",
"Get extended error information",
"Create temporary file",
"Create new file",
"Lock or unlock file region",
"Reserved",
"Get machine name",
"Device redirection",
"Reserved",
"Reserved",
"Get PSP address",
"Get DBCS lead byte table",
"Reserved",
"Get extended country information",
"Get or set code page",
"Set handle count",
"Commit file",
"Reserved",
"Reserved",
"Reserved",
"Extended open file"
};
static const char *intOthers[] = {
"Exit", /* 0x20 */
"", /* other table */
"Terminate handler address", /* 0x22 */
"Ctrl-C handler address", /* 0x23 */
"Critical-error handler address", /* 0x24 */
"Absolute disk read", /* 0x25 */
"Absolute disk write", /* 0x26 */
"Terminate and stay resident", /* 0x27 */
"Reserved", /* 0x28 */
"Reserved", /* 0x29 */
"Reserved", /* 0x2A */
"Reserved", /* 0x2B */
"Reserved", /* 0x2C */
"Reserved", /* 0x2D */
"Reserved" /* 0x2E */
static char *intOthers[] = {
"Exit", /* 0x20 */
"", /* other table */
"Terminate handler address", /* 0x22 */
"Ctrl-C handler address", /* 0x23 */
"Critical-error handler address", /* 0x24 */
"Absolute disk read", /* 0x25 */
"Absolute disk write", /* 0x26 */
"Terminate and stay resident", /* 0x27 */
"Reserved", /* 0x28 */
"Reserved", /* 0x29 */
"Reserved", /* 0x2A */
"Reserved", /* 0x2B */
"Reserved", /* 0x2C */
"Reserved", /* 0x2D */
"Reserved" /* 0x2E */
};
void writeIntComment (PICODE icode, char *s)
/* Writes the description of the current interrupt. Appends it to the
* string s. */
void LLInst::writeIntComment (std::ostringstream &s)
{
uint32_t src_immed=src().getImm2();
s<<"\t/* ";
if (src_immed == 0x21)
{
s <<int21h[dst.off];
{ char *t;
t = (char *)allocMem(intSize * sizeof(char));
if (icode->ic.ll.immed.op == 0x21)
{ sprintf (t, "\t/* %s */\n", int21h[icode->ic.ll.dst.off]);
strcat (s, t);
}
else if (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)
{
s <<intOthers[src_immed - 0x20];
}
else if (src_immed == 0x2F)
{
switch (dst.off)
{
case 0x01 :
s << "Print spooler";
break;
case 0x02:
s << "Assign";
break;
case 0x10:
s << "Share";
break;
case 0xB7:
s << "Append";
}
}
else
s<<"Unknown int";
s<<" */\n";
else if (icode->ic.ll.immed.op == 0x2F)
switch (icode->ic.ll.dst.off) {
case 0x01 : strcat (s, "\t/* Print spooler */\n");
break;
case 0x02: strcat (s, "\t/* Assign */\n");
break;
case 0x10: strcat (s, "\t/* Share */\n");
break;
case 0xB7: strcat (s, "\t/* Append */\n");
}
else
strcat (s, "\n");
}
//, &cCode.decl
void Function::writeProcComments()
{
std::ostringstream ostr;
writeProcComments(ostr);
cCode.appendDecl(ostr.str());
void writeProcComments (PPROC p, strTable *strTab)
{ int i;
ID *id; /* Pointer to register argument identifier */
PSTKSYM psym; /* Pointer to register argument symbol */
/* 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";
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,36 +5,37 @@
****************************************************************************/
#include "dcc.h"
#include "project.h"
#include <string.h>
#ifdef __UNIX__
#include <unistd.h>
#else
#include <stdio.h>
#include <io.h> /* For unlink() */
#endif
/* Global variables - extern to other modules */
char *progname; /* argv[0] - for error msgs */
char *asm1_name, *asm2_name; /* Assembler output filenames */
SYMTAB symtab; /* Global symbol table */
STATS stats; /* cfg statistics */
//PROG prog; /* programs fields */
PROG prog; /* programs fields */
OPTION option; /* Command line options */
//Function * pProcList; /* List of procedures, topologically sort */
//Function * pLastProc; /* Pointer to last node in procedure list */
//FunctionListType pProcList;
//CALL_GRAPH *callGraph; /* Call graph of the program */
PPROC pProcList; /* List of procedures, topologically sort */
PPROC pLastProc; /* Pointer to last node in procedure list */
CALL_GRAPH *callGraph; /* Call graph of the program */
static char *initargs(int argc, char *argv[]);
static void displayTotalStats(void);
#include <llvm/Support/raw_os_ostream.h>
static void displayTotalStats();
/****************************************************************************
* main
***************************************************************************/
#include <iostream>
extern Project g_proj;
int main(int argc, char *argv[])
{
// llvm::MCOperand op=llvm::MCOperand::CreateImm(11);
// llvm::MCAsmInfo info;
// llvm::raw_os_ostream wrap(std::cerr);
// op.print(wrap,&info);
// wrap.flush();
/* Extract switches and filename */
strcpy(option.filename, initargs(argc, argv));
@ -42,9 +43,7 @@ int main(int argc, char *argv[])
* building the call graph and attaching appropriate bits of code for
* each procedure.
*/
DccFrontend fe(option.filename);
if(false==fe.FrontEnd ())
return -1;
FrontEnd (option.filename, &callGraph);
/* In the middle is a so called Universal Decompiling Machine.
* It processes the procedure list and I-code and attaches where it can
@ -56,14 +55,14 @@ int main(int argc, char *argv[])
* analysis, data flow etc. and outputs it to output file ready for
* re-compilation.
*/
BackEnd(option.filename, g_proj.callGraph);
BackEnd(option.filename, callGraph);
g_proj.callGraph->write();
writeCallGraph (callGraph);
if (option.Stats)
displayTotalStats();
/*
/*
freeDataStructures(pProcList);
*/
return 0;
@ -75,51 +74,50 @@ int main(int argc, char *argv[])
static char *initargs(int argc, char *argv[])
{
char *pc;
progname = *argv; /* Save invocation name for error messages */
while (--argc > 0 && (*++argv)[0] == '-')
{
while (--argc > 0 && (*++argv)[0] == '-') {
for (pc = argv[0]+1; *pc; pc++)
switch (*pc)
{
case 'a': /* Print assembler listing */
if (*(pc+1) == '2')
option.asm2 = true;
else
option.asm1 = true;
if (*(pc+1) == '1' || *(pc+1) == '2')
pc++;
break;
case 'c':
option.Calls = true;
break;
case 'i':
option.Interact = true;
break;
case 'm': /* Print memory map */
option.Map = true;
break;
case 's': /* Print Stats */
option.Stats = true;
break;
case 'V': /* Very verbose => verbose */
option.VeryVerbose = true;
case 'v':
option.verbose = true; /* Make everything verbose */
break;
case 'o': /* assembler output file */
if (*(pc+1)) {
asm1_name = asm2_name = pc+1;
goto NextArg;
}
else if (--argc > 0) {
asm1_name = asm2_name = *++argv;
goto NextArg;
}
default:
fatalError(INVALID_ARG, *pc);
return *argv;
switch (*pc) {
case 'a': /* Print assembler listing */
if (*(pc+1) == '2')
option.asm2 = TRUE;
else
option.asm1 = TRUE;
if (*(pc+1) == '1' || *(pc+1) == '2')
pc++;
break;
case 'c':
option.Calls = TRUE;
break;
case 'i':
option.Interact = TRUE;
break;
case 'm': /* Print memory map */
option.Map = TRUE;
break;
case 's': /* Print Stats */
option.Stats = TRUE;
break;
case 'V': /* Very verbose => verbose */
option.VeryVerbose = TRUE;
case 'v': /* Make everything verbose */
option.verbose = TRUE;
break;
case 'o': /* assembler output file */
if (*(pc+1)) {
asm1_name = asm2_name = pc+1;
goto NextArg;
}
else if (--argc > 0) {
asm1_name = asm2_name = *++argv;
goto NextArg;
}
default:
fatalError(INVALID_ARG, *pc);
return *argv;
}
NextArg:;
NextArg:;
}
if (argc == 1)
@ -128,13 +126,13 @@ NextArg:;
{
if (! asm1_name)
{
asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
asm1_name = strcpy((char*)allocMem(strlen(*argv)+4), *argv);
pc = strrchr(asm1_name, '.');
if (pc > strrchr(asm1_name, '/'))
{
*pc = '\0';
}
asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
asm2_name = (char*)allocMem(strlen(asm1_name)+4) ;
strcat(strcpy(asm2_name, asm1_name), ".a2");
unlink(asm2_name);
strcat(asm1_name, ".a1");
@ -142,10 +140,10 @@ NextArg:;
unlink(asm1_name); /* Remove asm output files */
}
return *argv; /* filename of the program to decompile */
}
}
fatalError(USAGE);
return *argv; // does not reach this.
return *argv;
}
static void

File diff suppressed because it is too large Load Diff

View File

@ -3,47 +3,54 @@
* (C) Cristina Cifuentes
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <string>
#include <stdarg.h>
#include "dcc.h"
static std::map<eErrorId,std::string> errorMessage =
{
{INVALID_ARG ,"Invalid option -%c\n"},
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
{CANNOT_OPEN ,"Cannot open %s\n"},
{CANNOT_READ ,"Error while reading %s\n"},
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
{NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"},
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
};
#include <stdio.h>
#include <stdlib.h>
//#ifndef __UNIX__
#if 1
#include <stdarg.h>
#else
#include <varargs.h>
#endif
static char *errorMessage[] = {
"Invalid option -%c\n", /* INVALID_ARG */
"Invalid instruction %02X at location %06lX\n", /* INVALID_OPCODE */
"Don't understand 80386 instruction %02X at location %06lX\n",
/* INVALID_386OP */
"Segment override with no memory operand at location %06lX\n",
/* FUNNY_SEGOVR */
"REP prefix without a string instruction at location %06lX\n",/* FUNNY_REP */
"Cannot open %s\n", /* CANNOT_OPEN */
"Error while reading %s\n", /* CANNOT_READ */
"malloc of %ld bytes failed\n", /* MALLOC_FAILED */
"Don't understand new EXE format\n", /* NEWEXE_FORMAT */
"Failed to find a BB for jump to %ld in proc %s\n", /* NO_BB */
"Basic Block is a synthetic jump\n", /* INVALID_SYNTHETIC_BB */
"Failed to find a BB for interval\n", /* INVALID_INT_BB */
"Instruction at location %06lX goes beyond loaded image\n",
/* IP_OUT_OF_RANGE*/
"Definition not found for condition code usage at opcode %d\n",
/* DEF_NOT_FOUND */
"JX use, definition not supported at opcode #%d\n", /* JX_NOT_DEF */
"Def - use not supported. Def op = %d, use op = %d.\n", /* NOT_DEF_USE */
"Failed to construct repeat..until() condition.\n", /* REPEAT_FAIL */
"Failed to construct while() condition.\n", /* WHILE_FAIL */
};
/****************************************************************************
fatalError: displays error message and exits the program.
****************************************************************************/
void fatalError(eErrorId errId, ...)
void fatalError(Int errId, ...)
{ va_list args;
//#ifdef __UNIX__ /* ultrix */
#if 0
int errId;
Int errId;
va_start(args);
errId = va_arg(args, int);
errId = va_arg(args, Int);
#else
va_start(args, errId);
#endif
@ -52,7 +59,7 @@ void fatalError(eErrorId errId, ...)
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
else {
fprintf(stderr, "dcc: ");
vfprintf(stderr, errorMessage[errId].c_str(), args);
vfprintf(stderr, errorMessage[errId - 1], args);
}
va_end(args);
exit((int)errId);
@ -62,18 +69,18 @@ void fatalError(eErrorId errId, ...)
/****************************************************************************
reportError: reports the warning/error and continues with the program.
****************************************************************************/
void reportError(eErrorId errId, ...)
void reportError(Int errId, ...)
{ va_list args;
//#ifdef __UNIX__ /* ultrix */
#if 0
int errId;
Int errId;
va_start(args);
errId = va_arg(args, int);
errId = va_arg(args, Int);
#else /* msdos or windows*/
va_start(args, errId);
#endif
fprintf(stderr, "dcc: ");
vfprintf(stderr, errorMessage[errId].c_str(), args);
vfprintf(stderr, errorMessage[errId - 1], args);
va_end(args);
}

View File

@ -18,26 +18,29 @@
#ifndef bool
#define bool unsigned char
#define uint8_t unsigned char
#define TRUE 1
#define FALSE 0
#define byte unsigned char
#endif
static int pc; /* Indexes into pat[] */
/* prototypes */
static bool ModRM(uint8_t pat[]); /* Handle the mod/rm uint8_t */
static bool TwoWild(uint8_t pat[]); /* Make the next 2 bytes wild */
static bool FourWild(uint8_t pat[]); /* Make the next 4 bytes wild */
void fixWildCards(uint8_t pat[]); /* Main routine */
static bool ModRM(byte pat[]); /* Handle the mod/rm byte */
static bool TwoWild(byte pat[]); /* Make the next 2 bytes wild */
static bool FourWild(byte pat[]); /* Make the next 4 bytes wild */
void fixWildCards(byte pat[]); /* Main routine */
/* Handle the mod/rm case. Returns true if pattern exhausted */
static bool ModRM(uint8_t pat[])
static bool
ModRM(byte pat[])
{
uint8_t op;
byte op;
/* A standard mod/rm uint8_t follows opcode */
op = pat[pc++]; /* The mod/rm uint8_t */
if (pc >= PATLEN) return true; /* Skip Mod/RM */
/* A standard mod/rm byte follows opcode */
op = pat[pc++]; /* The mod/rm byte */
if (pc >= PATLEN) return TRUE; /* Skip Mod/RM */
switch (op & 0xC0)
{
case 0x00: /* [reg] or [nnnn] */
@ -45,42 +48,42 @@ static bool ModRM(uint8_t pat[])
{
/* Uses [nnnn] address mode */
pat[pc++] = WILD;
if (pc >= PATLEN) return true;
if (pc >= PATLEN) return TRUE;
pat[pc++] = WILD;
if (pc >= PATLEN) return true;
if (pc >= PATLEN) return TRUE;
}
break;
case 0x40: /* [reg + nn] */
if ((pc+=1) >= PATLEN) return true;
if ((pc+=1) >= PATLEN) return TRUE;
break;
case 0x80: /* [reg + nnnn] */
/* Possibly just a long constant offset from a register,
but often will be an index from a variable */
pat[pc++] = WILD;
if (pc >= PATLEN) return true;
if (pc >= PATLEN) return TRUE;
pat[pc++] = WILD;
if (pc >= PATLEN) return true;
if (pc >= PATLEN) return TRUE;
break;
case 0xC0: /* reg */
break;
}
return false;
return FALSE;
}
/* Change the next two bytes to wild cards */
static bool
TwoWild(uint8_t pat[])
TwoWild(byte pat[])
{
pat[pc++] = WILD;
if (pc >= PATLEN) return true; /* Pattern exhausted */
if (pc >= PATLEN) return TRUE; /* Pattern exhausted */
pat[pc++] = WILD;
if (pc >= PATLEN) return true;
return false;
if (pc >= PATLEN) return TRUE;
return FALSE;
}
/* Change the next four bytes to wild cards */
static bool
FourWild(uint8_t pat[])
FourWild(byte pat[])
{
TwoWild(pat);
return TwoWild(pat);
@ -89,21 +92,22 @@ FourWild(uint8_t pat[])
/* Chop from the current point by wiping with zeroes. Can't rely on anything
after this point */
static void
chop(uint8_t pat[])
chop(byte pat[])
{
if (pc >= PATLEN) return; /* Could go negative otherwise */
memset(&pat[pc], 0, PATLEN - pc);
}
static bool op0F(uint8_t pat[])
static bool
op0F(byte pat[])
{
/* The two uint8_t opcodes */
uint8_t op = pat[pc++];
/* The two byte opcodes */
byte op = pat[pc++];
switch (op & 0xF0)
{
case 0x00: /* 00 - 0F */
if (op >= 0x06) /* Clts, Invd, Wbinvd */
return false;
return FALSE;
else
{
/* Grp 6, Grp 7, LAR, LSL */
@ -113,10 +117,10 @@ static bool op0F(uint8_t pat[])
return ModRM(pat);
case 0x80:
pc += 2; /* uint16_t displacement cond jumps */
return false;
pc += 2; /* Word displacement cond jumps */
return FALSE;
case 0x90: /* uint8_t set on condition */
case 0x90: /* Byte set on condition */
return ModRM(pat);
case 0xA0:
@ -126,7 +130,7 @@ static bool op0F(uint8_t pat[])
case 0xA1: /* Pop FS */
case 0xA8: /* Push GS */
case 0xA9: /* Pop GS */
return false;
return FALSE;
case 0xA3: /* Bt Ev,Gv */
case 0xAB: /* Bts Ev,Gv */
@ -134,9 +138,9 @@ static bool op0F(uint8_t pat[])
case 0xA4: /* Shld EvGbIb */
case 0xAC: /* Shrd EvGbIb */
if (ModRM(pat)) return true;
if (ModRM(pat)) return TRUE;
pc++; /* The #num bits to shift */
return false;
return FALSE;
case 0xA5: /* Shld EvGb CL */
case 0xAD: /* Shrd EvGb CL */
@ -150,9 +154,9 @@ static bool op0F(uint8_t pat[])
if (op == 0xBA)
{
/* Grp 8: bt/bts/btr/btc Ev,#nn */
if (ModRM(pat)) return true;
if (ModRM(pat)) return TRUE;
pc++; /* The #num bits to shift */
return false;
return FALSE;
}
return ModRM(pat);
@ -163,10 +167,10 @@ static bool op0F(uint8_t pat[])
return ModRM(pat);
}
/* Else BSWAP */
return false;
return FALSE;
default:
return false; /* Treat as double uint8_t opcodes */
return FALSE; /* Treat as double byte opcodes */
}
@ -181,10 +185,10 @@ static bool op0F(uint8_t pat[])
PATLEN bytes are scanned.
*/
void
fixWildCards(uint8_t pat[])
fixWildCards(byte pat[])
{
uint8_t op, quad, intArg;
byte op, quad, intArg;
pc=0;
@ -193,17 +197,17 @@ fixWildCards(uint8_t pat[])
op = pat[pc++];
if (pc >= PATLEN) return;
quad = (uint8_t) (op & 0xC0); /* Quadrant of the opcode map */
quad = (byte) (op & 0xC0); /* Quadrant of the opcode map */
if (quad == 0)
{
/* Arithmetic group 00-3F */
if ((op & 0xE7) == 0x26) /* First check for the odds */
{
/* Segment prefix: treat as 1 uint8_t opcode */
/* Segment prefix: treat as 1 byte opcode */
continue;
}
if (op == 0x0F) /* 386 2 uint8_t opcodes */
if (op == 0x0F) /* 386 2 byte opcodes */
{
if (op0F(pat)) return;
continue;
@ -214,20 +218,20 @@ fixWildCards(uint8_t pat[])
/* All these are constant. Work out the instr length */
if (op & 2)
{
/* Push, pop, other 1 uint8_t opcodes */
/* Push, pop, other 1 byte opcodes */
continue;
}
else
{
if (op & 1)
{
/* uint16_t immediate operands */
/* Word immediate operands */
pc += 2;
continue;
}
else
{
/* uint8_t immediate operands */
/* Byte immediate operands */
pc++;
continue;
}
@ -253,7 +257,7 @@ fixWildCards(uint8_t pat[])
/* 0x60 - 0x70 */
if (op & 0x10)
{
/* 70-7F 2 uint8_t jump opcodes */
/* 70-7F 2 byte jump opcodes */
pc++;
continue;
}
@ -280,11 +284,11 @@ fixWildCards(uint8_t pat[])
if (TwoWild(pat)) return;
continue;
case 0x68: /* Push uint8_t */
case 0x6A: /* Push uint8_t */
case 0x68: /* Push byte */
case 0x6A: /* Push byte */
case 0x6D: /* insb port */
case 0x6F: /* outsb port */
/* 2 uint8_t instr, no wilds */
/* 2 byte instr, no wilds */
pc++;
continue;
@ -298,14 +302,14 @@ fixWildCards(uint8_t pat[])
switch (op & 0xF0)
{
case 0x80: /* 80 - 8F */
/* All have a mod/rm uint8_t */
/* All have a mod/rm byte */
if (ModRM(pat)) return;
/* These also have immediate values */
switch (op)
{
case 0x80:
case 0x83:
/* One uint8_t immediate */
/* One byte immediate */
pc++;
continue;
@ -324,7 +328,7 @@ fixWildCards(uint8_t pat[])
if (FourWild(pat)) return;
continue;
}
/* All others are 1 uint8_t opcodes */
/* All others are 1 byte opcodes */
continue;
case 0xA0: /* A0 - AF */
if ((op & 0x0C) == 0)
@ -335,7 +339,7 @@ fixWildCards(uint8_t pat[])
}
else if ((op & 0xFE) == 0xA8)
{
/* test al,#uint8_t or test ax,#uint16_t */
/* test al,#byte or test ax,#word */
if (op & 1) pc += 2;
else pc += 1;
continue;
@ -364,10 +368,10 @@ fixWildCards(uint8_t pat[])
/* In the last quadrant of the op code table */
switch (op)
{
case 0xC0: /* 386: Rotate group 2 ModRM, uint8_t, #uint8_t */
case 0xC1: /* 386: Rotate group 2 ModRM, uint16_t, #uint8_t */
case 0xC0: /* 386: Rotate group 2 ModRM, byte, #byte */
case 0xC1: /* 386: Rotate group 2 ModRM, word, #byte */
if (ModRM(pat)) return;
/* uint8_t immediate value follows ModRM */
/* Byte immediate value follows ModRM */
pc++;
continue;
@ -388,27 +392,27 @@ fixWildCards(uint8_t pat[])
case 0xC6: /* Mov ModRM, #nn */
if (ModRM(pat)) return;
/* uint8_t immediate value follows ModRM */
/* Byte immediate value follows ModRM */
pc++;
continue;
case 0xC7: /* Mov ModRM, #nnnn */
if (ModRM(pat)) return;
/* uint16_t immediate value follows ModRM */
/* Word immediate value follows ModRM */
/* Immediate 16 bit values might be constant, but also
might be relocatable. For now, make them wild */
if (TwoWild(pat)) return;
continue;
case 0xC8: /* Enter Iw, Ib */
pc += 3; /* Constant uint16_t, uint8_t */
pc += 3; /* Constant word, byte */
continue;
case 0xC9: /* Leave */
continue;
case 0xCC: /* int 3 */
case 0xCC: /* Int 3 */
continue;
case 0xCD: /* int nn */
case 0xCD: /* Int nn */
intArg = pat[pc++];
if ((intArg >= 0x34) && (intArg <= 0x3B))
{
@ -423,10 +427,10 @@ fixWildCards(uint8_t pat[])
case 0xCF: /* Iret */
continue;
case 0xD0: /* Group 2 rotate, uint8_t, 1 bit */
case 0xD1: /* Group 2 rotate, uint16_t, 1 bit */
case 0xD2: /* Group 2 rotate, uint8_t, CL bits */
case 0xD3: /* Group 2 rotate, uint16_t, CL bits */
case 0xD0: /* Group 2 rotate, byte, 1 bit */
case 0xD1: /* Group 2 rotate, word, 1 bit */
case 0xD2: /* Group 2 rotate, byte, CL bits */
case 0xD3: /* Group 2 rotate, word, CL bits */
if (ModRM(pat)) return;
continue;
@ -498,8 +502,8 @@ fixWildCards(uint8_t pat[])
case 0xFD: /* Std */
continue;
case 0xF6: /* Group 3 uint8_t test/not/mul/div */
case 0xF7: /* Group 3 uint16_t test/not/mul/div */
case 0xF6: /* Group 3 byte test/not/mul/div */
case 0xF7: /* Group 3 word test/not/mul/div */
case 0xFE: /* Inc/Dec group 4 */
if (ModRM(pat)) return;
continue;
@ -509,7 +513,7 @@ fixWildCards(uint8_t pat[])
if (ModRM(pat)) return;
continue;
default: /* Rest are single uint8_t opcodes */
default: /* Rest are single byte opcodes */
continue;
}
}

View File

@ -1,51 +1,54 @@
/*****************************************************************************
* dcc project Front End module
* Loads a program into simulated main memory and builds the procedure list.
* (C) Cristina Cifuentes
****************************************************************************/
* dcc project Front End module
* Loads a program into simulated main memory and builds the procedure list.
* (C) Cristina Cifuentes
****************************************************************************/
#include "dcc.h"
#include "disassem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __BORLAND__
#include <alloc.h>
#else
#include <malloc.h> /* For malloc, free, realloc */
#include "project.h"
#endif
typedef struct { /* PSP structure */
uint16_t int20h; /* interrupt 20h */
uint16_t eof; /* segment, end of allocation block */
uint8_t res1; /* reserved */
uint8_t dosDisp[5]; /* far call to DOS function dispatcher */
uint8_t int22h[4]; /* vector for terminate routine */
uint8_t int23h[4]; /* vector for ctrl+break routine */
uint8_t int24h[4]; /* vector for error routine */
uint8_t res2[22]; /* reserved */
uint16_t segEnv; /* segment address of environment block */
uint8_t res3[34]; /* reserved */
uint8_t int21h[6]; /* opcode for int21h and far return */
uint8_t res4[6]; /* reserved */
uint8_t fcb1[16]; /* default file control block 1 */
uint8_t fcb2[16]; /* default file control block 2 */
uint8_t res5[4]; /* reserved */
uint8_t cmdTail[0x80]; /* command tail and disk transfer area */
word int20h; /* interrupt 20h */
word eof; /* segment, end of allocation block */
byte res1; /* reserved */
byte dosDisp[5]; /* far call to DOS function dispatcher */
byte int22h[4]; /* vector for terminate routine */
byte int23h[4]; /* vector for ctrl+break routine */
byte int24h[4]; /* vector for error routine */
byte res2[22]; /* reserved */
word segEnv; /* segment address of environment block */
byte res3[34]; /* reserved */
byte int21h[6]; /* opcode for int21h and far return */
byte res4[6]; /* reserved */
byte fcb1[16]; /* default file control block 1 */
byte fcb2[16]; /* default file control block 2 */
byte res5[4]; /* reserved */
byte cmdTail[0x80]; /* command tail and disk transfer area */
} PSP;
static struct { /* EXE file header */
uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */
uint8_t sigHi;
uint16_t lastPageSize; /* Size of the last page */
uint16_t numPages; /* Number of pages in the file */
uint16_t numReloc; /* Number of relocation items */
uint16_t numParaHeader; /* # of paragraphs in the header */
uint16_t minAlloc; /* Minimum number of paragraphs */
uint16_t maxAlloc; /* Maximum number of paragraphs */
uint16_t initSS; /* Segment displacement of stack */
uint16_t initSP; /* Contents of SP at entry */
uint16_t checkSum; /* Complemented checksum */
uint16_t initIP; /* Contents of IP at entry */
uint16_t initCS; /* Segment displacement of code */
uint16_t relocTabOffset; /* Relocation table offset */
uint16_t overlayNum; /* Overlay number */
byte sigLo; /* .EXE signature: 0x4D 0x5A */
byte sigHi;
word lastPageSize; /* Size of the last page */
word numPages; /* Number of pages in the file */
word numReloc; /* Number of relocation items */
word numParaHeader; /* # of paragraphs in the header */
word minAlloc; /* Minimum number of paragraphs */
word maxAlloc; /* Maximum number of paragraphs */
word initSS; /* Segment displacement of stack */
word initSP; /* Contents of SP at entry */
word checkSum; /* Complemented checksum */
word initIP; /* Contents of IP at entry */
word initCS; /* Segment displacement of code */
word relocTabOffset; /* Relocation table offset */
word overlayNum; /* Overlay number */
} header;
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
@ -55,294 +58,440 @@ static void displayLoadInfo(void);
static void displayMemMap(void);
/*****************************************************************************
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
* rewritter, and displays any useful information.
****************************************************************************/
extern Project g_proj;
bool DccFrontend::FrontEnd ()
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
* rewritter, and displays any useful information.
****************************************************************************/
void FrontEnd (char *filename, PCALL_GRAPH *pcallGraph)
{
PPROC pProc;
PSYM psym;
Int i, c;
g_proj.callGraph = 0;
g_proj.m_fname = m_fname;
/* Load program into memory */
LoadImage(filename);
/* Load program into memory */
LoadImage(g_proj);
if (option.verbose)
{
displayLoadInfo();
}
if (option.verbose)
displayLoadInfo();
/* Do depth first flow analysis building call graph and procedure list,
* and attaching the I-code to each procedure */
parse (pcallGraph);
/* Do depth first flow analysis building call graph and procedure list,
* and attaching the I-code to each procedure */
parse (g_proj);
if (option.asm1)
{
printf("dcc: writing assembler file %s\n", asm1_name);
}
if (option.asm1)
{
printf("dcc: writing assembler file %s\n", asm1_name);
}
/* Search through code looking for impure references and flag them */
for (pProc = pProcList; pProc; pProc = pProc->next)
{
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);
}
/* Search through code looking for impure references and flag them */
Disassembler ds(1);
for(Function &f : g_proj.pProcList)
{
f.markImpure();
if (option.asm1)
{
ds.disassem(&f);
}
}
if (option.Interact)
{
interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */
}
if (option.Interact)
{
interactDis(pProcList, 0); /* Interactive disassembler */
}
/* Converts jump target addresses to icode offsets */
for(Function &f : g_proj.pProcList)
{
f.bindIcodeOff();
}
/* Print memory bitmap */
if (option.Map)
displayMemMap();
return(true); // we no longer own proj !
/* Converts jump target addresses to icode offsets */
for (pProc = pProcList; pProc; pProc = pProc->next)
bindIcodeOff (pProc);
/* Print memory bitmap */
if (option.Map)
displayMemMap();
}
/****************************************************************************
* displayLoadInfo - Displays low level loader type info.
***************************************************************************/
* displayLoadInfo - Displays low level loader type info.
***************************************************************************/
static void displayLoadInfo(void)
{
PROG &prog(Project::get()->prog);
int i;
Int i;
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
if (! prog.fCOM) {
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
printf("# relocation items = %04X\n", LH(&header.numReloc));
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
}
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
if (! prog.fCOM) {
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
printf("# relocation items = %04X\n", LH(&header.numReloc));
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
}
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
if (option.VeryVerbose && prog.cReloc)
{
printf("\nRelocation Table\n");
for (i = 0; i < prog.cReloc; i++)
{
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.Image + prog.relocTable[i]));
}
}
printf("\n");
if (option.VeryVerbose && prog.cReloc)
{
printf("\nRelocation Table\n");
for (i = 0; i < prog.cReloc; i++)
{
printf("%06X -> [%04X]\n", prog.relocTable[i],
LH(prog.Image + prog.relocTable[i]));
}
}
printf("\n");
}
/*****************************************************************************
* fill - Fills line for displayMemMap()
****************************************************************************/
static void fill(int ip, char *bf)
* fill - Fills line for displayMemMap()
****************************************************************************/
static void fill(Int ip, char *bf)
{
PROG &prog(Project::get()->prog);
static uint8_t type[4] = {'.', 'd', 'c', 'x'};
uint8_t i;
static byte type[4] = {'.', 'd', 'c', 'x'};
byte i;
for (i = 0; i < 16; i++, ip++)
{
*bf++ = ' ';
*bf++ = (ip < prog.cbImage)? type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
}
*bf = '\0';
for (i = 0; i < 16; i++, ip++)
{
*bf++ = ' ';
*bf++ = (ip < prog.cbImage)?
type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
}
*bf = '\0';
}
/*****************************************************************************
* displayMemMap - Displays the memory bitmap
****************************************************************************/
* displayMemMap - Displays the memory bitmap
****************************************************************************/
static void displayMemMap(void)
{
PROG &prog(Project::get()->prog);
char c, b1[33], b2[33], b3[33];
byte i;
Int ip = 0;
char c, b1[33], b2[33], b3[33];
uint8_t i;
int ip = 0;
printf("\nMemory Map\n");
while (ip < prog.cbImage)
{
fill(ip, b1);
printf("%06X %s\n", ip, b1);
ip += 16;
for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
; /* Check if all same */
if (i > 32)
{
fill(ip, b2); /* Skip until next two are not same */
fill(ip+16, b3);
if (! (strcmp(b1, b2) || strcmp(b1, b3)))
{
printf(" :\n");
do
{
ip += 16;
fill(ip+16, b1);
} while (! strcmp(b1, b2));
}
}
}
printf("\n");
printf("\nMemory Map\n");
while (ip < prog.cbImage)
{
fill(ip, b1);
printf("%06X %s\n", ip, b1);
ip += 16;
for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
; /* Check if all same */
if (i > 32)
{
fill(ip, b2); /* Skip until next two are not same */
fill(ip+16, b3);
if (! (strcmp(b1, b2) || strcmp(b1, b3)))
{
printf(" :\n");
do
{
ip += 16;
fill(ip+16, b1);
} while (! strcmp(b1, b2));
}
}
}
printf("\n");
}
/*****************************************************************************
* LoadImage
****************************************************************************/
void DccFrontend::LoadImage(Project &proj)
* LoadImage
****************************************************************************/
static void LoadImage(char *filename)
{
PROG &prog(Project::get()->prog);
FILE *fp;
int i, cb;
uint8_t buf[4];
FILE *fp;
Int i, cb;
byte buf[4];
/* Open the input file */
if ((fp = fopen(proj.m_fname.c_str(), "rb")) == NULL)
{
fatalError(CANNOT_OPEN, proj.m_fname.c_str());
}
/* Open the input file */
if ((fp = fopen(filename, "rb")) == NULL)
{
fatalError(CANNOT_OPEN, filename);
}
/* Read in first 2 bytes to check EXE signature */
if (fread(&header, 1, 2, fp) != 2)
{
fatalError(CANNOT_READ, proj.m_fname.c_str());
}
/* Read in first 2 bytes to check EXE signature */
if (fread(&header, 1, 2, fp) != 2)
{
fatalError(CANNOT_READ, filename);
}
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
/* Read rest of header */
fseek(fp, 0, SEEK_SET);
if (fread(&header, sizeof(header), 1, fp) != 1)
{
fatalError(CANNOT_READ, proj.m_fname.c_str());
}
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
/* Read rest of header */
fseek(fp, 0, SEEK_SET);
if (fread(&header, sizeof(header), 1, fp) != 1)
{
fatalError(CANNOT_READ, filename);
}
/* This is a typical DOS kludge! */
if (LH(&header.relocTabOffset) == 0x40)
{
fatalError(NEWEXE_FORMAT);
}
/* This is a typical DOS kludge! */
if (LH(&header.relocTabOffset) == 0x40)
{
fatalError(NEWEXE_FORMAT);
}
/* Calculate the load module size.
* This is the number of pages in the file
* less the length of the header and reloc table
* less the number of bytes unused on last page
*/
cb = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16;
if (header.lastPageSize)
{
cb -= 512 - LH(&header.lastPageSize);
}
/* Calculate the load module size.
* This is the number of pages in the file
* less the length of the header and reloc table
* less the number of bytes unused on last page
*/
cb = (dword)LH(&header.numPages) * 512 - (dword)LH(&header.numParaHeader) * 16;
if (header.lastPageSize)
{
cb -= 512 - LH(&header.lastPageSize);
}
/* We quietly ignore minAlloc and maxAlloc since for our
* purposes it doesn't really matter where in real memory
* the program would end up. EXE programs can't really rely on
* their load location so setting the PSP segment to 0 is fine.
* Certainly programs that prod around in DOS or BIOS are going
* to have to load DS from a constant so it'll be pretty
* obvious.
*/
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
prog.initIP = (int16_t)LH(&header.initIP);
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
prog.initSP = (int16_t)LH(&header.initSP);
prog.cReloc = (int16_t)LH(&header.numReloc);
/* 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);
/* Allocate the relocation table */
if (prog.cReloc)
{
prog.relocTable = new uint32_t [prog.cReloc];
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
/* Allocate the relocation table */
if (prog.cReloc)
{
prog.relocTable = (dword*)allocMem(prog.cReloc * sizeof(Int));
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
/* Read in seg:offset pairs and convert to Image ptrs */
for (i = 0; i < prog.cReloc; i++)
{
fread(buf, 1, 4, fp);
prog.relocTable[i] = LH(buf) +
(((int)LH(buf+2) + EXE_RELOCATION)<<4);
}
}
/* Seek to start of image */
uint32_t start_of_image= LH(&header.numParaHeader) * 16;
fseek(fp, start_of_image, SEEK_SET);
}
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 */
for (i = 0; i < prog.cReloc; i++)
{
fread(buf, 1, 4, fp);
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);
/* COM programs start off with an ORG 100H (to leave room for a PSP)
* 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;
/* COM programs start off with an ORG 100H (to leave room for a PSP)
* 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);
}
fseek(fp, 0, SEEK_SET);
}
/* Allocate a block of memory for the program. */
prog.cbImage = cb + sizeof(PSP);
prog.Image = new uint8_t [prog.cbImage];
prog.Image[0] = 0xCD; /* Fill in PSP int 20h location */
prog.Image[1] = 0x20; /* for termination checking */
/* 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 */
/* Read in the image past where a PSP would go */
if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
{
fatalError(CANNOT_READ, proj.m_fname.c_str());
}
/* Read in the image past where a PSP would go */
#ifdef __DOSWIN__
if (cb > 0xFFFF)
{
printf("Image size of %ld bytes too large for fread!\n", cb);
fatalError(CANNOT_READ, filename);
}
#endif
if (cb != (Int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
{
fatalError(CANNOT_READ, filename);
}
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (uint8_t *)malloc(cb);
memset(prog.map, BM_UNKNOWN, (size_t)cb);
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb);
/* Relocate segment constants */
if (prog.cReloc)
{
for (i = 0; i < prog.cReloc; i++)
{
uint8_t *p = &prog.Image[prog.relocTable[i]];
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
*p++ = (uint8_t)(w & 0x00FF);
*p = (uint8_t)((w & 0xFF00) >> 8);
}
}
/* Relocate segment constants */
if (prog.cReloc)
{
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);
}
}
fclose(fp);
fclose(fp);
}
/*****************************************************************************
* allocMem - malloc with failure test
****************************************************************************/
void *allocMem(int cb)
* allocMem - malloc with failure test
****************************************************************************/
void *allocMem(Int cb)
{
uint8_t *p;
byte *p;
//printf("Attempt to allocMem %5ld bytes\n", cb);
//printf("Attempt to allocMem %5ld bytes\n", cb);
if (! (p = (uint8_t*)malloc((size_t)cb)))
/* if (! (p = (uint8_t*)calloc((size_t)cb, 1))) */
{
fatalError(MALLOC_FAILED, cb);
}
// printf("allocMem: %p\n", p);
return p;
#if 0 /* Microsoft specific heap debugging code */
switch (_heapset('Z'))
{
case _HEAPBADBEGIN: printf("aM: Bad heap begin\n"); break;
case _HEAPBADNODE: printf("aM: Bad heap node\n");
printf("Attempt to allocMem %5d bytes\n", cb);
{
_HEAPINFO hinfo;
int heapstatus;
boolT cont = TRUE;
hinfo._pentry = NULL;
while (cont)
{
switch (heapstatus = _heapwalk(&hinfo))
{
case _HEAPOK:
printf("%6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
break;
case _HEAPBADBEGIN:
printf("Heap bad begin\n");
break;
case _HEAPBADNODE:
printf("BAD NODE %6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
break;
case _HEAPEND:
cont = FALSE;
break;
case _HEAPBADPTR:
printf("INFO BAD %6s block at %Fp of size %4.4X\n",
(hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
hinfo._pentry, hinfo._size);
cont=FALSE;
}
}
}
getchar();
exit(1);
case _HEAPEMPTY: printf("aM: Heap empty\n"); getchar(); break;
case _HEAPOK:putchar('.');break;
}
#endif
if (! (p = (byte*)malloc((size_t)cb)))
/* if (! (p = (byte*)calloc((size_t)cb, 1))) */
{
fatalError(MALLOC_FAILED, cb);
}
/*printf("allocMem: %p\n", p);/**/
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

View File

@ -5,379 +5,365 @@
#include "dcc.h"
#include <string.h>
#if __BORLAND__
#include <alloc.h>
#else
#include <malloc.h> /* For free() */
#include "graph.h"
#include "project.h"
extern Project g_proj;
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
static void mergeFallThrough(Function * pProc, BB * pBB);
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
#endif
static PBB rmJMP(PPROC pProc, Int marker, PBB pBB);
static void mergeFallThrough(PPROC pProc, PBB pBB);
static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last);
/*****************************************************************************
* createCFG - Create the basic control flow graph
****************************************************************************/
void Function::createCFG()
PBB createCFG(PPROC pProc)
{
/* Splits Icode associated with the procedure into Basic Blocks.
* The links between BBs represent the control flow graph of the
* procedure.
* A Basic Block is defined to end on one of the following instructions:
* 1) Conditional and unconditional jumps
* 2) CALL(F)
* 3) RET(F)
* 4) On the instruction before a join (a flagged TARGET)
* 5) Repeated string instructions
* 6) End of procedure
*/
int i;
int ip;
BB * psBB;
BB * pBB;
iICODE pIcode = Icode.begin();
iICODE iStart = Icode.begin();
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);
/* Splits Icode associated with the procedure into Basic Blocks.
* The links between BBs represent the control flow graph of the
* procedure.
* A Basic Block is defined to end on one of the following instructions:
* 1) Conditional and unconditional jumps
* 2) CALL(F)
* 3) RET(F)
* 4) On the instruction before a join (a flagged TARGET)
* 5) Repeated string instructions
* 6) End of procedure
*/
Int i;
Int ip, start;
BB cfg;
PBB psBB;
PBB pBB = &cfg;
PICODE pIcode = pProc->Icode.GetFirstIcode();
}
cfg.next = NULL;
stats.numBBbef = stats.numBBaft = 0;
for (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 */
else if (not ll->testFlags(NO_CODE) )
{
switch (ll->getOpcode()) {
case iJB: case iJBE: case iJAE: case iJA:
case iJL: case iJLE: case iJGE: case iJG:
case iJE: case iJNE: case iJS: case iJNS:
case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ:
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
CondJumps:
//start = ip + 1;
iStart = ++iICODE(pIcode);
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
/* This is for jumps off into nowhere */
if ( ll->testFlags(NO_LABEL) )
{
pBB->edges.pop_back();
}
else
pBB->edges[1].ip = ll->src().getImm2();
break;
/* Only process icodes that have valid instructions */
else if ((pIcode->ic.ll.flg & NO_CODE) != NO_CODE)
{
switch (pIcode->ic.ll.opcode) {
case iJB: case iJBE: case iJAE: case iJA:
case iJL: case iJLE: case iJGE: case iJG:
case iJE: case iJNE: case iJS: case iJNS:
case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ:
pBB = newBB(pBB, start, ip, TWO_BRANCH, 2, pProc);
CondJumps:
start = ip + 1;
pBB->edges[0].ip = (dword)start;
/* This is for jumps off into nowhere */
if (pIcode->ic.ll.flg & NO_LABEL)
pBB->numOutEdges--;
else
pBB->edges[1].ip = pIcode->ic.ll.immed.op;
break;
case iLOOP: case iLOOPE: case iLOOPNE:
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
goto CondJumps;
case iLOOP: case iLOOPE: case iLOOPNE:
pBB = newBB(pBB, start, ip, LOOP_NODE, 2, pProc);
goto CondJumps;
case iJMPF: case iJMP:
if (ll->testFlags(SWITCH))
{
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
for (i = 0; i < ll->caseTbl2.size(); i++)
pBB->edges[i].ip = ll->caseTbl2[i];
hasCase = true;
}
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
{
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
case iJMPF: case iJMP:
if (pIcode->ic.ll.flg & SWITCH)
{
pBB = newBB(pBB, start, ip, MULTI_BRANCH,
pIcode->ic.ll.caseTbl.numEntries, pProc);
for (i = 0; i < pIcode->ic.ll.caseTbl.numEntries; i++)
pBB->edges[i].ip = pIcode->ic.ll.caseTbl.entries[i];
pProc->hasCase = TRUE;
}
else if ((pIcode->ic.ll.flg & (I | NO_LABEL)) == I) {
pBB = newBB(pBB, start, ip, ONE_BRANCH, 1, pProc);
pBB->edges[0].ip = pIcode->ic.ll.immed.op;
}
else
newBB(pBB, start, ip, NOWHERE_NODE, 0, pProc);
start = ip + 1;
break;
pBB->edges[0].ip = ll->src().getImm2();
}
else
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
iStart = ++iICODE(pIcode);
break;
case iCALLF: case iCALL:
{ PPROC p = pIcode->ic.ll.immed.proc.proc;
if (p)
i = ((p->flg) & TERMINATES) ? 0 : 1;
else
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:
{
Function * p = ll->src().proc.proc;
if (p)
i = ((p->flg) & TERMINATES) ? 0 : 1;
else
i = 1;
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
iStart = ++iICODE(pIcode);//start = ip + 1;
if (i)
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
}
break;
case iRET: case iRETF:
newBB(pBB, start, ip, RETURN_NODE, 0, pProc);
start = ip + 1;
break;
case iRET: case iRETF:
//BB::Create(start, ip, RETURN_NODE, 0, this);
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
iStart = ++iICODE(pIcode);
break;
default:
/* Check for exit to DOS */
if (pIcode->ic.ll.flg & TERMINATES)
{
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:
/* Check for exit to DOS */
iICODE next1=++iICODE(pIcode);
if ( ll->testFlags(TERMINATES) )
{
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
iStart = ++iICODE(pIcode); // start = ip + 1;
}
/* Check for a fall through */
else if (next1 != Icode.end())
{
if (next1->ll()->testFlags(TARGET | CASE))
{
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
iStart = ++iICODE(pIcode); // start = ip + 1;
pBB->addOutEdge(iStart->loc_ip);
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
}
}
break;
}
}
}
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);
}
}
/* Convert list of BBs into a graph */
for (pBB = cfg.next; pBB; pBB = pBB->next)
{
for (i = 0; i < pBB->numOutEdges; i++)
{
ip = pBB->edges[i].ip;
if (ip >= SYNTHESIZED_MIN)
fatalError (INVALID_SYNTHETIC_BB);
else
{
for (psBB = cfg.next; psBB; psBB = psBB->next)
if (psBB->start == ip)
{
pBB->edges[i].BBptr = psBB;
psBB->numInEdges++;
break;
}
if (! psBB)
fatalError(NO_BB, ip, pProc->name);
}
}
}
return cfg.next;
}
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
*****************************************************************************/
PBB newBB (PBB pBB, Int start, Int ip, byte nodeType, Int numOutEdges,
PPROC pproc)
{
PBB pnewBB;
pnewBB = allocStruc(BB);
memset (pnewBB, 0, sizeof(BB));
pnewBB->nodeType = nodeType; /* Initialise */
pnewBB->start = start;
pnewBB->length = ip - start + 1;
pnewBB->numOutEdges = (byte)numOutEdges;
pnewBB->immedDom = NO_DOM;
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
if (numOutEdges)
pnewBB->edges = (TYPEADR_TYPE*)allocMem(numOutEdges * sizeof(TYPEADR_TYPE));
/* Mark the basic block to which the icodes belong to, but only for
* real code basic blocks (ie. not interval bbs) */
if (start >= 0)
pproc->Icode.SetInBB(start, ip, pnewBB);
while (pBB->next) /* Link */
pBB = pBB->next;
pBB->next = pnewBB;
if (start != -1) { /* Only for code BB's */
stats.numBBbef++;
}
return pnewBB;
}
/*****************************************************************************
* freeCFG - Deallocates a cfg
****************************************************************************/
void Function::freeCFG()
void freeCFG(PBB cfg)
{
for(BB *p : heldBBs)
{
delete p;
}
PBB pBB;
for (pBB = cfg; pBB; pBB = cfg) {
if (pBB->inEdges)
free(pBB->inEdges);
if (pBB->edges)
free(pBB->edges);
cfg = pBB->next;
free(pBB);
}
}
/*****************************************************************************
* compressCFG - Remove redundancies and add in-edge information
****************************************************************************/
void Function::compressCFG()
{
BB *pNxt;
int ip, first=0, last;
void compressCFG(PPROC pProc)
{ PBB pBB, pNxt;
Int ip, first=0, last, i;
/* First pass over BB list removes redundant jumps of the form
* (Un)Conditional -> Unconditional jump */
for (BB *pBB : m_cfg)
{
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
continue;
for (TYPEADR_TYPE &edgeRef : pBB->edges)
{
ip = pBB->rbegin()->loc_ip;
pNxt = edgeRef.BBptr->rmJMP(ip, edgeRef.BBptr);
/* First pass over BB list removes redundant jumps of the form
* (Un)Conditional -> Unconditional jump */
for (pBB = pProc->cfg; pBB; pBB = pBB->next)
if (pBB->numInEdges != 0 && (pBB->nodeType == ONE_BRANCH ||
pBB->nodeType == TWO_BRANCH))
for (i = 0; i < pBB->numOutEdges; i++)
{
ip = pBB->start + pBB->length - 1;
pNxt = rmJMP(pProc, ip, pBB->edges[i].BBptr);
if (not pBB->edges.empty()) /* Might have been clobbered */
{
edgeRef.BBptr = pNxt;
assert(pBB->back().loc_ip==ip);
pBB->back().ll()->SetImmediateOp((uint32_t)pNxt->begin()->loc_ip);
//Icode[ip].SetImmediateOp((uint32_t)pNxt->begin());
}
}
}
if (pBB->numOutEdges) /* Might have been clobbered */
{
pBB->edges[i].BBptr = pNxt;
pProc->Icode.SetImmediateOp(ip, (dword)pNxt->start);
}
}
/* Next is a depth-first traversal merging any FALL_NODE or
* ONE_BRANCH that fall through to a node with that as their only
* in-edge. */
m_cfg.front()->mergeFallThrough(Icode);
/* Next is a depth-first traversal merging any FALL_NODE or
* ONE_BRANCH that fall through to a node with that as their only
* in-edge. */
mergeFallThrough(pProc, pProc->cfg);
/* Remove redundant BBs created by the above compressions
* and allocate in-edge arrays as required. */
stats.numBBaft = stats.numBBbef;
/* Remove redundant BBs created by the above compressions
* and allocate in-edge arrays as required. */
stats.numBBaft = stats.numBBbef;
for(auto iter=m_cfg.begin(); iter!=m_cfg.end(); ++iter)
{
BB * pBB = *iter;
if (pBB->inEdges.empty())
{
if (iter == m_cfg.begin()) /* Init it misses out on */
pBB->index = UN_INIT;
else
{
delete pBB;
stats.numBBaft--;
}
}
else
{
pBB->inEdgeCount = pBB->inEdges.size();
}
}
for (pBB = pProc->cfg; pBB; pBB = pNxt)
{
pNxt = pBB->next;
if (pBB->numInEdges == 0)
{
if (pBB == pProc->cfg) /* Init it misses out on */
pBB->index = UN_INIT;
else
{
if (pBB->numOutEdges)
free(pBB->edges);
free(pBB);
stats.numBBaft--;
}
}
else
{
pBB->inEdgeCount = pBB->numInEdges;
pBB->inEdges = (PBB*)allocMem(pBB->numInEdges * sizeof(PBB));
}
}
/* Allocate storage for dfsLast[] array */
numBBs = stats.numBBaft;
m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *))
/* Allocate storage for dfsLast[] array */
pProc->numBBs = stats.numBBaft;
pProc->dfsLast = (PBB*)allocMem(pProc->numBBs * sizeof(PBB));
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
last = numBBs - 1;
m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
last = pProc->numBBs - 1;
dfsNumbering(pProc->cfg, pProc->dfsLast, &first, &last);
}
/****************************************************************************
* rmJMP - If BB addressed is just a JMP it is replaced with its target
***************************************************************************/
BB *BB::rmJMP(int marker, BB * pBB)
static PBB rmJMP(PPROC pProc, Int marker, PBB pBB)
{
marker += (int)DFS_JMP;
marker += DFS_JMP;
while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1)
{
if (pBB->traversed != marker)
{
pBB->traversed = (eDFS)marker;
pBB->inEdges.pop_back();
if (not pBB->inEdges.empty())
{
pBB->edges[0].BBptr->inEdges.push_back((BB *)nullptr);
}
else
{
pBB->front().ll()->setFlags(NO_CODE);
pBB->front().invalidate(); //pProc->Icode.SetLlInvalid(pBB->begin(), true);
}
while (pBB->nodeType == ONE_BRANCH && pBB->length == 1) {
if (pBB->traversed != marker) {
pBB->traversed = marker;
if (--pBB->numInEdges)
pBB->edges[0].BBptr->numInEdges++;
else
{
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
}
pBB = pBB->edges[0].BBptr;
}
else
{
/* We are going around in circles */
pBB->nodeType = NOWHERE_NODE;
pBB->front().ll()->replaceSrc(LLOperand::CreateImm2(pBB->front().loc_ip));
//pBB->front().ll()->src.immed.op = pBB->front().loc_ip;
do {
pBB = pBB->edges[0].BBptr;
pBB->inEdges.pop_back(); // was --numInedges
if (! pBB->inEdges.empty())
{
pBB->front().ll()->setFlags(NO_CODE);
pBB->front().invalidate();
// pProc->Icode.setFlags(pBB->start, NO_CODE);
// pProc->Icode.SetLlInvalid(pBB->start, true);
}
} while (pBB->nodeType != NOWHERE_NODE);
pBB = pBB->edges[0].BBptr;
}
else { /* We are going around in circles */
pBB->nodeType = NOWHERE_NODE;
pProc->Icode.GetIcode(pBB->start)->ic.ll.immed.op = (dword)pBB->start;
pProc->Icode.SetImmediateOp(pBB->start, (dword)pBB->start);
do {
pBB = pBB->edges[0].BBptr;
if (! --pBB->numInEdges)
{
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
}
} while (pBB->nodeType != NOWHERE_NODE);
pBB->edges.clear();
}
}
return pBB;
free(pBB->edges);
pBB->numOutEdges = 0;
pBB->edges = NULL;
}
}
return pBB;
}
/*****************************************************************************
* mergeFallThrough
****************************************************************************/
void BB::mergeFallThrough( CIcodeRec &Icode)
static void mergeFallThrough(PPROC pProc, PBB pBB)
{
BB * pChild;
int i;
PBB pChild;
Int i, ip;
if (!this)
{
printf("mergeFallThrough on empty BB!\n");
}
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
{
pChild = edges[0].BBptr;
/* Jump to next instruction can always be removed */
if (nodeType == ONE_BRANCH)
{
assert(Parent==pChild->Parent);
if(back().loc_ip>pChild->front().loc_ip) // back edege
break;
auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c)
{return not c.ll()->testFlags(NO_CODE);});
if (pBB) {
while (pBB->nodeType == FALL_NODE || pBB->nodeType == ONE_BRANCH)
{
pChild = pBB->edges[0].BBptr;
/* Jump to next instruction can always be removed */
if (pBB->nodeType == ONE_BRANCH)
{
ip = pBB->start + pBB->length;
for (i = ip; i < pChild->start
&& (pProc->Icode.GetLlFlag(i) & NO_CODE); i++);
if (i != pChild->start)
break;
pProc->Icode.SetLlFlag(ip - 1, NO_CODE);
pProc->Icode.SetLlInvalid(ip - 1, TRUE);
pBB->nodeType = FALL_NODE;
pBB->length--;
if (iter != pChild->begin())
break;
back().ll()->setFlags(NO_CODE);
back().invalidate();
nodeType = FALL_NODE;
//instructions.advance_end(-1); //TODO: causes creation of empty BB
}
/* If there's no other edges into child can merge */
if (pChild->inEdges.size() != 1)
break;
}
/* If there's no other edges into child can merge */
if (pChild->numInEdges != 1)
break;
nodeType = pChild->nodeType;
instructions = boost::make_iterator_range(begin(),pChild->end());
pChild->front().ll()->clrFlags(TARGET);
edges.swap(pChild->edges);
pBB->nodeType = pChild->nodeType;
pBB->length = pChild->start + pChild->length - pBB->start;
pProc->Icode.ClearLlFlag(pChild->start, TARGET);
pBB->numOutEdges = pChild->numOutEdges;
free(pBB->edges);
pBB->edges = pChild->edges;
pChild->inEdges.clear();
pChild->edges.clear();
}
traversed = DFS_MERGE;
pChild->numOutEdges = pChild->numInEdges = 0;
pChild->edges = NULL;
}
pBB->traversed = DFS_MERGE;
/* Process all out edges recursively */
for (i = 0; i < edges.size(); i++)
if (edges[i].BBptr->traversed != DFS_MERGE)
edges[i].BBptr->mergeFallThrough(Icode);
/* Process all out edges recursively */
for (i = 0; i < pBB->numOutEdges; i++)
if (pBB->edges[i].BBptr->traversed != DFS_MERGE)
mergeFallThrough(pProc, pBB->edges[i].BBptr);
}
}
@ -385,26 +371,30 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
* dfsNumbering - Numbers nodes during first and last visits and determine
* in-edges
****************************************************************************/
void BB::dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last)
static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last)
{
BB * pChild;
traversed = DFS_NUM;
dfsFirstNum = (*first)++;
PBB pChild;
byte i;
/* index is being used as an index to inEdges[]. */
// for (i = 0; i < edges.size(); i++)
for(auto edge : edges)
{
pChild = edge.BBptr;
pChild->inEdges[pChild->index++] = this;
if (pBB)
{
pBB->traversed = DFS_NUM;
pBB->dfsFirstNum = (*first)++;
/* Is this the last visit? */
if (pChild->index == pChild->inEdges.size())
pChild->index = UN_INIT;
/* index is being used as an index to inEdges[]. */
for (i = 0; i < pBB->numOutEdges; i++)
{
pChild = pBB->edges[i].BBptr;
pChild->inEdges[pChild->index++] = pBB;
if (pChild->traversed != DFS_NUM)
pChild->dfsNumbering(dfsLast, first, last);
}
dfsLastNum = *last;
dfsLast[(*last)--] = this;
/* Is this the last visit? */
if (pChild->index == pChild->numInEdges)
pChild->index = UN_INIT;
if (pChild->traversed != DFS_NUM)
dfsNumbering(pChild, dfsLast, first, last);
}
pBB->dfsLastNum = *last;
dfsLast[(*last)--] = pBB;
}
}

View File

@ -4,631 +4,483 @@
* Date: September-October 1993
* (C) Cristina Cifuentes
*/
#include <cassert>
#include <string.h>
#include <string>
#include <sstream>
#include "dcc.h"
using namespace std;
#define ICODE_DELTA 25
/* Masks off bits set by duReg[] */
std::bitset<32> maskDuReg[] = { 0x00,
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
0xEFFFFF, /* tmp reg */
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
dword maskDuReg[] = { 0x00,
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* word regs */
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* byte regs */
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
0xEFFFFF, /* tmp reg */
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
static char buf[lineSize]; /* Line buffer for hl icode output */
void newAsgnHlIcode (PICODE pIcode, COND_EXPR *lhs, COND_EXPR *rhs)
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
void HLTYPE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
{
set(lhs,rhs);
pIcode->type = HIGH_LEVEL;
pIcode->ic.hl.opcode = HLI_ASSIGN;
pIcode->ic.hl.oper.asgn.lhs = lhs;
pIcode->ic.hl.oper.asgn.rhs = rhs;
}
}
void ICODE::checkHlCall()
{
//assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
}
void newCallHlIcode (PICODE pIcode)
/* Places the new HLI_CALL high-level operand in the high-level icode array */
void ICODE::newCallHl()
{
type = HIGH_LEVEL;
hl()->opcode = HLI_CALL;
hl()->call.proc = ll()->src().proc.proc;
hl()->call.args = new STKFRAME;
if (ll()->src().proc.cb != 0)
hl()->call.args->cb = ll()->src().proc.cb;
else if(hl()->call.proc)
hl()->call.args->cb =hl()->call.proc->cbParam;
else
{
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
hl()->call.args->cb = 0;
}
pIcode->type = HIGH_LEVEL;
pIcode->ic.hl.opcode = HLI_CALL;
pIcode->ic.hl.oper.call.proc = pIcode->ic.ll.immed.proc.proc;
pIcode->ic.hl.oper.call.args = (STKFRAME*)allocMem (sizeof(STKFRAME));
memset (pIcode->ic.hl.oper.call.args, 0, sizeof(STKFRAME));
if (pIcode->ic.ll.immed.proc.cb != 0)
pIcode->ic.hl.oper.call.args->cb = pIcode->ic.ll.immed.proc.cb;
else
pIcode->ic.hl.oper.call.args->cb =pIcode->ic.hl.oper.call.proc->cbParam;
}
void newUnaryHlIcode (PICODE pIcode, hlIcode op, COND_EXPR *exp)
/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
* array */
void ICODE::setUnary(hlIcode op, COND_EXPR *_exp)
{
type = HIGH_LEVEL;
hl()->set(op,_exp);
pIcode->type = HIGH_LEVEL;
pIcode->ic.hl.opcode = op;
pIcode->ic.hl.oper.exp = exp;
}
void newJCondHlIcode (PICODE pIcode, COND_EXPR *cexp)
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
void ICODE::setJCond(COND_EXPR *cexp)
{
type = HIGH_LEVEL;
hl()->set(HLI_JCOND,cexp);
pIcode->type = HIGH_LEVEL;
pIcode->ic.hl.opcode = HLI_JCOND;
pIcode->ic.hl.oper.exp = cexp;
}
/* Sets the invalid field to true as this low-level icode is no longer valid,
void invalidateIcode (PICODE pIcode)
/* Sets the invalid field to TRUE as this low-level icode is no longer valid,
* it has been replaced by a high-level icode. */
void ICODE ::invalidate()
{
invalid = true;
pIcode->invalid = TRUE;
}
/* Removes the defined register regi from the lhs subtree.
* If all registers
* of this instruction are unused, the instruction is invalidated (ie. removed)
*/
bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
{
int numDefs;
boolT removeDefRegi (byte regi, PICODE picode, Int thisDefIdx, LOCAL_ID *locId)
/* Removes the defined register regi from the lhs subtree. If all registers
* of this instruction are unused, the instruction is invalidated (ie.
* removed) */
{ Int numDefs;
numDefs = du1.numRegsDef;
numDefs = picode->du1.numRegsDef;
if (numDefs == thisDefIdx)
{
for ( ; numDefs > 0; numDefs--)
{
if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
if ((picode->du1.idx[numDefs-1][0] != 0)||(picode->du.lastDefRegi))
break;
}
}
if (numDefs == 0)
{
invalidate();
return true;
invalidateIcode (picode);
return (TRUE);
}
HlTypeSupport *p=hl()->get();
if(p and p->removeRegFromLong(regi,locId))
{
du1.numRegsDef--;
du.def &= maskDuReg[regi];
}
return false;
}
HLTYPE LLInst::createCall()
{
HLTYPE res(HLI_CALL);
res.call.proc = src().proc.proc;
res.call.args = new STKFRAME;
if (src().proc.cb != 0)
res.call.args->cb = src().proc.cb;
else if(res.call.proc)
res.call.args->cb =res.call.proc->cbParam;
else
{
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
res.call.args->cb = 0;
switch (picode->ic.hl.opcode) {
case HLI_ASSIGN: removeRegFromLong (regi, locId,
picode->ic.hl.oper.asgn.lhs);
picode->du1.numRegsDef--;
picode->du.def &= maskDuReg[regi];
break;
case 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:
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
void highLevelGen (PPROC pProc)
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
* Note: this process should be done before data flow analysis, which
* refines the HIGH_LEVEL icodes. */
void Function::highLevelGen()
{
int numIcode; /* number of icode instructions */
iICODE pIcode; /* ptr to current icode node */
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
uint32_t _flg; /* icode flags */
numIcode = Icode.size();
for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
{ Int i, /* idx into icode array */
numIcode; /* number of icode instructions */
PICODE pIcode; /* ptr to current icode node */
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
flags32 flg; /* icode flags */
numIcode = pProc->Icode.GetNumIcodes();
for (i = 0; i < numIcode; i++)
{
assert(numIcode==Icode.size());
pIcode = i; //Icode.GetIcode(i)
LLInst *ll = pIcode->ll();
if ( ll->testFlags(NOT_HLL) )
pIcode->invalidate();
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
continue;
_flg = ll->getFlag();
if ((_flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
if ((_flg & NO_OPS) != NO_OPS) /* if there are opers */
{
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())
pIcode = pProc->Icode.GetIcode(i);
if ((pIcode->ic.ll.flg & NOT_HLL) == NOT_HLL)
invalidateIcode (pIcode);
if ((pIcode->type == LOW_LEVEL) && (pIcode->invalid == FALSE))
{
case iADD:
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
pIcode->setAsgn(lhs, rhs);
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) )
flg = pIcode->ic.ll.flg;
if ((flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
if ((flg & NO_OPS) != NO_OPS) /* if there are opers */
{
lhs = COND_EXPR::idReg (rAL, 0, &localId);
pIcode->setRegDU( rAL, eDEF);
if ((flg & NO_SRC) != NO_SRC) /* if there is src op */
rhs = idCondExp (pIcode, SRC, pProc, i, pIcode, NONE);
lhs = idCondExp (pIcode, DST, pProc, i, pIcode, NONE);
}
else
{
lhs = COND_EXPR::idReg (rAX, 0, &localId);
pIcode->setRegDU( rAX, eDEF);
}
pIcode->setAsgn(lhs, rhs);
break;
case iIMUL:
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
pIcode->setAsgn(lhs, rhs);
break;
switch (pIcode->ic.ll.opcode) {
case iADD: rhs = boolCondExp (lhs, rhs, ADD);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iINC:
rhs = COND_EXPR::idKte (1, 2);
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
pIcode->setAsgn(lhs, rhs);
break;
case iAND: rhs = boolCondExp (lhs, rhs, AND);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iLEA:
rhs = COND_EXPR::unary (ADDRESSOF, rhs);
pIcode->setAsgn(lhs, rhs);
break;
case iCALL:
case iCALLF: newCallHlIcode (pIcode);
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);
}
pIcode->setAsgn(lhs, rhs);
break;
case iDEC: rhs = idCondExpKte (1, 2);
rhs = boolCondExp (lhs, rhs, SUB);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iMOV: pIcode->setAsgn(lhs, rhs);
break;
case iDIV:
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:
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
pIcode->setAsgn(lhs, rhs);
break;
case iIMUL: rhs = boolCondExp (lhs, rhs, MUL);
lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode,
NONE);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iNEG:
rhs = COND_EXPR::unary (NEGATION, lhs);
pIcode->setAsgn(lhs, rhs);
break;
case iINC: rhs = idCondExpKte (1, 2);
rhs = boolCondExp (lhs, rhs, ADD);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iNOT:
rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
pIcode->setAsgn(lhs, rhs);
break;
case iLEA: rhs = unaryCondExp (ADDRESSOF, rhs);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iOR:
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
pIcode->setAsgn(lhs, rhs);
break;
case iMOD: rhs = boolCondExp (lhs, rhs, MOD);
if (pIcode->ic.ll.flg & B)
{
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);
break;
case iMOV: newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
break;
case iMUL: rhs = boolCondExp (lhs, rhs, MUL);
lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode,
NONE);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iRET:
case iRETF: pIcode->setUnary(HLI_RET, NULL);
break;
case iNEG: rhs = unaryCondExp (NEGATION, lhs);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iSHL:
rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
pIcode->setAsgn(lhs, rhs);
break;
case iNOT: rhs = boolCondExp (NULL, rhs, NOT);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iSAR: /* signed */
case iSHR:
rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
pIcode->setAsgn(lhs, rhs);
break;
case iOR: rhs = boolCondExp (lhs, rhs, OR);
newAsgnHlIcode (pIcode, lhs, rhs);
break;
case iSIGNEX: pIcode->setAsgn(lhs, rhs);
break;
case iPOP: newUnaryHlIcode (pIcode, HLI_POP, lhs);
break;
case iSUB:
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
pIcode->setAsgn(lhs, rhs);
break;
case iPUSH: newUnaryHlIcode (pIcode, HLI_PUSH, lhs);
break;
case iXCHG:
break;
case iRET:
case iRETF: newUnaryHlIcode (pIcode, HLI_RET, NULL);
break;
case iXOR:
rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
pIcode->setAsgn(lhs, rhs);
break;
case iSHL: rhs = boolCondExp (lhs, rhs, SHL);
newAsgnHlIcode (pIcode, lhs, rhs);
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
* in if..then[..else] statements, to reflect the condition that takes the
* then part. */
COND_EXPR *COND_EXPR::inverse () const
{
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
DUMMY, DBL_OR, DBL_AND};
COND_EXPR *res=0;
if (m_type == BOOLEAN_OP)
{
switch ( op() )
{
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;
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
DUMMY, DBL_OR, DBL_AND};
if (*exp == NULL) return;
case AND: case OR: case XOR: case NOT: case ADD:
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
return COND_EXPR::unary (NEGATION, this->clone());
if ((*exp)->type == BOOLEAN_OP)
{
switch ((*exp)->expr.boolExpr.op) {
case LESS_EQUAL: case LESS: case EQUAL:
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
break;
case DBL_AND: case DBL_OR:
// Binary::Create(invertop,lhs->inverse(),rhs->inverse());
res = this->clone();
res->boolExpr.op = invCondOp[op()];
res->boolExpr.lhs=lhs()->inverse ();
res->boolExpr.rhs=rhs()->inverse ();
return res;
} /* eos */
case AND: case OR: case XOR: case NOT: case ADD:
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
*exp = unaryCondExp (NEGATION, *exp);
break;
}
else if (m_type == NEGATION) //TODO: memleak here
{
return expr.unaryExp->clone();
}
return this->clone();
/* other types are left unmodified */
case DBL_AND: case DBL_OR:
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
inverseCondOp (&(*exp)->expr.boolExpr.lhs);
inverseCondOp (&(*exp)->expr.boolExpr.rhs);
break;
} /* eos */
}
else if ((*exp)->type == NEGATION)
*exp = (*exp)->expr.unaryExp;
/* other types are left unmodified */
}
char *writeCall (PPROC tproc, PSTKFRAME args, PPROC pproc, Int *numLoc)
/* Returns the string that represents the procedure call of tproc (ie. with
* actual parameters) */
std::string writeCall (Function * tproc, STKFRAME & args, Function * pproc, int *numLoc)
{
int i; /* counter of # arguments */
string condExp;
ostringstream ostr;
ostr<<tproc->name<<" (";
for(const STKSYM &sym : args)
{ Int i; /* counter of # arguments */
char *s, *condExp;
s = (char*)allocMem (100 * sizeof(char));
s[0] = '\0';
sprintf (s, "%s (", tproc->name);
for (i = 0; i < args->csym; i++)
{
ostr << walkCondExpr (sym.actual, pproc, numLoc);
if((&sym)!=&(args.back()))
ostr << ", ";
condExp = walkCondExpr (args->sym[i].actual, pproc, numLoc);
strcat (s, condExp);
if (i < (args->csym - 1))
strcat (s, ", ");
}
ostr << ")";
return ostr.str();
strcat (s, ")");
return (s);
}
char *writeJcond (HLTYPE h, PPROC pProc, Int *numLoc)
/* Displays the output of a HLI_JCOND icode. */
char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
{
assert(h.expr());
{ char *e;
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
buf[0] = '\0';
strcat (buf, "if ");
COND_EXPR *inverted=h.expr()->inverse();
//inverseCondOp (&h.exp);
std::string e = walkCondExpr (inverted, pProc, numLoc);
delete inverted;
strcat (buf, e.c_str());
inverseCondOp (&h.oper.exp);
e = walkCondExpr (h.oper.exp, pProc, numLoc);
strcat (buf, e);
strcat (buf, " {\n");
return (buf);
return (buf);
}
char *writeJcondInv (HLTYPE h, PPROC pProc, Int *numLoc)
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case
* when the THEN clause of an if..then..else is empty. The clause is
* negated and the ELSE clause is used instead. */
char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc)
{
{ char *e;
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
buf[0] = '\0';
strcat (buf, "if ");
std::string e = walkCondExpr (h.expr(), pProc, numLoc);
strcat (buf, e.c_str());
e = walkCondExpr (h.oper.exp, pProc, numLoc);
strcat (buf, e);
strcat (buf, " {\n");
return (buf);
return (buf);
}
string AssignType::writeOut(Function *pProc, int *numLoc)
{
ostringstream ostr;
ostr << walkCondExpr (lhs, pProc, numLoc);
ostr << " = ";
ostr << walkCondExpr (rhs, pProc, numLoc);
ostr << ";\n";
return ostr.str();
}
string CallType::writeOut(Function *pProc, int *numLoc)
{
ostringstream ostr;
ostr << writeCall (proc, *args, pProc,numLoc);
ostr << ";\n";
return ostr.str();
}
string ExpType::writeOut(Function *pProc, int *numLoc)
{
return walkCondExpr (v, pProc, numLoc);
}
char *write1HlIcode (HLTYPE h, PPROC pProc, Int *numLoc)
/* Returns a string with the contents of the current high-level icode.
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
* done in a separate routine to be able to support the removal of
* empty THEN clauses on an if..then..else. */
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
{
string e;
ostringstream ostr;
HlTypeSupport *p = get();
switch (opcode)
{
case HLI_ASSIGN:
return p->writeOut(pProc,numLoc);
case HLI_CALL:
return p->writeOut(pProc,numLoc);
case HLI_RET:
e = p->writeOut(pProc,numLoc);
if (! e.empty())
ostr << "return (" << e << ");\n";
break;
case HLI_POP:
ostr << "HLI_POP ";
ostr << p->writeOut(pProc,numLoc);
ostr << "\n";
break;
case HLI_PUSH:
ostr << "HLI_PUSH ";
ostr << p->writeOut(pProc,numLoc);
ostr << "\n";
break;
{ char *e;
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
switch (h.opcode) {
case HLI_ASSIGN: e = walkCondExpr (h.oper.asgn.lhs, pProc, numLoc);
strcat (buf, e);
strcat (buf, " = ");
e = walkCondExpr (h.oper.asgn.rhs, pProc, numLoc);
strcat (buf, e);
strcat (buf, ";\n");
break;
case HLI_CALL: e = writeCall (h.oper.call.proc, h.oper.call.args, pProc,
numLoc);
strcat (buf, e);
strcat (buf, ";\n");
break;
case HLI_RET: e = walkCondExpr (h.oper.exp, pProc, numLoc);
if (e[0] != '\0')
{
strcat (buf, "return (");
strcat (buf, e);
strcat (buf, ");\n");
}
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
//TODO: replace all >= INDEX_BX_SI with machine_x86::isRegExpression
Int power2 (Int i)
/* Returns the value of 2 to the power of i */
{
if (i == 0)
return (1);
return (2 << (i-1));
}
void writeDU (PICODE pIcode, Int idx)
/* Writes the registers/stack variables that are used and defined by this
* instruction. */
void ICODE::writeDU()
{
int my_idx = loc_ip;
{ static char buf[100];
Int i, j;
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
for (i = 0; i < (INDEXBASE-1); i++)
{
ostringstream ostr;
Machine_X86::writeRegVector(ostr,du.def);
if (!ostr.str().empty())
printf ("Def (reg) = %s\n", ostr.str().c_str());
if ((pIcode->du.def & power2(i)) != 0)
{
strcat (buf, allRegs[i]);
strcat (buf, " ");
}
}
if (buf[0] != '\0')
printf ("Def (reg) = %s\n", buf);
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
for (i = 0; i < INDEXBASE; i++)
{
ostringstream ostr;
Machine_X86::writeRegVector(ostr,du.use);
if (!ostr.str().empty())
printf ("Use (reg) = %s\n", ostr.str().c_str());
if ((pIcode->du.use & power2(i)) != 0)
{
strcat (buf, allRegs[i]);
strcat (buf, " ");
}
}
if (buf[0] != '\0')
printf ("Use (reg) = %s\n", buf);
/* Print du1 chain */
printf ("# regs defined = %d\n", du1.numRegsDef);
for (int i = 0; i < MAX_REGS_DEF; i++)
{
if (not du1.used(i))
continue;
printf ("%d: du1[%d][] = ", my_idx, i);
for(auto j : du1.idx[i].uses)
printf ("# regs defined = %d\n", pIcode->du1.numRegsDef);
for (i = 0; i < MAX_REGS_DEF; i++)
if (pIcode->du1.idx[i][0] != 0)
{
printf ("%d: du1[%d][] = ", idx, i);
for (j = 0; j < MAX_USES; j++)
{
printf ("%d ", j->loc_ip);
if (pIcode->du1.idx[i][j] == 0)
break;
printf ("%d ", pIcode->du1.idx[i][j]);
}
printf ("\n");
}
}
/* For HLI_CALL, print # parameter bytes */
if (hl()->opcode == HLI_CALL)
printf ("# param bytes = %d\n", hl()->call.args->cb);
if (pIcode->ic.hl.opcode == HLI_CALL)
printf ("# param bytes = %d\n", pIcode->ic.hl.oper.call.args->cb);
printf ("\n");
}
void freeHlIcode (PICODE icode, Int numIcodes)
/* Frees the storage allocated to h->hlIcode */
{ Int i;
HLTYPE h;
for (i = 0; i < numIcodes; i++)
{
h = icode[i].ic.hl;
switch (h.opcode) {
case HLI_ASSIGN: freeCondExpr (h.oper.asgn.lhs);
freeCondExpr (h.oper.asgn.rhs);
break;
case HLI_POP: case HLI_PUSH:
case HLI_JCOND: freeCondExpr (h.oper.exp);
break;
}
}
}

View File

@ -5,98 +5,139 @@
#include <malloc.h>
#include <memory.h>
#include "dcc.h"
#include "types.h" // Common types like uint8_t, etc
#include "types.h" // Common types like byte, etc
#include "ast.h" // Some icode types depend on these
#include "icode.h"
void *reallocVar(void *p, Int newsize); /* frontend.c !? */
#define ICODE_DELTA 25 // Amount to allocate for new chunk
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level;
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level;
CIcodeRec::CIcodeRec()
{
numIcode = 0;
alloc = 0;
icode = 0; // Initialise the pointer to 0
}
CIcodeRec::~CIcodeRec()
{
if (icode)
{
free(icode);
}
}
PICODE CIcodeRec::addIcode(PICODE pIcode)
/* Copies the icode that is pointed to by pIcode to the icode array.
* If there is need to allocate extra memory, it is done so, and
* the alloc variable is adjusted. */
ICODE * CIcodeRec::addIcode(ICODE *pIcode)
{
push_back(*pIcode);
back().loc_ip = size()-1;
return &back();
}
PICODE resIcode;
void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB)
{
for(ICODE &ic : rang)
if (numIcode == alloc)
{
ic.setParent(pnewBB);
alloc += ICODE_DELTA;
icode = (PICODE)reallocVar(icode, alloc * sizeof(ICODE));
memset (&icode[numIcode], 0, ICODE_DELTA * sizeof(ICODE));
}
resIcode = (PICODE)memcpy (&icode[numIcode], pIcode,
sizeof(ICODE));
numIcode++;
return (resIcode);
}
PICODE CIcodeRec::GetFirstIcode()
{
return icode;
}
/* Don't need this; just pIcode++ since array is guaranteed to be contiguous
PICODE CIcodeRec::GetNextIcode(PICODE pCurIcode)
{
int idx = pCurIcode - icode; // Current index
ASSERT(idx+1 < numIcode);
return &icode[idx+1];
}
*/
boolT CIcodeRec::IsValid(PICODE pCurIcode)
{
int idx = pCurIcode - icode; // Current index
return idx < numIcode;
}
int CIcodeRec::GetNumIcodes()
{
return numIcode;
}
void CIcodeRec::SetInBB(int start, int end, struct _BB* pnewBB)
{
for (int i = start; i <= end; i++)
icode[i].inBB = pnewBB;
}
void CIcodeRec::SetImmediateOp(int ip, dword dw)
{
icode[ip].ic.ll.immed.op = dw;
}
void CIcodeRec::SetLlFlag(int ip, dword flag)
{
icode[ip].ic.ll.flg |= flag;
}
dword CIcodeRec::GetLlFlag(int ip)
{
return icode[ip].ic.ll.flg;
}
void CIcodeRec::ClearLlFlag(int ip, dword flag)
{
icode[ip].ic.ll.flg &= (~flag);
}
void CIcodeRec::SetLlInvalid(int ip, boolT fInv)
{
icode[ip].invalid = fInv;
}
dword CIcodeRec::GetLlLabel(int ip)
{
return icode[ip].ic.ll.label;
}
llIcode CIcodeRec::GetLlOpcode(int ip)
{
return icode[ip].ic.ll.opcode;
}
boolT CIcodeRec::labelSrch(dword target, Int *pIndex)
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
replaces *pIndex with an icode index */
bool CIcodeRec::labelSrch(uint32_t target, uint32_t &pIndex)
replaces *pIndex with an icode index */
{
iICODE location=labelSrch(target);
if(end()==location)
return false;
pIndex=location->loc_ip;
return true;
}
bool CIcodeRec::alreadyDecoded(uint32_t target)
{
iICODE location=labelSrch(target);
if(end()==location)
return false;
return true;
}
CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target)
{
return find_if(begin(),end(),[target](ICODE &l) -> bool {return l.ll()->label==target;});
}
ICODE * CIcodeRec::GetIcode(int ip)
{
assert(ip>=0 && ip<size());
iICODE res=begin();
advance(res,ip);
return &(*res);
}
Int i;
extern int getNextLabel();
extern bundle cCode;
/* Checks the given icode to determine whether it has a label associated
* to it. If so, a goto is emitted to this label; otherwise, a new label
* is created and a goto is also emitted.
* Note: this procedure is to be used when the label is to be backpatched
* onto code in cCode.code */
void LLInst::emitGotoLabel (int indLevel)
{
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */
for (i = 0; i < numIcode; i++)
{
/* Generate new label */
hllLabNum = getNextLabel();
setFlags(HLL_LABEL);
/* Node has been traversed already, so backpatch this label into
* the code */
cCode.code.addLabelBundle (codeIdx, hllLabNum);
if (icode[i].ic.ll.label == target)
{
*pIndex = i;
return TRUE;
}
}
cCode.appendCode( "%sgoto L%ld;\n", indentStr(indLevel), hllLabNum);
stats.numHLIcode++;
return FALSE;
}
bool LLOperand::isReg() const
PICODE CIcodeRec::GetIcode(int ip)
{
return (regi>=rAX) && (regi<=rTMP);
}
void LLOperand::addProcInformation(int param_count, uint32_t call_conv)
{
proc.proc->cbParam = (int16_t)param_count;
proc.cb = param_count;
proc.proc->flg |= call_conv;
return &icode[ip];
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -5,113 +5,127 @@
* (C) Cristina Cifuentes
*/
#include <cstring>
#include "locident.h"
#include "dcc.h"
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
{
return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h);
}
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
}
ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
loc=f;
}
#include <string.h>
#define LOCAL_ID_DELTA 25
#define IDX_ARRAY_DELTA 5
void insertIdx (IDX_ARRAY *list, Int idx)
/* Inserts the new index at the end of the list. If there is need to
* allocate extra storage, it does so. */
{
if (list->csym == list->alloc)
{
list->alloc += IDX_ARRAY_DELTA;
list->idx = (Int*)reallocVar(list->idx, list->alloc * sizeof(Int));
memset (&list->idx[list->csym], 0, IDX_ARRAY_DELTA * sizeof(Int));
}
list->idx[list->csym] = idx;
list->csym++;
}
static boolT inList (IDX_ARRAY *list, Int idx)
/* Returns whether idx is in the list array or not */
{ Int i;
for (i = 0; i < list->csym; i++)
if (list->idx[i] == idx)
return (TRUE);
return (FALSE);
}
static void newIdent (LOCAL_ID *locSym, hlType t, frameType f)
/* Creates a new identifier node of type t and returns it.
* Arguments: locSym : local long symbol table
* t : type of LONG identifier
* f : frame where this variable is located
* ix : index into icode array where this var is used */
void LOCAL_ID::newIdent(hlType t, frameType f)
{
ID newid(t,f);
id_arr.push_back(newid);
if (locSym->csym == locSym->alloc)
{
locSym->alloc += LOCAL_ID_DELTA;
locSym->id = (ID*)reallocVar(locSym->id, locSym->alloc * sizeof(ID));
memset (&locSym->id[locSym->csym], 0, LOCAL_ID_DELTA * sizeof(ID));
}
locSym->id[locSym->csym].type = t;
locSym->id[locSym->csym].loc = f;
locSym->csym++;
}
Int newByteWordRegId (LOCAL_ID *locSym, hlType t, byte regi)
/* Creates a new register identifier node of TYPE_BYTE_(UN)SIGN or
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
{
int idx;
{ Int idx;
/* Check for entry in the table */
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
return ((el.type == t) && (el.id.regi == regi));
});
if(found!=id_arr.end())
return found-id_arr.begin();
for (idx = 0; idx < locSym->csym; idx++)
{
if ((locSym->id[idx].type == t) &&
(locSym->id[idx].id.regi == regi))
return (idx);
}
/* Not in table, create new identifier */
newIdent (t, REG_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.regi = regi;
newIdent (locSym, t, REG_FRAME);
idx = locSym->csym - 1;
locSym->id[idx].id.regi = regi;
return (idx);
}
static void flagByteWordId (LOCAL_ID *locsym, Int off)
/* Flags the entry associated with the offset off to illegal, as this
* offset is part of a long stack variable.
* Note: it is easier enough to remove this entry by moving the rest of
* the array 1 position. The problem is that indexes into this
* array have already been saved in several positions; therefore,
* flagging this entry as illegal is all that can be done. */
void LOCAL_ID::flagByteWordId (int off)
{
int idx;
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
//if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
if ((en.typeBitsize()<=16) &&
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0))
return true;
return false;
});
if(found==id_arr.end())
{ Int idx;
for (idx = 0; idx < locsym->csym; idx++)
{
printf("No entry to flag as invalid in LOCAL_ID::flagByteWordId \n");
return;
if (((locsym->id[idx].type == TYPE_WORD_SIGN) ||
(locsym->id[idx].type == TYPE_BYTE_SIGN)) &&
(locsym->id[idx].id.bwId.off == off) &&
(locsym->id[idx].id.bwId.regOff == 0))
{
locsym->id[idx].illegal = TRUE;
break;
}
}
found->illegal = true;
}
Int newByteWordStkId (LOCAL_ID *locSym, hlType t, Int off, byte regOff)
/* Creates a new stack identifier node of TYPE_BYTE_(UN)SIGN or
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
{
int idx;
{ Int idx;
/* Check for entry in the table */
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
return true;
return false;
});
if(found!=id_arr.end())
return found-id_arr.begin(); //return Index to found element
for (idx = 0; idx < locSym->csym; idx++)
{
if ((locSym->id[idx].id.bwId.off == off) &&
(locSym->id[idx].id.bwId.regOff == regOff))
return (idx);
}
/* Not in table, create new identifier */
newIdent (t, STK_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.bwId.regOff = regOff;
id_arr[idx].id.bwId.off = off;
newIdent (locSym, t, STK_FRAME);
idx = locSym->csym - 1;
locSym->id[idx].id.bwId.regOff = regOff;
locSym->id[idx].id.bwId.off = off;
return (idx);
}
Int newIntIdxId (LOCAL_ID *locSym, int16 seg, int16 off, byte regi,
Int ix, hlType t)
/* Checks if the entry exists in the locSym, if so, returns the idx to this
* entry; otherwise creates a new global identifier node of type
* TYPE_WORD_(UN)SIGN and returns the index to this new entry.
@ -121,196 +135,186 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
* regi: indexed register into global variable
* ix: index into icode array
* t: HIGH_LEVEL type */
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t)
{
int idx;
{ Int idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (idx = 0; idx < locSym->csym; idx++)
{
if (/*(locSym->id[idx].type == t) && Not checking type */
(id_arr[idx].id.bwGlb.seg == seg) &&
(id_arr[idx].id.bwGlb.off == off) &&
(id_arr[idx].id.bwGlb.regi == regi))
(locSym->id[idx].id.bwGlb.seg == seg) &&
(locSym->id[idx].id.bwGlb.off == off) &&
(locSym->id[idx].id.bwGlb.regi == regi))
return (idx);
}
/* Not in the table, create new identifier */
newIdent (t, GLB_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.bwGlb.seg = seg;
id_arr[idx].id.bwGlb.off = off;
id_arr[idx].id.bwGlb.regi = regi;
newIdent (locSym, t, GLB_FRAME);
idx = locSym->csym - 1;
locSym->id[idx].id.bwGlb.seg = seg;
locSym->id[idx].id.bwGlb.off = off;
locSym->id[idx].id.bwGlb.regi = regi;
return (idx);
}
Int newLongRegId (LOCAL_ID *locSym, hlType t, byte regH, byte regL, Int ix)
/* Checks if the entry exists in the locSym, if so, returns the idx to this
* entry; otherwise creates a new register identifier node of type
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
{
size_t idx;
//iICODE ix_;
{ Int idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (idx = 0; idx < locSym->csym; idx++)
{
ID &entry(id_arr[idx]);
if (/*(locSym->id[idx].type == t) && Not checking type */
(entry.id.longId.h == regH) &&
(entry.id.longId.l == regL))
(locSym->id[idx].id.longId.h == regH) &&
(locSym->id[idx].id.longId.l == regL))
{
/* Check for occurrence in the list */
if (entry.idx.inList(ix_))
if (inList (&locSym->id[idx].idx, ix))
return (idx);
else
{
/* Insert icode index in list */
entry.idx.push_back(ix_);
//entry.idx.insert(ix_);
insertIdx (&locSym->id[idx].idx, ix);
return (idx);
}
}
}
/* Not in the table, create new identifier */
newIdent (t, REG_FRAME);
id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_);
idx = id_arr.size() - 1;
id_arr[idx].id.longId.h = regH;
id_arr[idx].id.longId.l = regL;
newIdent (locSym, t, REG_FRAME);
insertIdx (&locSym->id[locSym->csym-1].idx, ix);
idx = locSym->csym - 1;
locSym->id[idx].id.longId.h = regH;
locSym->id[idx].id.longId.l = regL;
return (idx);
}
/* Returns an identifier conditional expression node of type TYPE_LONG or
* TYPE_WORD_SIGN */
COND_EXPR * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
{
return COND_EXPR::idID(retVal,this,ix_);
}
static Int newLongGlbId (LOCAL_ID *locSym, int16 seg, int16 offH, int16 offL,
Int ix, hlType t)
/* Checks if the entry exists in the locSym, if so, returns the idx to this
* entry; otherwise creates a new global identifier node of type
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
{
size_t idx;
{ Int idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (idx = 0; idx < locSym->csym; idx++)
{
if (/*(locSym->id[idx].type == t) && Not checking type */
(id_arr[idx].id.longGlb.seg == seg) &&
(id_arr[idx].id.longGlb.offH == offH) &&
(id_arr[idx].id.longGlb.offL == offL))
(locSym->id[idx].id.longGlb.seg == seg) &&
(locSym->id[idx].id.longGlb.offH == offH) &&
(locSym->id[idx].id.longGlb.offL == offL))
return (idx);
}
/* Not in the table, create new identifier */
newIdent (t, GLB_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.longGlb.seg = seg;
id_arr[idx].id.longGlb.offH = offH;
id_arr[idx].id.longGlb.offL = offL;
newIdent (locSym, t, GLB_FRAME);
idx = locSym->csym - 1;
locSym->id[idx].id.longGlb.seg = seg;
locSym->id[idx].id.longGlb.offH = offH;
locSym->id[idx].id.longGlb.offL = offL;
return (idx);
}
static Int newLongIdxId (LOCAL_ID *locSym, int16 seg, int16 offH, int16 offL,
byte regi, Int ix, hlType t)
/* Checks if the entry exists in the locSym, if so, returns the idx to this
* entry; otherwise creates a new global identifier node of type
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
int LOCAL_ID::newLongIdx( int16_t seg, int16_t offH, int16_t offL,uint8_t regi, hlType t)
{
size_t idx;
{ Int idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (idx = 0; idx < locSym->csym; idx++)
{
if (/*(locSym->id[idx].type == t) && Not checking type */
(id_arr[idx].id.longGlb.seg == seg) &&
(id_arr[idx].id.longGlb.offH == offH) &&
(id_arr[idx].id.longGlb.offL == offL) &&
(id_arr[idx].id.longGlb.regi == regi))
(locSym->id[idx].id.longGlb.seg == seg) &&
(locSym->id[idx].id.longGlb.offH == offH) &&
(locSym->id[idx].id.longGlb.offL == offL) &&
(locSym->id[idx].id.longGlb.regi == regi))
return (idx);
}
/* Not in the table, create new identifier */
newIdent (t, GLB_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.longGlb.seg = seg;
id_arr[idx].id.longGlb.offH = offH;
id_arr[idx].id.longGlb.offL = offL;
id_arr[idx].id.longGlb.regi = regi;
newIdent (locSym, t, GLB_FRAME);
idx = locSym->csym - 1;
locSym->id[idx].id.longGlb.seg = seg;
locSym->id[idx].id.longGlb.offH = offH;
locSym->id[idx].id.longGlb.offL = offL;
locSym->id[idx].id.longGlb.regi = regi;
return (idx);
}
Int newLongStkId (LOCAL_ID *locSym, hlType t, Int offH, Int offL)
/* Creates a new stack identifier node of type TYPE_LONG_(UN)SIGN.
* Returns the index to this entry. */
int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
{
size_t idx;
{ Int idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (idx = 0; idx < locSym->csym; idx++)
{
if ((id_arr[idx].type == t) &&
(id_arr[idx].id.longStkId.offH == offH) &&
(id_arr[idx].id.longStkId.offL == offL))
if ((locSym->id[idx].type == t) &&
(locSym->id[idx].id.longStkId.offH == offH) &&
(locSym->id[idx].id.longStkId.offL == offL))
return (idx);
}
/* Not in the table; flag as invalid offH and offL */
flagByteWordId (offH);
flagByteWordId (offL);
flagByteWordId (locSym, offH);
flagByteWordId (locSym, offL);
/* Create new identifier */
newIdent (t, STK_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.longStkId.offH = offH;
id_arr[idx].id.longStkId.offL = offL;
newIdent (locSym, t, STK_FRAME);
idx = locSym->csym - 1;
locSym->id[idx].id.longStkId.offH = offH;
locSym->id[idx].id.longStkId.offL = offL;
return (idx);
}
Int newLongId (LOCAL_ID *locSym, opLoc sd, PICODE pIcode, hlFirst f, Int ix,
operDu du, Int off)
/* Returns the index to an appropriate long identifier.
* Note: long constants should be checked first and stored as a long integer
* number in an expression record. */
int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset)
{
size_t idx;
const LLOperand *pmH, *pmL;
LLInst &p_ll(*pIcode->ll());
{ Int idx;
PMEM pmH, pmL;
if (f == LOW_FIRST)
{
pmL = p_ll.get(sd);
pmH = atOffset.get(sd);
pmL = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
pmH = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
}
else /* HIGH_FIRST */
{
pmL = atOffset.get(sd);
pmH = p_ll.get(sd);
pmH = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
pmL = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
}
if (pmL->regi == 0) /* global variable */
idx = newLongGlb(pmH->segValue, pmH->off, pmL->off, TYPE_LONG_SIGN);
idx = newLongGlbId (locSym, pmH->segValue, pmH->off, pmL->off, ix,
TYPE_LONG_SIGN);
else if (pmL->regi < INDEX_BX_SI) /* register */
else if (pmL->regi < INDEXBASE) /* register */
{
idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
idx = newLongRegId (locSym, TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
if (f == HIGH_FIRST)
pIcode->setRegDU( pmL->regi, du); /* low part */
setRegDU (pIcode, pmL->regi, du); /* low part */
else
pIcode->setRegDU( pmH->regi, du); /* high part */
setRegDU (pIcode, pmH->regi, du); /* high part */
}
else if (pmL->off) { /* offset */
if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */
if ((pmL->seg == rSS) && (pmL->regi == INDEXBASE + 6)) /* idx on bp */
idx = newLongStkId (locSym, TYPE_LONG_SIGN, pmH->off, pmL->off);
else if ((pmL->seg == rDS) && (pmL->regi == INDEXBASE + 7)) /* bx */
{ /* glb var indexed on bx */
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
pIcode->setRegDU( rBX, eUSE);
idx = newLongIdxId (locSym, pmH->segValue, pmH->off, pmL->off,
rBX, ix, TYPE_LONG_SIGN);
setRegDU (pIcode, rBX, E_USE);
}
else /* idx <> bp, bx */
printf ("long not supported, idx <> bp\n");
@ -323,6 +327,8 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
}
boolT checkLongEq (LONG_STKID_TYPE longId, PICODE pIcode, Int i, Int idx,
PPROC pProc, COND_EXPR **rhs, COND_EXPR **lhs, Int off)
/* Checks whether the long stack identifier is equivalent to the source or
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
* icodes at present). If so, returns the rhs and lhs of this instruction.
@ -332,36 +338,34 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
* idx : idx into icode array
* pProc : ptr to current procedure record
* rhs, lhs : return expressions if successful. */
boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
{
/* pointers to LOW_LEVEL icodes */
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */
pmHdst = &pIcode->ll()->dst;
pmLdst = &atOffset.dst;
pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src();
pmHdst = &pIcode->ic.ll.dst;
pmLdst = &(pIcode+off)->ic.ll.dst;
pmHsrc = &pIcode->ic.ll.src;
pmLsrc = &(pIcode+off)->ic.ll.src;
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
{
asgn.lhs = COND_EXPR::idLongIdx (i);
if ( not pIcode->ll()->testFlags(NO_SRC) )
{
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
}
return true;
*lhs = idCondExpLongIdx (i);
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
*rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
idx, E_USE, off);
return (TRUE);
}
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
{
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
asgn.rhs = COND_EXPR::idLongIdx (i);
return true;
*lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
E_DEF, off);
*rhs = idCondExpLongIdx (i);
return (TRUE);
}
return false;
return (FALSE);
}
boolT checkLongRegEq (LONGID_TYPE longId, PICODE pIcode, Int i, Int idx,
PPROC pProc, COND_EXPR **rhs, COND_EXPR **lhs, Int off)
/* Checks whether the long stack identifier is equivalent to the source or
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
* icodes at present). If so, returns the rhs and lhs of this instruction.
@ -371,45 +375,40 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro
* idx : idx into icode array
* pProc : ptr to current procedure record
* rhs, lhs : return expressions if successful. */
boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
Function * pProc, Assignment &asgn, LLInst &atOffset)
{
/* pointers to LOW_LEVEL icodes */
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */
pmHdst = &pIcode->ll()->dst;
pmLdst = &atOffset.dst;
pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src();
pmHdst = &pIcode->ic.ll.dst;
pmLdst = &(pIcode+off)->ic.ll.dst;
pmHsrc = &pIcode->ic.ll.src;
pmLsrc = &(pIcode+off)->ic.ll.src;
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
{
asgn.lhs = COND_EXPR::idLongIdx (i);
if ( not pIcode->ll()->testFlags(NO_SRC) )
{
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
}
return true;
*lhs = idCondExpLongIdx (i);
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
*rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
idx, E_USE, off);
return (TRUE);
}
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
{
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
asgn.rhs = COND_EXPR::idLongIdx (i);
return true;
*lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
E_DEF, off);
*rhs = idCondExpLongIdx (i);
return (TRUE);
}
return false;
return (FALSE);
}
byte otherLongRegi (byte regi, Int idx, LOCAL_ID *locTbl)
/* Given an index into the local identifier table for a long register
* variable, determines whether regi is the high or low part, and returns
* the other part */
eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
{
ID *id;
{ ID *id;
id = &locTbl->id_arr[idx];
id = &locTbl->id[idx];
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
(id->type == TYPE_LONG_UNSIGN)))
{
@ -418,33 +417,37 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
else if (id->id.longId.l == regi)
return (id->id.longId.h);
}
return rUNDEF; // Cristina: please check this!
return 0; // Cristina: please check this!
}
void propLongId (LOCAL_ID *locid, byte regL, byte regH, char *name)
/* Checks if the registers regL and regH have been used independently in
* the local identifier table. If so, macros for these registers are
* placed in the local identifier table, as these registers belong to a
* long register identifier. */
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
{
for (ID &rid : id_arr)
{
if (rid.typeBitsize()!=16)
continue;
if ( (rid.id.regi != regL) and (rid.id.regi != regH) )
continue;
// otherwise at least 1 is ok
rid.name = name;
rid.hasMacro = true;
rid.illegal = true;
if (rid.id.regi == regL)
{
strcpy (rid.macro, "LO");
}
else // if (rid.id.regi == regH)
{
strcpy (rid.macro, "HI");
}
}
{ Int i;
ID *id;
for (i = 0; i < locid->csym; i++)
{
id = &locid->id[i];
if ((id->type == TYPE_WORD_SIGN) || (id->type == TYPE_WORD_UNSIGN))
{
if (id->id.regi == regL)
{
strcpy (id->name, name);
strcpy (id->macro, "LO");
id->hasMacro = TRUE;
id->illegal = TRUE;
}
else if (id->id.regi == regH)
{
strcpy (id->name, name);
strcpy (id->macro, "HI");
id->hasMacro = TRUE;
id->illegal = TRUE;
}
}
}
}

View File

@ -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)));
}

File diff suppressed because it is too large Load Diff

View File

@ -11,21 +11,32 @@
/* Private data structures */
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
static int NumEntry; /* Number of entries in the hash table (# keys) */
static int EntryLen; /* Size (bytes) of each entry (size of keys) */
static int SetSize; /* Size of the char set */
static char SetMin; /* First char in the set */
static int NumVert; /* c times NumEntry */
static word *T1base, *T2base; /* Pointers to start of T1, T2 */
static word *T1, *T2; /* Pointers to T1[i], T2[i] */
static int *graphNode; /* The array of edges */
static int *graphNext; /* Linked list of edges */
static int *graphFirst;/* First edge at a vertex */
static short *g; /* g[] */
static int numEdges; /* An edge counter */
//static bool *visited; /* Array of bools: whether visited */
static bool *visited; /* Array of bools: whether visited */
/* Private prototypes */
static void initGraph(void);
static void addToGraph(int e, int v1, int v2);
static bool isCycle(void);
static void duplicateKeys(int v1, int v2);
PatternHasher g_pattern_hasher;
void
PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
int _NumVert)
{
/* These parameters are stored in statics so as to obviate the need for
@ -39,32 +50,316 @@ PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
NumVert = _NumVert;
/* Allocate the variable sized tables etc */
T1base = new uint16_t [EntryLen * SetSize];
T2base = new uint16_t [EntryLen * SetSize];
graphNode = new int [NumEntry*2 + 1];
graphNext = new int [NumEntry*2 + 1];
graphFirst = new int [NumVert + 1];
g = new short [NumVert + 1];
// visited = new bool [NumVert + 1];
if ((T1base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
{
goto BadAlloc;
}
if ((T2base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
{
goto BadAlloc;
}
if ((graphNode = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
{
goto BadAlloc;
}
if ((graphNext = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
{
goto BadAlloc;
}
if ((graphFirst = (int *)malloc((NumVert + 1) * sizeof(int))) == 0)
{
goto BadAlloc;
}
if ((g = (short *)malloc((NumVert+1) * sizeof(short))) == 0)
{
goto BadAlloc;
}
if ((visited = (bool *)malloc((NumVert+1) * sizeof(bool))) == 0)
{
goto BadAlloc;
}
return;
BadAlloc:
printf("Could not allocate memory\n");
hashCleanup();
exit(1);
}
void PatternHasher::cleanup(void)
void
hashCleanup(void)
{
/* Free the storage for variable sized tables etc */
delete [] T1base;
delete [] T2base;
delete [] graphNode;
delete [] graphNext;
delete [] graphFirst;
delete [] g;
// delete [] visited;
if (T1base) free(T1base);
if (T2base) free(T2base);
if (graphNode) free(graphNode);
if (graphNext) free(graphNext);
if (graphFirst) free(graphFirst);
if (g) free(g);
}
int PatternHasher::hash(uint8_t *string)
void
map(void)
{
uint16_t u, v;
int i, j, c;
word f1, f2;
bool cycle;
byte *keys;
c = 0;
do
{
initGraph();
cycle = FALSE;
/* Randomly generate T1 and T2 */
for (i=0; i < SetSize*EntryLen; i++)
{
T1base[i] = rand() % NumVert;
T2base[i] = rand() % NumVert;
}
for (i=0; i < NumEntry; i++)
{
f1 = 0; f2 = 0;
getKey(i, &keys);
for (j=0; j < EntryLen; j++)
{
T1 = T1base + j * SetSize;
T2 = T2base + j * SetSize;
f1 += T1[keys[j] - SetMin];
f2 += T2[keys[j] - SetMin];
}
f1 %= (word)NumVert;
f2 %= (word)NumVert;
if (f1 == f2)
{
/* A self loop. Reject! */
printf("Self loop on vertex %d!\n", f1);
cycle = TRUE;
break;
}
addToGraph(numEdges++, f1, f2);
}
if (cycle || (cycle = isCycle())) /* OK - is there a cycle? */
{
printf("Iteration %d\n", ++c);
}
else
{
break;
}
}
while (/* there is a cycle */ 1);
}
/* Initialise the graph */
static void
initGraph(void)
{
int i;
for (i=1; i <= NumVert; i++)
{
graphFirst[i] = 0;
}
for (i= -NumEntry; i <= NumEntry; i++)
{
/* No need to init graphNode[] as they will all be filled by successive
calls to addToGraph() */
graphNext[NumEntry+i] = 0;
}
numEdges = 0;
}
/* Add an edge e between vertices v1 and v2 */
/* e, v1, v2 are 0 based */
static void
addToGraph(int e, int v1, int v2)
{
e++; v1++; v2++; /* So much more convenient */
graphNode[NumEntry+e] = v2; /* Insert the edge information */
graphNode[NumEntry-e] = v1;
graphNext[NumEntry+e] = graphFirst[v1]; /* Insert v1 to list of alphas */
graphFirst[v1]= e;
graphNext[NumEntry-e] = graphFirst[v2]; /* Insert v2 to list of omegas */
graphFirst[v2]= -e;
}
bool DFS(int parentE, int v)
{
int e, w;
/* Depth first search of the graph, starting at vertex v, looking for
cycles. parent and v are origin 1. Note parent is an EDGE,
not a vertex */
visited[v] = TRUE;
/* For each e incident with v .. */
for (e = graphFirst[v]; e; e = graphNext[NumEntry+e])
{
byte *key1;
getKey(abs(e)-1, &key1);
if (*(long *)key1 == 0)
{
/* A deleted key. Just ignore it */
continue;
}
w = graphNode[NumEntry+e];
if (visited[w])
{
/* Did we just come through this edge? If so, ignore it. */
if (abs(e) != abs(parentE))
{
/* There is a cycle in the graph. There is some subtle code here
to work around the distinct possibility that there may be
duplicate keys. Duplicate keys will always cause unit
cycles, since f1 and f2 (used to select v and w) will be the
same for both. The edges (representing an index into the
array of keys) are distinct, but the key values are not.
The logic is as follows: for the candidate edge e, check to
see if it terminates in the parent vertex. If so, we test
the keys associated with e and the parent, and if they are
the same, we can safely ignore e for the purposes of cycle
detection, since edge e adds nothing to the cycle. Cycles
involving v, w, and e0 will still be found. The parent
edge was not similarly eliminated because at the time when
it was a candidate, v was not yet visited.
We still have to remove the key from further consideration,
since each edge is visited twice, but with a different
parent edge each time.
*/
/* We save some stack space by calculating the parent vertex
for these relatively few cases where it is needed */
int parentV = graphNode[NumEntry-parentE];
if (w == parentV)
{
byte *key2;
getKey(abs(parentE)-1, &key2);
if (memcmp(key1, key2, EntryLen) == 0)
{
printf("Duplicate keys with edges %d and %d (",
e, parentE);
dispKey(abs(e)-1);
printf(" & ");
dispKey(abs(parentE)-1);
printf(")\n");
/* *(long *)key1 = 0; /* Wipe the key */
memset(key1, 0, EntryLen);
}
else
{
/* A genuine (unit) cycle. */
printf("There is a unit cycle involving vertex %d and edge %d\n", v, e);
return TRUE;
}
}
else
{
/* We have reached a previously visited vertex not the
parent. Therefore, we have uncovered a genuine cycle */
printf("There is a cycle involving vertex %d and edge %d\n", v, e);
return TRUE;
}
}
}
else /* Not yet seen. Traverse it */
{
if (DFS(e, w))
{
/* Cycle found deeper down. Exit */
return TRUE;
}
}
}
return FALSE;
}
static bool
isCycle(void)
{
int v;
for (v=1; v <= NumVert; v++)
{
visited[v] = FALSE;
}
for (v=1; v <= NumVert; v++)
{
if (!visited[v])
{
if (DFS(-32767, v))
{
return TRUE;
}
}
}
return FALSE;
}
void
traverse(int u)
{
int w, e;
visited[u] = TRUE;
/* Find w, the neighbours of u, by searching the edges e associated with u */
e = graphFirst[1+u];
while (e)
{
w = graphNode[NumEntry+e]-1;
if (!visited[w])
{
g[w] = (abs(e)-1 - g[u]) % NumEntry;
if (g[w] < 0) g[w] += NumEntry; /* Keep these positive */
traverse(w);
}
e = graphNext[NumEntry+e];
}
}
void
assign(void)
{
int v;
for (v=0; v < NumVert; v++)
{
g[v] = 0; /* g is sparse; leave the gaps 0 */
visited[v] = FALSE;
}
for (v=0; v < NumVert; v++)
{
if (!visited[v])
{
g[v] = 0;
traverse(v);
}
}
}
int
hash(byte *string)
{
word u, v;
int j;
u = 0;
@ -86,18 +381,68 @@ int PatternHasher::hash(uint8_t *string)
return (g[u] + g[v]) % NumEntry;
}
uint16_t * PatternHasher::readT1(void)
word *
readT1(void)
{
return T1base;
}
uint16_t *PatternHasher::readT2(void)
word *
readT2(void)
{
return T2base;
}
uint16_t * PatternHasher::readG(void)
word *
readG(void)
{
return (uint16_t *)g;
return (word *)g;
}
#if 0
void dispRecord(int i);
void
duplicateKeys(int v1, int v2)
{
int i, j;
byte *keys;
int u, v;
v1--; v2--; /* These guys are origin 1 */
printf("Duplicate keys:\n");
for (i=0; i < NumEntry; i++)
{
getKey(i, &keys);
u = 0;
for (j=0; j < EntryLen; j++)
{
T1 = T1base + j * SetSize;
u += T1[keys[j] - SetMin];
}
u %= NumVert;
if ((u != v1) && (u != v2)) continue;
v = 0;
for (j=0; j < EntryLen; j++)
{
T2 = T2base + j * SetSize;
v += T2[keys[j] - SetMin];
}
v %= NumVert;
if ((v == v2) || (v == v1))
{
printf("Entry #%d key: ", i+1);
for (j=0; j < EntryLen; j++) printf("%02X ", keys[j]);
printf("\n");
dispRecord(i+1);
}
}
exit(1);
}
#endif

View File

@ -5,83 +5,87 @@
* (C) Cristina Cifuentes
*/
#include <cstring>
#include <cassert>
#include "dcc.h"
#include "project.h"
#include <string.h>
extern Project g_proj;
/* Static indentation buffer */
static constexpr int indSize=81; /* size of indentation buffer; max 20 */
#define indSize 61 /* size of indentation buffer; max 20 */
static char indentBuf[indSize] =
" ";
// not static, used in icode.cpp at emitGotoLabel
const char *indentStr(int indLevel) // Indentation according to the depth of the statement
" ";
static char *indent (Int indLevel)
/* Indentation according to the depth of the statement */
{
return (&indentBuf[indSize-(indLevel*4)-1]);
return (&indentBuf[indSize-(indLevel*3)-1]);
}
static void insertArc (PCALL_GRAPH pcallGraph, PPROC newProc)
/* Inserts an outEdge at the current callGraph pointer if the newProc does
* not exist. */
void CALL_GRAPH::insertArc (ilFunction newProc)
{
CALL_GRAPH *pcg;
{ CALL_GRAPH *pcg;
Int i;
/* Check if procedure already exists */
auto res=std::find_if(outEdges.begin(),outEdges.end(),[newProc](CALL_GRAPH *e) {return e->proc==newProc;});
if(res!=outEdges.end())
return;
for (i = 0; i < pcallGraph->numOutEdges; i++)
if (pcallGraph->outEdges[i]->proc == newProc)
return;
/* Check if need to allocate more space */
if (pcallGraph->numOutEdges == pcallGraph->numAlloc)
{
pcallGraph->numAlloc += NUM_PROCS_DELTA;
pcallGraph->outEdges = (PCALL_GRAPH*)reallocVar(pcallGraph->outEdges,
pcallGraph->numAlloc * sizeof(PCALL_GRAPH));
memset (&pcallGraph->outEdges[pcallGraph->numOutEdges], 0,
NUM_PROCS_DELTA * sizeof(PCALL_GRAPH));
}
/* Include new arc */
pcg = new CALL_GRAPH;
pcg = allocStruc(CALL_GRAPH);
memset (pcg, 0, sizeof(CALL_GRAPH));
pcg->proc = newProc;
outEdges.push_back(pcg);
pcallGraph->outEdges[pcallGraph->numOutEdges] = pcg;
pcallGraph->numOutEdges++;
}
boolT insertCallGraph (PCALL_GRAPH pcallGraph, PPROC caller, PPROC callee)
/* Inserts a (caller, callee) arc in the call graph tree. */
bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
{
int i;
{ Int i;
if (proc == caller)
if (pcallGraph->proc == caller)
{
insertArc (callee);
return true;
insertArc (pcallGraph, callee);
return (TRUE);
}
else
{
for (i = 0; i < outEdges.size(); i++)
if (outEdges[i]->insertCallGraph (caller, callee))
return true;
return (false);
for (i = 0; i < pcallGraph->numOutEdges; i++)
if (insertCallGraph (pcallGraph->outEdges[i], caller, callee))
return (TRUE);
return (FALSE);
}
}
bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
{
return insertCallGraph(g_proj.funcIter(caller),callee);
}
static void writeNodeCallGraph (PCALL_GRAPH pcallGraph, Int indIdx)
/* Displays the current node of the call graph, and invokes recursively on
* the nodes the procedure invokes. */
void CALL_GRAPH::writeNodeCallGraph(int indIdx)
{
int i;
{ Int i;
printf ("%s%s\n", indentStr(indIdx), proc->name.c_str());
for (i = 0; i < outEdges.size(); i++)
outEdges[i]->writeNodeCallGraph (indIdx + 1);
printf ("%s%s\n", indent(indIdx), pcallGraph->proc->name);
for (i = 0; i < pcallGraph->numOutEdges; i++)
writeNodeCallGraph (pcallGraph->outEdges[i], indIdx + 1);
}
void writeCallGraph (PCALL_GRAPH pcallGraph)
/* Writes the header and invokes recursive procedure */
void CALL_GRAPH::write()
{
printf ("\nCall Graph:\n");
writeNodeCallGraph (0);
writeNodeCallGraph (pcallGraph, 0);
}
@ -89,298 +93,321 @@ void CALL_GRAPH::write()
* Routines to support arguments
*************************************************************************/
void newRegArg (PPROC pproc, PICODE picode, PICODE ticode)
/* Updates the argument table by including the register(s) (ie. lhs of
* picode) and the actual expression (ie. rhs of picode).
* Note: register(s) are only included once in the table. */
void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
{
COND_EXPR *lhs;
STKFRAME * call_args_stackframe, *target_stackframe;
const ID *id;
int tidx;
boolT regExist;
condId type;
Function * tproc;
eReg regL, regH; /* Registers involved in arguments */
{ COND_EXPR *lhs;
PSTKFRAME ps, ts;
ID *id;
Int i, tidx;
boolT regExist;
condId type;
PPROC tproc;
byte regL, regH; /* Registers involved in arguments */
/* Flag ticode as having register arguments */
tproc = ticode->hl()->call.proc;
tproc->flg |= REG_ARGS;
/* Flag ticode as having register arguments */
tproc = ticode->ic.hl.oper.call.proc;
tproc->flg |= REG_ARGS;
/* Get registers and index into target procedure's local list */
call_args_stackframe = ticode->hl()->call.args;
target_stackframe = &tproc->args;
lhs = picode->hl()->asgn.lhs;
type = lhs->expr.ident.idType;
if (type == REGISTER)
/* Get registers and index into target procedure's local list */
ps = ticode->ic.hl.oper.call.args;
ts = &tproc->args;
lhs = picode->ic.hl.oper.asgn.lhs;
type = lhs->expr.ident.idType;
if (type == REGISTER)
{
regL = 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;
if (regL < rAL)
tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL);
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*/);
ps->alloc += 5;
ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM));
}
sprintf (ps->sym[ps->csym].name, "arg%ld", ps->csym);
ps->sym[ps->csym].actual = picode->ic.hl.oper.asgn.rhs;
ps->sym[ps->csym].regs = lhs;
/* Check if register argument already on the formal argument list */
regExist = false;
for(STKSYM &tgt_sym : *target_stackframe)
{
if( tgt_sym.regs == NULL ) // both REGISTER and LONG_VAR require this precondition
continue;
if (type == REGISTER)
{
if ( tgt_sym.regs->expr.ident.idNode.regiIdx == tidx )
{
regExist = true;
}
}
else if (type == LONG_VAR)
{
if ( tgt_sym.regs->expr.ident.idNode.longIdx == tidx )
{
regExist = true;
}
}
if(regExist == true)
break;
}
/* Mask off high and low register(s) in picode */
switch (type) {
case REGISTER:
id = &pproc->localId.id[lhs->expr.ident.idNode.regiIdx];
picode->du.def &= maskDuReg[id->id.regi];
if (id->id.regi < rAL)
ps->sym[ps->csym].type = TYPE_WORD_SIGN;
else
ps->sym[ps->csym].type = TYPE_BYTE_SIGN;
break;
case LONG_VAR:
id = &pproc->localId.id[lhs->expr.ident.idNode.longIdx];
picode->du.def &= maskDuReg[id->id.longId.h];
picode->du.def &= maskDuReg[id->id.longId.l];
ps->sym[ps->csym].type = TYPE_LONG_SIGN;
break;
}
/* Do ts (formal arguments) */
if (regExist == false)
{
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++;
ps->csym++;
ps->numArgs++;
}
/** Inserts the new expression (ie. the actual parameter) on the argument
void allocStkArgs (PICODE picode, Int num)
/* Allocates num arguments in the actual argument list of the current
* icode picode. */
/** NOTE: this function is not used ****/
{ PSTKFRAME ps;
ps = picode->ic.hl.oper.call.args;
ps->alloc = num;
ps->csym = num;
ps->numArgs = num;
ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM));
/**** memset here??? *****/
}
boolT newStkArg (PICODE picode, COND_EXPR *exp, llIcode opcode, PPROC pproc)
/* Inserts the new expression (ie. the actual parameter) on the argument
* list.
* @return true if it was a near call that made use of a segment register.
* false elsewhere
*/
bool CallType::newStkArg(COND_EXPR *exp, llIcode opcode, Function * pproc)
{
uint8_t regi;
/* 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;
}
}
* Returns: TRUE if it was a near call that made use of a segment register.
* FALSE elsewhere */
{ PSTKFRAME ps;
byte regi;
/* Place register argument on the argument list */
STKSYM newsym;
newsym.actual = exp;
args->push_back(newsym);
args->numArgs++;
return false;
/* 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->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
* argument list of picode. */
void CallType::placeStkArg (COND_EXPR *exp, int pos)
{
(*args)[pos].actual = exp;
(*args)[pos].setArgName(pos);
}
{ PSTKFRAME ps;
COND_EXPR *CallType::toId()
{
return COND_EXPR::idFunc( proc, args);
ps = picode->ic.hl.oper.call.args;
ps->sym[pos].actual = exp;
sprintf (ps->sym[pos].name, "arg%ld", pos);
}
void adjustActArgType (COND_EXPR *exp, hlType forType, PPROC pproc)
/* Checks to determine whether the expression (actual argument) has the
* same type as the given type (from the procedure's formal list). If not,
* the actual argument gets modified */
void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
{
PROG &prog(Project::get()->prog);
hlType actType;
int offset, offL;
{ hlType actType;
Int offset, offL;
if (exp == NULL)
return;
if (exp == NULL)
return;
actType = exp-> expType (pproc);
if (((actType == forType) || (exp->m_type != IDENTIFIER)))
return;
switch (forType)
{
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
case TYPE_LONG_UNSIGN: case TYPE_RECORD:
break;
actType = expType (exp, pproc);
if ((actType != forType) && (exp->type == IDENTIFIER))
{
switch (forType) {
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
case TYPE_LONG_UNSIGN: case TYPE_RECORD:
break;
case TYPE_PTR:
case TYPE_CONST:
break;
case TYPE_PTR:
case TYPE_CONST:
break;
case TYPE_STR:
switch (actType) {
case TYPE_CONST:
/* It's an offset into image where a string is
* found. Point to the string. */
offL = exp->expr.ident.idNode.kte.kte;
if (prog.fCOM)
offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
else
offset = (pproc->state.r[rDS]<<4) + offL;
exp->expr.ident.idNode.strIdx = offset;
exp->expr.ident.idType = STRING;
break;
case TYPE_STR:
switch (actType) {
case TYPE_CONST:
/* It's an offset into image where a string is
* found. Point to the string. */
offL = exp->expr.ident.idNode.kte.kte;
if (prog.fCOM)
offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
else
offset = (pproc->state.r[rDS]<<4) + offL;
exp->expr.ident.idNode.strIdx = offset;
exp->expr.ident.idType = STRING;
break;
case TYPE_PTR:
/* It's a pointer to a char rather than a pointer to
* an integer */
/***HERE - modify the type ****/
break;
case TYPE_PTR:
/* It's a pointer to a char rather than a pointer to
* an integer */
/***HERE - modify the type ****/
break;
case TYPE_WORD_SIGN:
case TYPE_WORD_SIGN:
break;
} /* eos */
break;
}
break;
} /* eos */
break;
}
}
}
void adjustForArgType (PSTKFRAME pstkFrame, Int numArg, hlType actType)
/* Determines whether the formal argument has the same type as the given
* type (type of the actual argument). If not, the formal argument is
* changed its type */
void STKFRAME::adjustForArgType(int numArg_, hlType actType_)
{
hlType forType;
STKSYM * psym, * nsym;
int off, i;
/* If formal argument does not exist, do not create new ones, just
* ignore actual argument
*/
if(numArg_>size())
return;
{ hlType forType;
PSTKSYM psym, nsym;
Int off, i;
/* Find stack offset for this argument */
off = m_minOff;
i=0;
for(STKSYM &s : *this) // walk formal arguments upto numArg_
{
if(i>=numArg_)
break;
off+=s.size;
i++;
}
/* Find stack offset for this argument */
off = pstkFrame->minOff;
for (i = 0; i < numArg; i++)
off += pstkFrame->sym[i].size;
/* Find formal argument */
//psym = &at(numArg_);
//i = numArg_;
//auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;});
auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {s.label==off;});
if(iter==end()) // symbol not found
return;
psym = &(*iter);
/* Find formal argument */
if (numArg < pstkFrame->csym)
{
psym = &pstkFrame->sym[numArg];
i = numArg;
while ((i < pstkFrame->csym) && (psym->off != off))
{
psym++;
i++;
}
if (numArg == pstkFrame->csym)
return;
}
/* If formal argument does not exist, do not create new ones, just
* ignore actual argument */
else
return;
forType = psym->type;
if (forType != actType_)
{
switch (actType_) {
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
break;
forType = psym->type;
if (forType != actType)
{
switch (actType) {
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
break;
case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
if ((forType == TYPE_WORD_UNSIGN) ||
(forType == TYPE_WORD_SIGN) ||
(forType == TYPE_UNKNOWN))
{
/* Merge low and high */
psym->type = actType_;
psym->size = 4;
nsym = psym + 1;
nsym->macro = "HI";
psym->macro = "LO";
nsym->hasMacro = true;
psym->hasMacro = true;
nsym->name = psym->name;
nsym->invalid = true;
numArgs--;
}
break;
case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
if ((forType == TYPE_WORD_UNSIGN) ||
(forType == TYPE_WORD_SIGN) ||
(forType == TYPE_UNKNOWN))
{
/* Merge low and high */
psym->type = actType;
psym->size = 4;
nsym = psym + 1;
sprintf (nsym->macro, "HI");
sprintf (psym->macro, "LO");
nsym->hasMacro = TRUE;
psym->hasMacro = TRUE;
sprintf (nsym->name, "%s", psym->name);
nsym->invalid = TRUE;
pstkFrame->numArgs--;
}
break;
case TYPE_PTR:
case TYPE_CONST:
case TYPE_STR:
break;
} /* eos */
}
case TYPE_PTR:
case TYPE_CONST:
case TYPE_STR:
break;
} /* eos */
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -3,388 +3,418 @@
* constructs an equivalent reducible graph if one is not found.
* (C) Cristina Cifuentes
********************************************************************/
#include <algorithm>
#include <cassert>
#include "dcc.h"
#include <stdio.h>
#ifdef __BORLAND__
#include <alloc.h>
#else
#include <malloc.h> /* For free() */
#endif
#include <string.h>
static int numInt; /* Number of intervals */
static Int numInt; /* Number of intervals */
#define nonEmpty(q) (q != NULL)
/* Returns whether the queue q is empty or not */
bool trivialGraph(BB *G)
{
return G->edges.empty();
}
#define trivialGraph(G) (G->numOutEdges == 0)
/* Returns whether the graph is a trivial graph or not */
static BB *firstOfQueue (queue **Q)
/* Returns the first element in the queue Q, and removes this element
* from the list. Q is not an empty queue. */
static BB *firstOfQueue (queue &Q)
{
assert(!Q.empty());
BB *res=Q.front();
Q.pop_front();
return res;
{ queue *elim;
BB *first;
elim = *Q; /* Pointer to first node */
first = (*Q)->node; /* First element */
*Q = (*Q)->next; /* Pointer to next node */
free (elim); /* Free storage */
return (first);
}
queue *appendQueue (queue **Q, BB *node)
/* Appends pointer to node at the end of the queue Q if node is not present
* in this queue. Returns the queue node just appended. */
queue::iterator appendQueue (queue &Q, BB *node)
{
auto iter=std::find(Q.begin(),Q.end(),node);
if(iter!=Q.end())
return iter;
Q.push_back(node);
iter=Q.end();
--iter;
return iter;
{ queue *pq, *l;
pq = allocStruc(queue);
pq->node = node;
pq->next = NULL;
if (Q)
if (*Q)
{
for (l = *Q; l->next && l->node != node; l = l->next)
;
if (l->node != node)
l->next = pq;
}
else /* (*Q) == NULL */
*Q = pq;
return (pq);
}
static BB *firstOfInt (interval *pI)
/* Returns the next unprocessed node of the interval list (pointed to by
* pI->currNode). Removes this element logically from the list, by updating
* the currNode pointer to the next unprocessed element. */
BB *interval::firstOfInt ()
{
auto pq = currNode;
if (pq == nodes.end())
return 0;
++currNode;
return *pq;
{ queue *pq;
pq = pI->currNode;
if (pq == NULL)
return (NULL);
pI->currNode = pq->next;
return (pq->node);
}
/* Appends node @node to the end of the interval list @pI, updates currNode
* if necessary, and removes the node from the header list @pqH if it is
static queue *appendNodeInt (queue *pqH, BB *node, interval *pI)
/* Appends node node to the end of the interval list I, updates currNode
* if necessary, and removes the node from the header list H if it is
* there. The interval header information is placed in the field
* node->inInterval.
* Note: nodes are added to the interval list in interval order (which
* topsorts the dominance relation). */
static void appendNodeInt (queue &pqH, BB *node, interval *pI)
{
queue::iterator pq; /* Pointer to current node of the list */
{ queue *pq, /* Pointer to current node of the list */
*prev; /* Pointer to previous node in the list */
/* Append node if it is not already in the interval list */
pq = appendQueue (pI->nodes, node);
pq = appendQueue (&pI->nodes, node);
/* Update currNode if necessary */
if (pI->currNode == pI->nodes.end())
pI->currNode = pq;
if (pI->currNode == NULL)
pI->currNode = pq;
/* Check header list for occurrence of node, if found, remove it
* and decrement number of out-edges from this interval. */
if (node->beenOnH && !pqH.empty())
if (node->beenOnH && pqH)
{
auto found_iter=std::find(pqH.begin(),pqH.end(),node);
if(found_iter!=pqH.end())
{
pI->numOutEdges -= (uint8_t)(*found_iter)->inEdges.size() - 1;
pqH.erase(found_iter);
}
prev = pqH;
for (pq = prev; pq && pq->node != node; pq = pq->next)
prev = pq;
if (pq == prev)
{
pqH = pqH->next;
pI->numOutEdges -= (byte)pq->node->numInEdges - 1;
}
else if (pq)
{
prev->next = pq->next;
pI->numOutEdges -= (byte)pq->node->numInEdges - 1;
}
}
/* Update interval header information for this basic block */
node->inInterval = pI;
return (pqH);
}
static void findIntervals (derSeq *derivedGi)
/* Finds the intervals of graph derivedGi->Gi and places them in the list
* of intervals derivedGi->Ii.
* Algorithm by M.S.Hecht. */
void derSeq_Entry::findIntervals (Function *c)
{
interval *pI, /* Interval being processed */
*J; /* ^ last interval in derivedGi->Ii */
BB *h, /* Node being processed */
*header, /* Current interval's header node */
*succ; /* Successor basic block */
int i; /* Counter */
queue H; /* Queue of possible header nodes */
boolT first = true; /* First pass through the loop */
{ interval *pI, /* Interval being processed */
*J; /* ^ last interval in derivedGi->Ii */
BB *h, /* Node being processed */
*header, /* Current interval's header node */
*succ; /* Successor basic block */
Int i; /* Counter */
queue *H; /* Queue of possible header nodes */
boolT first = TRUE; /* First pass through the loop */
appendQueue (H, Gi); /* H = {first node of G} */
Gi->beenOnH = true;
Gi->reachingInt = BB::Create(0,"",c); /* ^ empty BB */
H = appendQueue (NULL, derivedGi->Gi); /* H = {first node of G} */
derivedGi->Gi->beenOnH = TRUE;
derivedGi->Gi->reachingInt = allocStruc(BB); /* ^ empty BB */
memset (derivedGi->Gi->reachingInt, 0, sizeof(BB));
/* Process header nodes list H */
while (!H.empty())
while (nonEmpty (H))
{
header = firstOfQueue (H);
pI = new interval;
pI->numInt = (uint8_t)numInt++;
if (first) /* ^ to first interval */
Ii = J = pI;
appendNodeInt (H, header, pI); /* pI(header) = {header} */
header = firstOfQueue (&H);
pI = allocStruc(interval);
memset (pI, 0, sizeof(interval));
pI->numInt = (byte)numInt++;
if (first) /* ^ to first interval */
derivedGi->Ii = J = pI;
H = appendNodeInt (H, header, pI); /* pI(header) = {header} */
/* Process all nodes in the current interval list */
while ((h = pI->firstOfInt()) != NULL)
{
/* Check all immediate successors of h */
for (i = 0; i < h->edges.size(); i++)
{
succ = h->edges[i].BBptr;
succ->inEdgeCount--;
/* Process all nodes in the current interval list */
while ((h = firstOfInt (pI)) != NULL)
{
/* Check all immediate successors of h */
for (i = 0; i < h->numOutEdges; i++)
{
succ = h->edges[i].BBptr;
succ->inEdgeCount--;
if (succ->reachingInt == NULL) /* first visit */
{
succ->reachingInt = header;
if (succ->inEdgeCount == 0)
appendNodeInt (H, succ, pI);
else if (! succ->beenOnH) /* out edge */
{
appendQueue (H, succ);
succ->beenOnH = true;
pI->numOutEdges++;
}
}
else /* node has been visited before */
if (succ->inEdgeCount == 0)
{
if (succ->reachingInt == header || succ->inInterval == pI) /* same interval */
{
if (succ != header)
appendNodeInt (H, succ, pI);
}
else /* out edge */
pI->numOutEdges++;
}
else if (succ != header && succ->beenOnH)
pI->numOutEdges++;
if (succ->reachingInt == NULL) /* first visit */
{
succ->reachingInt = header;
if (succ->inEdgeCount == 0)
H = appendNodeInt (H, succ, pI);
else if (! succ->beenOnH) /* out edge */
{
appendQueue (&H, succ);
succ->beenOnH = TRUE;
pI->numOutEdges++;
}
}
else /* node has been visited before */
if (succ->inEdgeCount == 0)
{
if (succ->reachingInt == header ||
succ->inInterval == pI) /* same interval */
{
if (succ != header)
H = appendNodeInt (H, succ, pI);
}
else /* out edge */
pI->numOutEdges++;
}
else if (succ != header && succ->beenOnH)
pI->numOutEdges++;
}
}
}
/* Link interval I to list of intervals */
if (! first)
{
J->next = pI;
J = pI;
}
else /* first interval */
first = false;
/* Link interval I to list of intervals */
if (! first)
{
J->next = pI;
J = pI;
}
else /* first interval */
first = FALSE;
}
}
/* Displays the intervals of the graph Gi. */
static void displayIntervals (interval *pI)
{
/* Displays the intervals of the graph Gi. */
{ queue *nodePtr;
while (pI)
{
printf (" Interval #: %ld\t#OutEdges: %ld\n", pI->numInt, pI->numOutEdges);
for(BB *node : pI->nodes)
{
if (node->correspInt == NULL) /* real BBs */
printf (" Node: %ld\n", node->begin()->loc_ip);
else // BBs represent intervals
printf (" Node (corresp int): %d\n", node->correspInt->numInt);
}
pI = pI->next;
nodePtr = pI->nodes;
printf (" Interval #: %ld\t#OutEdges: %ld\n",
pI->numInt, pI->numOutEdges);
while (nodePtr)
{
if (nodePtr->node->correspInt == NULL) /* real BBs */
printf (" Node: %ld\n", nodePtr->node->start);
else /* BBs represent intervals */
printf (" Node (corresp int): %d\n",
nodePtr->node->correspInt->numInt);
nodePtr = nodePtr->next;
}
pI = pI->next;
}
}
static derSeq *newDerivedSeq()
/* Allocates space for a new derSeq node. */
static derSeq_Entry *newDerivedSeq()
{
return new derSeq_Entry;
{ derSeq *pder;
pder = allocStruc(derSeq);
memset (pder, 0, sizeof(derSeq));
return (pder);
}
static void freeQueue (queue **q)
/* Frees the storage allocated for the queue q*/
static void freeQueue (queue &q)
{
q.clear();
{ queue *queuePtr;
for (queuePtr = *q; queuePtr; queuePtr = *q)
{
*q = (*q)->next;
free (queuePtr);
}
}
/* Frees the storage allocated for the interval pI */
static void freeInterval (interval **pI)
{
interval *Iptr;
/* Frees the storage allocated for the interval pI */
{ interval *Iptr;
while (*pI)
{
(*pI)->nodes.clear();
Iptr = *pI;
*pI = (*pI)->next;
delete (Iptr);
freeQueue (&((*pI)->nodes));
Iptr = *pI;
*pI = (*pI)->next;
free (Iptr);
}
}
void freeDerivedSeq(derSeq *derivedG)
/* Frees the storage allocated by the derived sequence structure, except
* for the original graph cfg (derivedG->Gi). */
void freeDerivedSeq(derSeq &derivedG)
{
derivedG.clear();
}
derSeq_Entry::~derSeq_Entry()
{
freeInterval (&Ii);
// if(Gi && Gi->nodeType == INTERVAL_NODE)
// freeCFG (Gi);
{ derSeq *derivedGi;
while (derivedG)
{
freeInterval (&(derivedG->Ii));
if (derivedG->Gi->nodeType == INTERVAL_NODE)
freeCFG (derivedG->Gi);
derivedGi = derivedG;
derivedG = derivedG->next;
free (derivedGi);
}
}
static boolT nextOrderGraph (derSeq *derivedGi)
/* Finds the next order graph of derivedGi->Gi according to its intervals
* (derivedGi->Ii), and places it in derivedGi->next->Gi. */
bool Function::nextOrderGraph (derSeq &derivedGi)
{
interval *Ii; /* Interval being processed */
BB *BBnode, /* New basic block of intervals */
*curr, /* BB being checked for out edges */
*succ /* Successor node */
;
//queue *listIi; /* List of intervals */
int i, /* Index to outEdges array */
j; /* Index to successors */
boolT sameGraph; /* Boolean, isomorphic graphs */
{ interval *Ii; /* Interval being processed */
BB *BBnode, /* New basic block of intervals */
*curr, /* BB being checked for out edges */
*succ, /* Successor node */
derInt;
queue *listIi; /* List of intervals */
Int i, /* Index to outEdges array */
j; /* Index to successors */
boolT sameGraph; /* Boolean, isomorphic graphs */
/* Process Gi's intervals */
derSeq_Entry &prev_entry(derivedGi.back());
derivedGi.push_back(derSeq_Entry());
derSeq_Entry &new_entry(derivedGi.back());
Ii = prev_entry.Ii;
sameGraph = true;
BBnode = 0;
std::vector<BB *> bbs;
while (Ii)
{
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);
derivedGi->next = newDerivedSeq();
Ii = derivedGi->Ii;
sameGraph = TRUE;
derInt.next = NULL;
BBnode = &derInt;
/* Check for more than 1 interval */
if (sameGraph && (listIi.size()>1))
sameGraph = false;
while (Ii) {
i = 0;
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)
{
for(BB *curr : listIi)
{
for (j = 0; j < curr->edges.size(); j++)
{
succ = curr->edges[j].BBptr;
if (succ->inInterval != curr->inInterval)
BBnode->edges[i++].intPtr = succ->inInterval;
}
}
}
/* Find out edges */
if (BBnode->numOutEdges > 0)
while (listIi) {
curr = listIi->node;
for (j = 0; j < curr->numOutEdges; j++) {
succ = curr->edges[j].BBptr;
if (succ->inInterval != curr->inInterval)
BBnode->edges[i++].intPtr = succ->inInterval;
}
listIi = listIi->next;
}
/* Next interval */
Ii = Ii->next;
/* Next interval */
Ii = Ii->next;
}
/* Convert list of pointers to intervals into a real graph.
* Determines the number of in edges to each new BB, and places it
* in numInEdges and inEdgeCount for later interval processing. */
curr = new_entry.Gi = bbs.front();
for(BB *curr : bbs)
{
for(TYPEADR_TYPE &edge : curr->edges)
{
BBnode = new_entry.Gi; /* BB of an interval */
auto iter= std::find_if(bbs.begin(),bbs.end(),
[&edge](BB *node)->bool { return edge.intPtr==node->correspInt;});
if(iter==bbs.end())
fatalError (INVALID_INT_BB);
edge.BBptr = *iter;
(*iter)->inEdges.push_back((BB *)nullptr);
(*iter)->inEdgeCount++;
}
curr = derivedGi->next->Gi = derInt.next;
while (curr) {
for (i = 0; i < curr->numOutEdges; i++) {
BBnode = derivedGi->next->Gi; /* BB of an interval */
while (BBnode && curr->edges[i].intPtr != BBnode->correspInt)
BBnode = BBnode->next;
if (BBnode) {
curr->edges[i].BBptr = BBnode;
BBnode->numInEdges++;
BBnode->inEdgeCount++;
}
else
fatalError (INVALID_INT_BB);
}
curr = curr->next;
}
return (boolT)(! sameGraph);
}
static byte findDerivedSeq (derSeq *derivedGi)
/* Finds the derived sequence of the graph derivedG->Gi (ie. cfg).
* Constructs the n-th order graph and places all the intermediate graphs
* in the derivedG list sequence. */
uint8_t Function::findDerivedSeq (derSeq &derivedGi)
{
BB *Gi; /* Current derived sequence graph */
{ BB *Gi; /* Current derived sequence graph */
derSeq::iterator iter=derivedGi.begin();
Gi = iter->Gi;
Gi = derivedGi->Gi;
while (! trivialGraph (Gi))
{
/* Find the intervals of Gi and place them in derivedGi->Ii */
iter->findIntervals(this);
/* Find the intervals of Gi and place them in derivedGi->Ii */
findIntervals (derivedGi);
/* Create Gi+1 and check if it is equivalent to Gi */
if (! nextOrderGraph (derivedGi))
/* Create Gi+1 and check if it is equivalent to Gi */
if (! nextOrderGraph (derivedGi))
break;
++iter;
Gi = iter->Gi;
stats.nOrder++;
derivedGi = derivedGi->next;
Gi = derivedGi->Gi;
stats.nOrder++;
}
if (! trivialGraph (Gi))
{
++iter;
derivedGi.erase(iter,derivedGi.end()); /* remove Gi+1 */
// freeDerivedSeq(derivedGi->next);
// derivedGi->next = NULL;
return false;
freeDerivedSeq(derivedGi->next); /* remove Gi+1 */
derivedGi->next = NULL;
return FALSE;
}
derivedGi.back().findIntervals (this);
return true;
findIntervals (derivedGi);
return TRUE;
}
static void nodeSplitting (BB *G)
/* Converts the irreducible graph G into an equivalent reducible one, by
* means of node splitting. */
static void nodeSplitting (std::list<BB *> &G)
{
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
}
void displayDerivedSeq(derSeq *derGi)
/* Displays the derived sequence and intervals of the graph G */
void derSeq::display()
{
int n = 1; /* Derived sequence number */
Int n = 1; /* Derived sequence number */
printf ("\nDerived Sequence Intervals\n");
derSeq::iterator iter=this->begin();
while (iter!=this->end())
while (derGi)
{
printf ("\nIntervals for G%lX\n", n++);
displayIntervals (iter->Ii);
++iter;
printf ("\nIntervals for G%lX\n", n++);
displayIntervals (derGi->Ii);
derGi = derGi->next;
}
}
void checkReducibility (PPROC pProc, derSeq **derivedG)
/* Checks whether the control flow graph, cfg, is reducible or not.
* If it is not reducible, it is converted into an equivalent reducible
* graph by node splitting. The derived sequence of graphs built from cfg
* are returned in the pointer *derivedG.
*/
derSeq * Function::checkReducibility()
{
derSeq * der_seq;
uint8_t reducible; /* Reducible graph flag */
{ byte reducible; /* Reducible graph flag */
numInt = 1; /* reinitialize no. of intervals*/
stats.nOrder = 1; /* nOrder(cfg) = 1 */
der_seq = new derSeq;
der_seq->resize(1);
der_seq->back().Gi = m_cfg.front();
reducible = findDerivedSeq(*der_seq);
stats.nOrder = 1; /* nOrder(cfg) = 1 */
*derivedG = newDerivedSeq();
(*derivedG)->Gi = pProc->cfg;
reducible = findDerivedSeq(*derivedG);
if (! reducible)
{
flg |= GRAPH_IRRED;
nodeSplitting (m_cfg);
if (! reducible) {
pProc->flg |= GRAPH_IRRED;
nodeSplitting (pProc->cfg);
}
return der_seq;
}

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
\* * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements a symbol table with a symbolic name, a symbol value
(uint16_t), and a procedure number. Two tables are maintained, to be able to
(word), and a procedure number. Two tables are maintained, to be able to
look up by name or by value. Pointers are used for the duplicated symbolic
name to save space. Both tables have the same structure.
The hash tables automatically expand when they get 90% full; they are
@ -19,176 +19,564 @@
Linear probing is used, due to the difficulty of implementing (e.g.)
quadratic probing with a variable table size.
*/
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <unordered_map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dcc.h"
#include "symtab.h"
#define TABLESIZE 16 /* Number of entries added each expansion */
/* Probably has to be a power of 2 */
/* Probably has to be a power of 2 */
#define STRTABSIZE 256 /* Size string table is inc'd by */
#define NIL ((uint16_t)-1)
using namespace std;
#define NIL ((word)-1)
static word numEntry; /* Number of entries in this table */
static word tableSize; /* Size of the table (entries) */
static SYMTABLE *symTab; /* Pointer to the symbol hashed table */
static SYMTABLE *valTab; /* Pointer to the value hashed table */
static char *pStrTab; /* Pointer to the current string table */
static int strTabNext; /* Next free index into pStrTab */
namespace std
{
template<>
struct hash<SYMTABLE> : public unary_function<const SYMTABLE &,size_t>
{
size_t operator()(const SYMTABLE & key) const
{
uint16_t h = 0;
h = (uint16_t)(key.symOff ^ (key.symOff >> 8));
return h;
}
};
}
static tableType curTableType; /* Which table is current */
struct TABLEINFO_TYPE
typedef struct _tableInfo
{
TABLEINFO_TYPE()
{
symTab=valTab=0;
}
//void deleteVal(uint32_t symOff, Function *symProc, boolT bSymToo);
void create(tableType type);
void destroy();
private:
SYMTABLE *symTab;
SYMTABLE *valTab;
word numEntry;
word tableSize;
} TABLEINFO_TYPE;
SYMTABLE *symTab; /* Pointer to the symbol hashed table */
SYMTABLE *valTab; /* Pointer to the value hashed table */
uint16_t numEntry; /* Number of entries in this table */
uint16_t tableSize;/* Size of the table (entries) */
unordered_map<string,SYMTABLE> z;
unordered_map<SYMTABLE,string> z2;
};
TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */
static TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */
static TABLEINFO_TYPE currentTabInfo;
/* Local prototypes */
static void expandSym(void);
/* Create a new symbol table. Returns "handle" */
void TABLEINFO_TYPE::create(tableType type)
{
switch(type)
{
case Comment:
numEntry = 0;
tableSize = TABLESIZE;
valTab = new SYMTABLE [TABLESIZE];
symTab = 0;
break;
case Label:
currentTabInfo.numEntry = 0;
currentTabInfo.tableSize = TABLESIZE;
currentTabInfo.symTab = new SYMTABLE [TABLESIZE];
currentTabInfo.valTab = new SYMTABLE [TABLESIZE];
break;
}
}
void createSymTables(void)
{
/* Initilise the comment table */
/* NB - there is no symbol hashed comment table */
currentTabInfo.create(Comment);
tableInfo[Comment] = currentTabInfo;
numEntry = 0;
tableSize = TABLESIZE;
valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE);
tableInfo[Comment].symTab = 0;
tableInfo[Comment].valTab = valTab;
tableInfo[Comment].numEntry = numEntry;
tableInfo[Comment].tableSize = tableSize;
/* Initialise the label table */
currentTabInfo.create(Label);
numEntry = 0;
tableSize = TABLESIZE;
symTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
memset(symTab, 0, sizeof(SYMTABLE) * TABLESIZE);
tableInfo[Label] = currentTabInfo;
valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE);
tableInfo[Label].symTab = symTab;
tableInfo[Label].valTab = valTab;
tableInfo[Label].numEntry = numEntry;
tableInfo[Label].tableSize = tableSize;
curTableType = Label;
/* Now the string table */
strTabNext = 0;
pStrTab = new char[STRTABSIZE];
pStrTab = (char *)allocMem(STRTABSIZE);
tableInfo[Label].symTab = symTab;
tableInfo[Label].valTab = valTab;
tableInfo[Label].numEntry = numEntry;
tableInfo[Label].tableSize = tableSize;
curTableType = Label;
}
void selectTable(tableType tt)
void
selectTable(tableType tt)
{
if (curTableType == tt)
return; /* Nothing to do */
currentTabInfo = tableInfo[tt];
if (curTableType == tt) return; /* Nothing to do */
symTab = tableInfo[tt].symTab;
valTab = tableInfo[tt].valTab;
numEntry = tableInfo[tt].numEntry;
tableSize= tableInfo[tt].tableSize;
curTableType = tt;
}
void TABLEINFO_TYPE::destroy()
{
delete [] symTab; // The symbol hashed label table
delete [] valTab; // And the value hashed label table
}
void destroySymTables(void)
{
selectTable(Label);
currentTabInfo.destroy();
free(symTab); /* The symbol hashed label table */
free(valTab); /* And the value hashed label table */
selectTable(Comment);
currentTabInfo.destroy();
free(valTab); /* And the value hashed comment table */
}
/* Using the value, read the symbolic name */
boolT readVal(std::ostringstream &symName, uint32_t symOff, Function * symProc)
{
return false; // no symbolic names for now
}
/* Updates the type of the symbol in the symbol table. The size is updated
* if necessary (0 means no update necessary). */
void SYMTAB::updateSymType (uint32_t symbol,const TypeContainer &tc)
/* Hash the symbolic name */
word symHash(char *name, word *pre)
{
int i;
auto iter=findByLabel(symbol);
if(iter==end())
return;
iter->type = tc.m_type;
if (tc.m_size != 0)
iter->size = tc.m_size;
}
word h = 0;
char ch;
/* Creates an entry in the global symbol table (symtab) if the variable
* is not there yet. If it is part of the symtab, the size of the variable
* is checked and updated if the old size was less than the new size (ie.
* the maximum size is always saved). */
//TODO: SYMTAB::updateGlobSym should be renamed to insertOrUpdateSym
SYM * SYMTAB::updateGlobSym (uint32_t operand, int size, uint16_t duFlag,bool &inserted_new)
{
/* Check for symbol in symbol table */
auto iter = findByLabel(operand);
if(iter!=end())
for (i=0; i < (int)strlen(name); i++)
{
if(iter->size<size)
iter->size = size;
inserted_new=false;
return &(*iter);
ch = name[i];
h = (h << 2) ^ ch;
h += (ch >> 2) + (ch << 5);
}
/* New symbol, not in symbol table */
SYM v;
char buf[32]={};
sprintf (buf, "var%05X", operand);
v.name = buf;
v.label = operand;
v.size = size;
v.type = TypeContainer::defaultTypeForSize(size);
if (duFlag == eDuVal::USE) /* must already have init value */
*pre = h; /* Pre modulo hash value */
return h % tableSize; /* Post modulo hash value */
}
/* Hash the symOff and symProc fields */
/* Note: for the time being, there no use is made of the symProc field */
word
valHash(dword symOff, PPROC symProc, word *pre)
{
word h = 0;
h = (word)(symOff ^ (symOff >> 8));
*pre = h; /* Pre modulo hash value */
return h % tableSize; /* Post modulo hash value */
}
void
enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo)
{
word h, pre, j;
if ((numEntry / 9 * 10) >= tableSize)
{
v.duVal.use =1; // USEVAL;
v.duVal.val =1;
/* Table is full. Expand it */
expandSym();
}
/* Enter it into the value hashed table first */
h = valHash(symOff, symProc, &pre); /* Ideal spot for this entry */
if (valTab[h].symProc == 0) /* Collision? */
{
/* No. Just insert here */
valTab[h].pSymName= symName; /* Symbol name ptr */
valTab[h].symOff = symOff; /* Offset of the symbol */
valTab[h].symProc = symProc; /* Symbol's proc num */
valTab[h].preHash = pre; /* Pre modulo hash value */
valTab[h].postHash= h; /* Post modulo hash value */
valTab[h].nextOvf = NIL; /* No overflow */
valTab[h].prevOvf = NIL; /* No back link */
}
else
{
v.duVal.setFlags(duFlag);
/* Linear probing, for now */
j = (h+1) % tableSize;
while (j != h)
{
if (valTab[j].symProc == 0)
{
/* Insert here */
valTab[j].pSymName= symName; /* Symbol name ptr */
valTab[j].symOff = symOff; /* Offset of the symbol */
valTab[j].symProc = symProc; /* Symbol's proc num */
valTab[j].preHash = pre; /* Pre modulo hash value */
valTab[j].postHash= h; /* Post modulo hash value */
/* Insert after the primary entry in the table */
valTab[j].nextOvf = valTab[h].nextOvf;
valTab[h].nextOvf = j;
valTab[j].prevOvf = h; /* The backlink */
break;
}
else
{
/* Probe further */
j = (j+1) % tableSize;
}
}
if (j == h)
{
printf("enterSym: val table overflow!\n");
exit(1);
}
}
push_back(v);
inserted_new=true;
return (&back());
/* Now enter into the symbol hashed table as well, if reqd */
if (!bSymToo) return;
h = symHash(symName, &pre); /* Ideal spot for this entry */
if (symTab[h].pSymName == 0) /* Collision? */
{
/* No. Just insert here */
symTab[h].pSymName= symName; /* Symbol name ptr */
symTab[h].symOff = symOff; /* Offset of the symbol */
symTab[h].symProc = symProc; /* Symbol's proc num */
symTab[h].preHash = pre; /* Pre modulo hash value */
symTab[h].postHash= h; /* Post modulo hash value */
symTab[h].nextOvf = NIL; /* No overflow */
symTab[h].prevOvf = NIL; /* No back link */
}
else
{
/* Linear probing, for now */
j = (h+1) % tableSize;
while (j != h)
{
if (symTab[j].pSymName == 0)
{
/* Insert here */
symTab[j].pSymName= symName; /* Symbol name ptr */
symTab[j].symOff = symOff; /* Offset of the symbol */
symTab[j].symProc = symProc; /* Symbol's proc num */
symTab[j].preHash = pre; /* Pre modulo hash value */
symTab[j].postHash= h; /* Post modulo hash value */
/* Insert after the primary entry in the table */
symTab[j].nextOvf = symTab[h].nextOvf;
symTab[h].nextOvf = j;
symTab[j].prevOvf = h; /* The backlink */
break;
}
else
{
/* Probe further */
j = (j+1) % tableSize;
}
}
if (j == h)
{
printf("enterSym: sym table overflow!\n");
exit(1);
}
}
}
//template<> class SymbolTableCommon<SYM>;
//template<> class SymbolTableCommon<STKSYM>;
boolT
findSym(char *symName, word *pIndex)
{
word h, j, pre;
h = symHash(symName, &pre);
j = h;
do
{
if (symTab[j].pSymName == 0)
{
return FALSE; /* No entry at all */
}
if (strcmp(symName, symTab[j].pSymName) == 0)
{
*pIndex = j;
return TRUE; /* Symbol found */
}
j = symTab[j].nextOvf; /* Follow the chain */
}
while (j != NIL);
return FALSE; /* End of chain */
}
/* Find symbol by value */
boolT
findVal(dword symOff, PPROC symProc, word *pIndex)
{
word h, j, pre;
h = valHash(symOff, symProc, &pre);
j = h;
do
{
if (valTab[j].symProc == 0)
{
return FALSE; /* No entry at all */
}
if ((valTab[j].symOff == symOff)
/*&& (valTab[j].symProc == symProc)*/)
{
*pIndex = j;
return TRUE; /* Symbol found */
}
j = valTab[j].nextOvf; /* Follow the chain */
}
while (j != NIL);
return FALSE; /* End of chain */
}
word
findBlankSym(char *symName)
{
word h, j, pre;
h = symHash(symName, &pre);
j = h;
do
{
if (symTab[j].pSymName == 0)
{
return j; /* Empty entry. Terminate probing */
}
j = (++j) % tableSize; /* Linear probing */
}
while (j != h);
printf("Could not find blank entry in table! Num entries is %ld of %ld\n",
(long)numEntry, (long)tableSize);
return 0;
}
/* Using the symbolic name, read the value */
boolT
readSym(char *symName, dword *pSymOff, PPROC *pSymProc)
{
word i;
if (!findSym(symName, &i))
{
return FALSE;
}
*pSymOff = symTab[i].symOff;
*pSymProc= symTab[i].symProc;
return TRUE;
}
/* Using the value, read the symbolic name */
boolT
readVal(char *symName, dword symOff, PPROC symProc)
{
word i;
if (!findVal(symOff, symProc, &i))
{
return FALSE;
}
strcpy(symName, valTab[i].pSymName);
return TRUE;
}
/* A doubly linked list of entries belonging to the same hash bucket is
maintained, to prevent the need for many entries to be moved when deleting
an entry. It is implemented with indexes, and is not an open hashing system.
Symbols are deleted from both hash tables.
*/
/* Known limitation: strings are never deleted from the string table */
void
deleteSym(char *symName)
{
word i, j, back;
dword symOff;
PPROC symProc;
/* Delete from symbol hashed table first */
if (!findSym(symName, &i))
{
printf("Could not delete non existant symbol name %s\n", symName);
exit(1);
}
symOff = symTab[i].symOff; /* Remember these for valTab */
symProc= symTab[i].symProc;
j = symTab[i].nextOvf; /* Look at next overflowed entry */
if (j == NIL) /* Any overflows? */
{
/* No, so we just wipe out this record. Must NIL the pointer of
the previous record, however */
symTab[symTab[i].prevOvf].nextOvf = NIL;
j = i; /* So we wipe out the current name */
}
else
{
/* Yes, move this entry to this vacated spot. Note that the nextOvf
field will still point to the next record in the overflow chain,
but we need to preserve the backlink for adjusting the current
item's backlink */
back = symTab[j].prevOvf;
memcpy(&symTab[i], &symTab[j], sizeof(SYMTABLE));
symTab[i].prevOvf = back;
}
/* And now mark the vacated record as empty */
symTab[j].pSymName = 0; /* Rub out the name */
/* Delete from value hashed table */
if (!findVal(symOff, symProc, &i))
{
printf("Could not delete non existant symbol off %04X proc %d\n",
symOff, symProc);
exit(1);
}
j = valTab[i].nextOvf; /* Look at next overflowed entry */
if (j == NIL) /* Any overflows? */
{
/* No, so we just wipe out this record. Must NIL the pointer of
the previous record, however */
valTab[valTab[i].prevOvf].nextOvf = NIL;
j = i; /* So we wipe out the current entry */
}
else
{
/* Yes, move this entry to this vacated spot. Note that the nextOvf
field will still point to the next record in the overflow chain,
but we need to preserve the backlink for adjusting the current
item's backlink */
back = valTab[j].prevOvf;
memcpy(&valTab[i], &valTab[j], sizeof(SYMTABLE));
valTab[i].prevOvf = back;
}
/* And now mark the vacated record as empty */
valTab[j].symProc = 0; /* Rub out the entry */
}
void
deleteVal(dword symOff, PPROC symProc, boolT bSymToo)
{
word i, j, back;
char *symName;
/* Delete from value hashed table */
if (!findVal(symOff, symProc, &i))
{
printf("Could not delete non existant symbol off %04X proc %p\n",
symOff, symProc);
exit(1);
}
symName = symTab[i].pSymName; /* Remember this for symTab */
j = valTab[i].nextOvf; /* Look at next overflowed entry */
if (j == NIL) /* Any overflows? */
{
/* No, so we just wipe out this record. Must NIL the pointer of
the previous record, however */
valTab[valTab[i].prevOvf].nextOvf = NIL;
j = i; /* So we wipe out the current entry */
}
else
{
/* Yes, move this entry to this vacated spot. Note that the nextOvf
field will still point to the next record in the overflow chain,
but we need to preserve the backlink for adjusting the current
item's backlink */
back = valTab[j].prevOvf;
memcpy(&valTab[i], &valTab[j], sizeof(SYMTABLE));
valTab[i].prevOvf = back;
}
/* And now mark the vacated record as empty */
valTab[j].symProc = 0; /* Rub out the entry */
/* If requested, delete from symbol hashed table now */
if (!bSymToo) return;
if (!findSym(symName, &i))
{
printf("Could not delete non existant symbol name %s\n", symName);
exit(1);
}
j = symTab[i].nextOvf; /* Look at next overflowed entry */
if (j == NIL) /* Any overflows? */
{
/* No, so we just wipe out this record. Must NIL the pointer of
the previous record, however */
symTab[symTab[i].prevOvf].nextOvf = NIL;
j = i; /* So we wipe out the current name */
}
else
{
/* Yes, move this entry to this vacated spot. Note that the nextOvf
field will still point to the next record in the overflow chain,
but we need to preserve the backlink for adjusting the current
item's backlink */
back = symTab[j].prevOvf;
memcpy(&symTab[i], &symTab[j], sizeof(SYMTABLE));
symTab[i].prevOvf = back;
}
/* And now mark the vacated record as empty */
symTab[j].pSymName = 0; /* Rub out the name */
}
static void
expandSym(void)
{
word i, j, n, newPost;
printf("\nResizing table...\r");
/* We double the table size each time, so on average only half of the
entries move to the new half. This works because we are effectively
shifting the "binary point" of the hash value to the left each time,
thereby leaving the number unchanged or adding an MSBit of 1. */
tableSize <<= 2;
symTab = (SYMTABLE*)reallocVar(symTab, tableSize * sizeof(SYMTABLE));
memset (&symTab[tableSize/2], 0, (tableSize/2) * sizeof(SYMTABLE));
/* Now we have to move some of the entries to take advantage of the extra
space */
for (i=0; i < numEntry; i++)
{
newPost = symTab[i].preHash % tableSize;
if (newPost != symTab[i].postHash)
{
/* This entry is now in the wrong place. Copy it to the new position,
then delete it. */
j = findBlankSym(symTab[i].pSymName);
memcpy(&symTab[j], &symTab[i], sizeof(SYMTABLE));
/* Correct the post hash value */
symTab[j].postHash = newPost;
/* Now adjust links */
n = symTab[j].prevOvf;
if (n != NIL)
{
symTab[n].nextOvf = j;
}
n = symTab[j].nextOvf;
if (n != NIL)
{
symTab[n].prevOvf = j;
}
/* Mark old position as deleted */
symTab[i].pSymName = 0;
}
}
}
/* This function adds to the string table. At this stage, strings are not
deleted */
char *
addStrTbl(char *pStr)
{
char *p;
if ((strTabNext + strlen(pStr) + 1) >= STRTABSIZE)
{
/* We can't realloc the old string table pointer, since that will
potentially move the string table, and pointers will be invalid.
So we realloc this one to its present usage (hopefully it won't
move), and allocate a new one */
if (reallocVar((void *)pStrTab, strTabNext) != pStrTab)
{
printf("Damn it! String table moved on shrinking!\n");
exit(1);
}
pStrTab = (char *)allocMem(STRTABSIZE);
strTabNext = 0;
}
p = strcpy(&pStrTab[strTabNext], pStr);
strTabNext += strlen(pStr) +1;
return p;
}

View File

@ -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();
}

View File

@ -4,104 +4,154 @@
* that just plays with abstract cfg's and intervals and such like.
* (C) Cristina Cifuentes
****************************************************************************/
#include <list>
#include <cassert>
#include <stdio.h>
#include "dcc.h"
#include "disassem.h"
#include "project.h"
extern Project g_proj;
static void displayCFG(Function * pProc);
static void displayDfs(BB * pBB);
#include "dcc.h"
#include <stdio.h>
static void displayCFG(PPROC pProc);
static void displayDfs(PBB pBB);
/****************************************************************************
* udm
****************************************************************************/
void Function::buildCFG(Disassembler &ds)
{
if(flg & PROC_ISLIB)
return; // Ignore library functions
createCFG();
if (option.VeryVerbose)
displayCFG();
compressCFG(); // Remove redundancies and add in-edge information
if (option.asm2)
{
ds.disassem(this); // Print 2nd pass assembler listing
}
/* Idiom analysis and propagation of long type */
lowLevelAnalysis();
/* Generate HIGH_LEVEL icodes whenever possible */
highLevelGen();
}
void Function::controlFlowAnalysis()
{
if (flg & PROC_ISLIB)
return; /* Ignore library functions */
derSeq *derivedG=0;
/* Make cfg reducible and build derived sequences */
derivedG=checkReducibility();
if (option.VeryVerbose)
derivedG->display();
/* Structure the graph */
structure(derivedG);
/* Check for compound conditions */
compoundCond ();
if (option.verbose)
{
printf("\nDepth first traversal - Proc %s\n", name.c_str());
m_cfg.front()->displayDfs();
}
/* Free storage occupied by this procedure */
freeDerivedSeq(*derivedG);
}
void udm(void)
{
{ PPROC pProc;
derSeq *derivedG;
/* Build the control flow graph, find idioms, and convert low-level
* icodes to high-level ones */
Disassembler ds(2);
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
{
iter->buildCFG(ds);
}
/* Build the control flow graph, find idioms, and convert low-level
* icodes to high-level ones */
for (pProc = pLastProc; pProc; pProc = pProc->prev)
{
if (pProc->flg & PROC_ISLIB)
continue; /* Ignore library functions */
/* Create the basic control flow graph */
pProc->cfg = createCFG(pProc);
if (option.VeryVerbose)
displayCFG(pProc);
/* Remove redundancies and add in-edge information */
compressCFG(pProc);
/* Print 2nd pass assembler listing */
if (option.asm2)
disassem(2, pProc);
/* Idiom analysis and propagation of long type */
lowLevelAnalysis (pProc);
/* Generate HIGH_LEVEL icodes whenever possible */
highLevelGen (pProc);
}
/* Data flow analysis - eliminate condition codes, extraneous registers
* and intermediate instructions. Find expressions by forward
* substitution algorithm */
std::bitset<32> live_regs;
g_proj.pProcList.front().dataFlow (live_regs);
* and intermediate instructions. Find expressions by forward
* substitution algorithm */
dataFlow (pProcList, 0);
/* Control flow analysis - structuring algorithm */
for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter)
{
iter->controlFlowAnalysis();
/* Control flow analysis - structuring algorithm */
for (pProc = pLastProc; pProc; pProc = pProc->prev)
{
if (pProc->flg & PROC_ISLIB)
continue; /* Ignore library functions */
/* Make cfg reducible and build derived sequences */
checkReducibility(pProc, &derivedG);
if (option.VeryVerbose)
displayDerivedSeq(derivedG);
/* Structure the graph */
structure(pProc, derivedG);
/* Check for compound conditions */
compoundCond (pProc);
if (option.verbose) {
printf("\nDepth first traversal - Proc %s\n", pProc->name);
displayDfs(pProc->cfg);
}
/* Free storage occupied by this procedure */
freeDerivedSeq(derivedG);
}
}
static char *nodeType[] = {"branch", "if", "case", "fall", "return", "call",
"loop", "repeat", "interval", "cycleHead",
"caseHead", "terminate",
"nowhere" };
static char *loopType[] = {"noLoop", "while", "repeat", "loop", "for"};
/****************************************************************************
* displayCFG - Displays the Basic Block list
***************************************************************************/
void Function::displayCFG()
static void displayCFG(PPROC pProc)
{
printf("\nBasic Block List - Proc %s", name.c_str());
for (BB *pBB : m_cfg)
{
pBB->display();
Int i;
PBB pBB;
printf("\nBasic Block List - Proc %s", pProc->name);
for (pBB = pProc->cfg; pBB; pBB = pBB->next) {
printf("\nnode type = %s, ", nodeType[pBB->nodeType]);
printf("start = %ld, length = %ld, #out edges = %ld\n",
pBB->start, pBB->length, pBB->numOutEdges);
for (i = 0; i < pBB->numOutEdges; i++)
printf(" outEdge[%2d] = %ld\n",i, pBB->edges[i].BBptr->start);
}
}
/*****************************************************************************
* displayDfs - Displays the CFG using a depth first traversal
****************************************************************************/
static void displayDfs(PBB pBB)
{
Int i;
if (! pBB)
return;
pBB->traversed = DFS_DISP;
printf("node type = %s, ", nodeType[pBB->nodeType]);
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
pBB->start, pBB->length, pBB->numInEdges, pBB->numOutEdges);
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
pBB->dfsFirstNum, pBB->dfsLastNum,
pBB->immedDom == MAX ? -1 : pBB->immedDom);
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
loopType[pBB->loopType],
pBB->loopHead == MAX ? -1 : pBB->loopHead,
pBB->latchNode == MAX ? -1 : pBB->latchNode,
pBB->loopFollow == MAX ? -1 : pBB->loopFollow);
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
pBB->ifFollow == MAX ? -1 : pBB->ifFollow,
pBB->caseHead == MAX ? -1 : pBB->caseHead,
pBB->caseTail == MAX ? -1 : pBB->caseTail);
if (pBB->nodeType == INTERVAL_NODE)
printf("corresponding interval = %ld\n", pBB->correspInt->numInt);
else for (i = 0; i < pBB->numInEdges; i++)
printf (" inEdge[%ld] = %ld\n", i, pBB->inEdges[i]->start);
/* Display out edges information */
for (i = 0; i < pBB->numOutEdges; i++)
if (pBB->nodeType == INTERVAL_NODE)
printf(" outEdge[%ld] = %ld\n", i,
pBB->edges[i].BBptr->correspInt->numInt);
else
printf(" outEdge[%ld] = %ld\n", i, pBB->edges[i].BBptr->start);
printf("----\n");
/* Recursive call on successors of current node */
for (i = 0; i < pBB->numOutEdges; i++)
if (pBB->edges[i].BBptr->traversed != DFS_DISP)
displayDfs(pBB->edges[i].BBptr);
}