Orignal dcc code
Only 2 differences with original release: add return type to main int disassem.cpp popPosStack() add cast to intptr_t
This commit is contained in:
@@ -1,132 +0,0 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <boost/range.hpp>
|
||||
#include "icode.h"
|
||||
#include "types.h"
|
||||
#include "graph.h"
|
||||
//#include "icode.h"
|
||||
/* Basic block (BB) node definition */
|
||||
struct Function;
|
||||
class CIcodeRec;
|
||||
struct BB;
|
||||
struct LOCAL_ID;
|
||||
struct interval;
|
||||
|
||||
struct TYPEADR_TYPE
|
||||
{
|
||||
uint32_t ip; /* Out edge icode address */
|
||||
BB * BBptr; /* Out edge pointer to next BB */
|
||||
interval *intPtr; /* Out edge ptr to next interval*/
|
||||
};
|
||||
|
||||
struct BB : public llvm::ilist_node<BB>
|
||||
{
|
||||
private:
|
||||
BB(const BB&);
|
||||
BB() : nodeType(0),traversed(DFS_NONE),
|
||||
numHlIcodes(0),flg(0),
|
||||
inEdges(0),
|
||||
edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0),
|
||||
inInterval(0),correspInt(0),liveUse(0),def(0),liveIn(0),liveOut(0),
|
||||
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(0),latchNode(0),
|
||||
numBackEdges(0),loopHead(0),loopFollow(0),caseHead(0),caseTail(0),index(0)
|
||||
{
|
||||
|
||||
}
|
||||
//friend class SymbolTableListTraits<BB, Function>;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
rCODE instructions;
|
||||
|
||||
public:
|
||||
struct ValidFunctor
|
||||
{
|
||||
bool operator()(BB *p) {return p->valid();}
|
||||
};
|
||||
iICODE begin();
|
||||
iICODE end() const;
|
||||
riICODE rbegin();
|
||||
riICODE rend();
|
||||
ICODE &front();
|
||||
ICODE &back();
|
||||
size_t size();
|
||||
uint8_t nodeType; /* Type of node */
|
||||
eDFS traversed; /* last traversal id is held here traversed yet? */
|
||||
int numHlIcodes; /* No. of high-level icodes */
|
||||
uint32_t flg; /* BB flags */
|
||||
|
||||
/* In edges and out edges */
|
||||
std::vector<BB *> inEdges; // does not own held pointers
|
||||
|
||||
//int numOutEdges; /* Number of out edges */
|
||||
std::vector<TYPEADR_TYPE> edges;/* Array of ptrs. to out edges */
|
||||
|
||||
/* For interval construction */
|
||||
int beenOnH; /* #times been on header list H */
|
||||
int inEdgeCount; /* #inEdges (to find intervals) */
|
||||
BB * reachingInt; /* Reaching interval header */
|
||||
interval *inInterval; /* Node's interval */
|
||||
|
||||
/* For derived sequence construction */
|
||||
interval *correspInt; /* Corresponding interval in
|
||||
* derived graph Gi-1 */
|
||||
|
||||
/* For live register analysis
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
std::bitset<32> liveUse; /* LiveUse(b) */
|
||||
std::bitset<32> def; /* Def(b) */
|
||||
std::bitset<32> liveIn; /* LiveIn(b) */
|
||||
std::bitset<32> liveOut; /* LiveOut(b) */
|
||||
|
||||
/* For structuring analysis */
|
||||
int dfsFirstNum; /* DFS #: first visit of node */
|
||||
int dfsLastNum; /* DFS #: last visit of node */
|
||||
int immedDom; /* Immediate dominator (dfsLast
|
||||
* index) */
|
||||
int ifFollow; /* node that ends the if */
|
||||
int loopType; /* Type of loop (if any) */
|
||||
int latchNode; /* latching node of the loop */
|
||||
int numBackEdges; /* # of back edges */
|
||||
int loopHead; /* most nested loop head to which
|
||||
* thcis node belongs (dfsLast) */
|
||||
int loopFollow; /* node that follows the loop */
|
||||
int caseHead; /* most nested case to which this
|
||||
node belongs (dfsLast) */
|
||||
int caseTail; /* tail node for the case */
|
||||
|
||||
int index; /* Index, used in several ways */
|
||||
static BB * Create(void *ctx=0,const std::string &s="",Function *parent=0,BB *insertBefore=0);
|
||||
static BB * Create(int start, int ip, uint8_t nodeType, int numOutEdges, Function * parent);
|
||||
static BB * Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent);
|
||||
void writeCode(int indLevel, Function *pProc, int *numLoc, int latchNode, int ifFollow);
|
||||
void mergeFallThrough(CIcodeRec &Icode);
|
||||
void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last);
|
||||
void displayDfs();
|
||||
void display();
|
||||
/// getParent - Return the enclosing method, or null if none
|
||||
///
|
||||
const Function *getParent() const { return Parent; }
|
||||
Function *getParent() { return Parent; }
|
||||
void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc);
|
||||
BB * rmJMP(int marker, BB *pBB);
|
||||
void genDU1();
|
||||
int findBBExps(LOCAL_ID &locals, Function *f);
|
||||
bool valid() {return 0==(flg & INVALID_BB); }
|
||||
bool wasTraversedAtLevel(int l) const {return traversed==l;}
|
||||
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond);
|
||||
void addOutEdge(uint32_t ip) // TODO: fix this
|
||||
{
|
||||
edges[0].ip = ip;
|
||||
}
|
||||
void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
|
||||
private:
|
||||
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);
|
||||
void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode);
|
||||
bool isEndOfPath(int latch_node_idx) const;
|
||||
Function *Parent;
|
||||
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
struct PROG /* Loaded program image parameters */
|
||||
{
|
||||
int16_t initCS;
|
||||
int16_t initIP; /* These are initial load values */
|
||||
int16_t initSS; /* Probably not of great interest */
|
||||
uint16_t initSP;
|
||||
bool fCOM; /* Flag set if COM program (else EXE)*/
|
||||
int cReloc; /* No. of relocation table entries */
|
||||
uint32_t * relocTable; /* Ptr. to relocation table */
|
||||
uint8_t * map; /* Memory bitmap ptr */
|
||||
int cProcs; /* Number of procedures so far */
|
||||
int offMain; /* The offset of the main() proc */
|
||||
uint16_t segMain; /* The segment of the main() proc */
|
||||
bool bSigs; /* True if signatures loaded */
|
||||
int cbImage; /* Length of image in bytes */
|
||||
uint8_t * Image; /* Allocated by loader to hold entire program image */
|
||||
};
|
||||
|
||||
283
include/Enums.h
283
include/Enums.h
@@ -1,283 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/* Register types */
|
||||
enum regType
|
||||
{
|
||||
BYTE_REG,
|
||||
WORD_REG
|
||||
};
|
||||
enum condId
|
||||
{
|
||||
GLOB_VAR, /* global variable */
|
||||
REGISTER, /* register */
|
||||
LOCAL_VAR, /* negative disp */
|
||||
PARAM, /* positive disp */
|
||||
GLOB_VAR_IDX, /* indexed global variable *//*** should merge w/glob-var*/
|
||||
CONSTANT, /* constant */
|
||||
STRING, /* string */
|
||||
LONG_VAR, /* long variable */
|
||||
FUNCTION, /* function */
|
||||
OTHER /* other **** tmp solution */
|
||||
};
|
||||
|
||||
enum condOp
|
||||
{
|
||||
/* For conditional expressions */
|
||||
LESS_EQUAL, /* <= */
|
||||
LESS, /* < */
|
||||
EQUAL, /* == */
|
||||
NOT_EQUAL, /* != */
|
||||
GREATER, /* > */
|
||||
GREATER_EQUAL, /* >= */
|
||||
/* For general expressions */
|
||||
AND, /* & */
|
||||
OR, /* | */
|
||||
XOR, /* ^ */
|
||||
NOT, /* ~ */ /* 1's complement */
|
||||
ADD, /* + */
|
||||
SUB, /* - */
|
||||
MUL, /* * */
|
||||
DIV, /* / */
|
||||
SHR, /* >> */
|
||||
SHL, /* << */
|
||||
MOD, /* % */
|
||||
DBL_AND, /* && */
|
||||
DBL_OR, /* || */
|
||||
DUMMY /* */
|
||||
};
|
||||
/* LOW_LEVEL operand location: source or destination */
|
||||
enum opLoc
|
||||
{
|
||||
SRC, /* Source operand */
|
||||
DST, /* Destination operand */
|
||||
LHS_OP /* Left-hand side operand (for HIGH_LEVEL) */
|
||||
};
|
||||
/* LOW_LEVEL icode flags */
|
||||
#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */
|
||||
enum eLLFlags
|
||||
{
|
||||
|
||||
B =0x0000001, /* uint8_t operands (value implicitly used) */
|
||||
I =0x0000002, /* Immed. source */
|
||||
NOT_HLL =0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP =0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED =0x0000010, /* Number is relocated segment value */
|
||||
IMPURE =0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF =0x0000040, /* Inst has uint16_t offset ie.could be address */
|
||||
TERMINATES =0x0000080, /* Instruction terminates program */
|
||||
CASE =0x0000100, /* Label as case part of switch */
|
||||
SWITCH =0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET =0x0000400, /* Jump target */
|
||||
SYNTHETIC =0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL =0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE =0x0002000, /* Hole in Icode array */
|
||||
SYM_USE =0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF =0x0008000, /* Instruction defines a symbol */
|
||||
NO_SRC =0x0010000, /* Opcode takes no source */
|
||||
NO_OPS =0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS =0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B =0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
|
||||
HLL_LABEL =0x0100000, /* Icode has a high level language label */
|
||||
IM_DST =0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC =0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST =0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
JMP_ICODE =0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP =0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK =0x4000000 /* Stack needs to be restored after CALL */
|
||||
#define ICODEMASK 0x0FF00FF /* Masks off parser flags */
|
||||
};
|
||||
/* Types of icodes */
|
||||
enum icodeType
|
||||
{
|
||||
NOT_SCANNED = 0, // not even scanned yet
|
||||
LOW_LEVEL, // low-level icode
|
||||
HIGH_LEVEL // high-level icode
|
||||
};
|
||||
|
||||
|
||||
/* LOW_LEVEL icode opcodes */
|
||||
enum llIcode
|
||||
{
|
||||
//iINVALID,
|
||||
iCBW, /* 0 */
|
||||
iAAA,
|
||||
iAAD,
|
||||
iAAM,
|
||||
iAAS,
|
||||
iADC,
|
||||
iADD,
|
||||
iAND,
|
||||
iBOUND,
|
||||
iCALL,
|
||||
iCALLF, /* 10 */
|
||||
iCLC,
|
||||
iCLD,
|
||||
iCLI,
|
||||
iCMC,
|
||||
iCMP,
|
||||
iCMPS,
|
||||
iREPNE_CMPS,
|
||||
iREPE_CMPS,
|
||||
iDAA,
|
||||
iDAS, /* 20 */
|
||||
iDEC,
|
||||
iDIV,
|
||||
iENTER,
|
||||
iESC,
|
||||
iHLT,
|
||||
iIDIV,
|
||||
iIMUL,
|
||||
iIN,
|
||||
iINC,
|
||||
iINS, /* 30 */
|
||||
iREP_INS,
|
||||
iINT,
|
||||
iIRET,
|
||||
iJB,
|
||||
iJBE,
|
||||
iJAE,
|
||||
iJA,
|
||||
iJE,
|
||||
iJNE,
|
||||
iJL, /* 40 */
|
||||
iJGE,
|
||||
iJLE,
|
||||
iJG,
|
||||
iJS,
|
||||
iJNS,
|
||||
iJO,
|
||||
iJNO,
|
||||
iJP,
|
||||
iJNP,
|
||||
iJCXZ, /* 50 */
|
||||
iJMP,
|
||||
iJMPF,
|
||||
iLAHF,
|
||||
iLDS,
|
||||
iLEA,
|
||||
iLEAVE,
|
||||
iLES,
|
||||
iLOCK,
|
||||
iLODS,
|
||||
iREP_LODS, /* 60 */
|
||||
iLOOP,
|
||||
iLOOPE,
|
||||
iLOOPNE,
|
||||
iMOV, /* 64 */
|
||||
iMOVS,
|
||||
iREP_MOVS,
|
||||
iMUL, /* 67 */
|
||||
iNEG,
|
||||
iNOT,
|
||||
iOR, /* 70 */
|
||||
iOUT,
|
||||
iOUTS,
|
||||
iREP_OUTS,
|
||||
iPOP,
|
||||
iPOPA,
|
||||
iPOPF,
|
||||
iPUSH,
|
||||
iPUSHA,
|
||||
iPUSHF,
|
||||
iRCL, /* 80 */
|
||||
iRCR,
|
||||
iROL,
|
||||
iROR,
|
||||
iRET, /* 84 */
|
||||
iRETF,
|
||||
iSAHF,
|
||||
iSAR,
|
||||
iSHL,
|
||||
iSHR,
|
||||
iSBB, /* 90 */
|
||||
iSCAS,
|
||||
iREPNE_SCAS,
|
||||
iREPE_SCAS,
|
||||
iSIGNEX,
|
||||
iSTC,
|
||||
iSTD,
|
||||
iSTI,
|
||||
iSTOS,
|
||||
iREP_STOS,
|
||||
iSUB, /* 100 */
|
||||
iTEST,
|
||||
iWAIT,
|
||||
iXCHG,
|
||||
iXLAT,
|
||||
iXOR,
|
||||
iINTO,
|
||||
iNOP,
|
||||
iREPNE,
|
||||
iREPE,
|
||||
iMOD /* 110 */
|
||||
};
|
||||
/* Conditional Expression enumeration nodes and operators */
|
||||
enum condNodeType
|
||||
{
|
||||
UNKNOWN_OP=0,
|
||||
BOOLEAN_OP, /* condOps */
|
||||
NEGATION, /* not (2's complement) */
|
||||
ADDRESSOF, /* addressOf (&) */
|
||||
DEREFERENCE, /* contents of (*) */
|
||||
IDENTIFIER, /* {register | local | param | constant | global} */
|
||||
/* The following are only available to C programs */
|
||||
POST_INC, /* ++ (post increment) */
|
||||
POST_DEC, /* -- (post decrement) */
|
||||
PRE_INC, /* ++ (pre increment) */
|
||||
PRE_DEC /* -- (pre decrement) */
|
||||
} ;
|
||||
|
||||
/* Enumeration to determine whether pIcode points to the high or low part
|
||||
* of a long number */
|
||||
enum hlFirst
|
||||
{
|
||||
HIGH_FIRST, /* High value is first */
|
||||
LOW_FIRST /* Low value is first */
|
||||
};
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
enum hlIcode
|
||||
{
|
||||
HLI_INVALID,
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
HLI_RET, /* Return from procedure */
|
||||
/* pseudo high-level icodes */
|
||||
HLI_POP, /* Pop expression */
|
||||
HLI_PUSH /* Push expression */
|
||||
} ;
|
||||
/* Type definitions used in the decompiled program */
|
||||
enum hlType
|
||||
{
|
||||
TYPE_UNKNOWN = 0, /* unknown so far */
|
||||
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
|
||||
TYPE_BYTE_UNSIGN, /* unsigned byte */
|
||||
TYPE_WORD_SIGN, /* signed word (16 bits) */
|
||||
TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */
|
||||
TYPE_LONG_SIGN, /* signed long (32 bits) */
|
||||
TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */
|
||||
TYPE_RECORD, /* record structure */
|
||||
TYPE_PTR, /* pointer (32 bit ptr) */
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE /* double precision float */
|
||||
};
|
||||
|
||||
/* Operand is defined, used or both flag */
|
||||
enum operDu
|
||||
{
|
||||
eDEF=0x10, /* Operand is defined */
|
||||
eUSE=0x100, /* Operand is used */
|
||||
USE_DEF, /* Operand is used and defined */
|
||||
NONE /* No operation is required on this operand */
|
||||
};
|
||||
|
||||
/* LOW_LEVEL icode, DU flag bits */
|
||||
enum eDuFlags
|
||||
{
|
||||
Cf=1,
|
||||
Sf=2,
|
||||
Zf=4,
|
||||
Df=8
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#include "ast.h"
|
||||
#include "types.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
struct IDENTTYPE
|
||||
{
|
||||
condId idType;
|
||||
regType regiType; /* for REGISTER only */
|
||||
union _idNode {
|
||||
int regiIdx; /* index into localId, REGISTER */
|
||||
int globIdx; /* index into symtab for GLOB_VAR */
|
||||
int localIdx; /* idx into localId, LOCAL_VAR */
|
||||
int paramIdx; /* idx into args symtab, PARAMS */
|
||||
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
struct _kte
|
||||
{ /* for CONSTANT only */
|
||||
uint32_t kte; /* value of the constant */
|
||||
uint8_t size; /* #bytes size constant */
|
||||
} kte;
|
||||
uint32_t strIdx; /* idx into image, for STRING */
|
||||
int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/
|
||||
struct _call { /* for FUNCTION only */
|
||||
Function *proc;
|
||||
STKFRAME *args;
|
||||
} call;
|
||||
struct { /* for OTHER; tmp struct */
|
||||
eReg seg; /* segment */
|
||||
eReg regi; /* index mode */
|
||||
int16_t off; /* offset */
|
||||
} other;
|
||||
} idNode;
|
||||
};
|
||||
@@ -1,199 +0,0 @@
|
||||
#pragma once
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <bitset>
|
||||
#include "BasicBlock.h"
|
||||
#include "locident.h"
|
||||
#include "state.h"
|
||||
#include "icode.h"
|
||||
#include "StackFrame.h"
|
||||
/* PROCEDURE NODE */
|
||||
struct CALL_GRAPH;
|
||||
struct COND_EXPR;
|
||||
struct Disassembler;
|
||||
struct Function;
|
||||
struct CALL_GRAPH;
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
// Traits for intrusive list of basic blocks...
|
||||
template<>
|
||||
struct ilist_traits<BB> : public ilist_default_traits<BB>
|
||||
{
|
||||
|
||||
// createSentinel is used to get hold of the node that marks the end of the
|
||||
// list... (same trick used here as in ilist_traits<Instruction>)
|
||||
BB *createSentinel() const {
|
||||
return static_cast<BB*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(BB*) {}
|
||||
|
||||
BB *provideInitialHead() const { return createSentinel(); }
|
||||
BB *ensureHead(BB*) const { return createSentinel(); }
|
||||
static void noteHead(BB*, BB*) {}
|
||||
|
||||
//static ValueSymbolTable *getSymTab(Function *ItemParent);
|
||||
private:
|
||||
mutable ilist_half_node<BB> Sentinel;
|
||||
};
|
||||
}
|
||||
/* Procedure FLAGS */
|
||||
enum PROC_FLAGS
|
||||
{
|
||||
PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */
|
||||
PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
|
||||
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
|
||||
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
|
||||
CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
|
||||
CALL_C =0x00004000, /* Proc uses C calling convention */
|
||||
CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
|
||||
PROC_NEAR =0x00010000, /* Proc exits with near return */
|
||||
PROC_FAR =0x00020000, /* Proc exits with far return */
|
||||
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
|
||||
SI_REGVAR =0x00200000, /* SI is used as a stack variable */
|
||||
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
|
||||
PROC_IS_FUNC=0x00800000, /* Proc is a function */
|
||||
REG_ARGS =0x01000000, /* Proc has registers as arguments */
|
||||
PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
|
||||
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
|
||||
PROC_ISLIB =0x10000000, /* Proc is a library function */
|
||||
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
|
||||
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
|
||||
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
};
|
||||
|
||||
struct FunctionType
|
||||
{
|
||||
bool m_vararg;
|
||||
bool isVarArg() const {return m_vararg;}
|
||||
};
|
||||
struct Assignment
|
||||
{
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
};
|
||||
struct JumpTable
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t finish;
|
||||
bool valid() {return start<finish;}
|
||||
size_t size() { return (finish-start)/2;}
|
||||
size_t entrySize() { return 2;}
|
||||
void pruneEntries(uint16_t cs);
|
||||
};
|
||||
|
||||
struct Function : public llvm::ilist_node<Function>
|
||||
{
|
||||
typedef llvm::iplist<BB> BasicBlockListType;
|
||||
// BasicBlock iterators...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
typedef BasicBlockListType::const_iterator const_iterator;
|
||||
private:
|
||||
BasicBlockListType BasicBlocks; ///< The basic blocks
|
||||
|
||||
public:
|
||||
uint32_t procEntry; /* label number */
|
||||
std::string name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
int depth; /* Depth at which we found it - for printing */
|
||||
uint32_t flg; /* Combination of Icode & Proc flags */
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
std::list<BB*> m_cfg; /* Ptr. to BB list/CFG */
|
||||
std::vector<BB*> m_dfsLast;
|
||||
std::list<BB*> heldBBs;
|
||||
//BB * *dfsLast; /* Array of pointers to BBs in dfsLast
|
||||
// * (reverse postorder) order */
|
||||
size_t numBBs; /* Number of BBs in the graph cfg */
|
||||
bool hasCase; /* Procedure has a case node */
|
||||
|
||||
/* For interprocedural live analysis */
|
||||
std::bitset<32> liveIn; /* Registers used before defined */
|
||||
std::bitset<32> liveOut; /* Registers that may be used in successors */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
Function(void *ty=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
static Function *Create(void *ty=0,int Linkage=0,const std::string &nm="",void *module=0)
|
||||
{
|
||||
Function *r=new Function(ty);
|
||||
r->name = nm;
|
||||
return r;
|
||||
}
|
||||
bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
||||
void compoundCond();
|
||||
void writeProcComments();
|
||||
void lowLevelAnalysis();
|
||||
void bindIcodeOff();
|
||||
void dataFlow(std::bitset<32> &liveOut);
|
||||
void compressCFG();
|
||||
void highLevelGen();
|
||||
void structure(derSeq *derivedG);
|
||||
derSeq *checkReducibility();
|
||||
void createCFG();
|
||||
void markImpure();
|
||||
void findImmedDom();
|
||||
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void process_operands(ICODE &pIcode, STATE *pstate);
|
||||
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
boolT process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void freeCFG();
|
||||
void codeGen(std::ostream &fs);
|
||||
void mergeFallThrough(BB *pBB);
|
||||
void structIfs();
|
||||
void structLoops(derSeq *derivedG);
|
||||
void buildCFG(Disassembler &ds);
|
||||
void controlFlowAnalysis();
|
||||
void newRegArg(iICODE picode, iICODE ticode);
|
||||
void writeProcComments(std::ostream &ostr);
|
||||
|
||||
void displayCFG();
|
||||
void displayStats();
|
||||
void processHliCall(COND_EXPR *exp, iICODE picode);
|
||||
|
||||
void preprocessReturnDU(std::bitset<32> &_liveOut);
|
||||
protected:
|
||||
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
|
||||
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b);
|
||||
bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
bool Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
bool Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
|
||||
void replaceInEdge(BB* where, BB* which, BB* with);
|
||||
void processExpPush(int &numHlIcodes, iICODE picode);
|
||||
|
||||
// TODO: replace those with friend visitor ?
|
||||
void propLongReg(int loc_ident_idx, const ID &pLocId);
|
||||
void propLongStk(int i, const ID &pLocId);
|
||||
void propLongGlb(int i, const ID &pLocId);
|
||||
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong);
|
||||
|
||||
int findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE iter);
|
||||
int findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg);
|
||||
void structCases();
|
||||
void findExps();
|
||||
void genDU1();
|
||||
void elimCondCodes();
|
||||
void liveRegAnalysis(std::bitset<32> &in_liveOut);
|
||||
void findIdioms();
|
||||
void propLong();
|
||||
void genLiveKtes();
|
||||
uint8_t findDerivedSeq (derSeq &derivedGi);
|
||||
bool nextOrderGraph(derSeq &derivedGi);
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "symtab.h"
|
||||
|
||||
struct STKFRAME : public SymbolTableCommon<STKSYM>
|
||||
{
|
||||
//std::vector<STKSYM> sym;
|
||||
//STKSYM * sym; /* Symbols */
|
||||
int16_t m_minOff; /* Initial offset in stack frame*/
|
||||
int16_t maxOff; /* Maximum offset in stack frame*/
|
||||
int cb; /* Number of bytes in arguments */
|
||||
int numArgs; /* No. of arguments in the table*/
|
||||
void adjustForArgType(int numArg_, hlType actType_);
|
||||
STKFRAME() : m_minOff(0),maxOff(0),cb(0),numArgs(0)
|
||||
{
|
||||
|
||||
}
|
||||
size_t getLocVar(int off);
|
||||
public:
|
||||
void updateFrameOff(int16_t off, int size, uint16_t duFlag);
|
||||
};
|
||||
272
include/ast.h
272
include/ast.h
@@ -4,12 +4,9 @@
|
||||
* Date: September 1993
|
||||
* (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
|
||||
{};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
361
include/dcc.h
361
include/dcc.h
@@ -2,15 +2,8 @@
|
||||
* dcc project general header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
//TODO: Remove boolT
|
||||
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "icode.h"
|
||||
@@ -18,31 +11,134 @@
|
||||
#include "error.h"
|
||||
#include "graph.h"
|
||||
#include "bundle.h"
|
||||
#include "Procedure.h"
|
||||
#include "BasicBlock.h"
|
||||
struct Project;
|
||||
|
||||
|
||||
/* SYMBOL TABLE */
|
||||
typedef struct {
|
||||
char name[10]; /* New name for this variable */
|
||||
dword label; /* physical address (20 bit) */
|
||||
Int size; /* maximum size */
|
||||
flags32 flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
hlType type; /* probable type */
|
||||
word duVal; /* DEF, USE, VAL */
|
||||
} SYM;
|
||||
typedef SYM *PSYM;
|
||||
|
||||
typedef struct {
|
||||
Int csym; /* No. of symbols in table */
|
||||
Int alloc; /* Allocation */
|
||||
PSYM sym; /* Symbols */
|
||||
} SYMTAB;
|
||||
typedef SYMTAB *PSYMTAB;
|
||||
|
||||
|
||||
/* STACK FRAME */
|
||||
typedef struct {
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16 off; /* Immediate off from BP (+:args, -:params) */
|
||||
byte regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
Int size; /* Size */
|
||||
hlType type; /* Probable type */
|
||||
word duVal; /* DEF, USE, VAL */
|
||||
boolT hasMacro; /* This type needs a macro */
|
||||
char macro[10]; /* Macro name */
|
||||
char name[10]; /* Name for this symbol/argument */
|
||||
boolT invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
} STKSYM;
|
||||
typedef STKSYM *PSTKSYM;
|
||||
|
||||
typedef struct _STKFRAME {
|
||||
Int csym; /* No. of symbols in table */
|
||||
Int alloc; /* Allocation */
|
||||
PSTKSYM sym; /* Symbols */
|
||||
int16 minOff; /* Initial offset in stack frame*/
|
||||
int16 maxOff; /* Maximum offset in stack frame*/
|
||||
Int cb; /* Number of bytes in arguments */
|
||||
Int numArgs; /* No. of arguments in the table*/
|
||||
} STKFRAME;
|
||||
typedef STKFRAME *PSTKFRAME;
|
||||
|
||||
/* PROCEDURE NODE */
|
||||
typedef struct _proc {
|
||||
dword procEntry; /* label number */
|
||||
char name[SYMLEN]; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
Int depth; /* Depth at which we found it - for printing */
|
||||
flags32 flg; /* Combination of Icode & Proc flags */
|
||||
int16 cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
PBB cfg; /* Ptr. to BB list/CFG */
|
||||
PBB *dfsLast; /* Array of pointers to BBs in dfsLast
|
||||
* (reverse postorder) order */
|
||||
Int numBBs; /* Number of BBs in the graph cfg */
|
||||
boolT hasCase; /* Procedure has a case node */
|
||||
|
||||
/* For interprocedural live analysis */
|
||||
dword liveIn; /* Registers used before defined */
|
||||
dword liveOut; /* Registers that may be used in successors */
|
||||
boolT liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
/* Double-linked list */
|
||||
struct _proc *next;
|
||||
struct _proc *prev;
|
||||
} PROCEDURE;
|
||||
typedef PROCEDURE *PPROC;
|
||||
|
||||
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
ilFunction proc; /* Pointer to procedure in pProcList */
|
||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
||||
public:
|
||||
void write();
|
||||
CALL_GRAPH() : outEdges(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
void writeNodeCallGraph(int indIdx);
|
||||
bool insertCallGraph(ilFunction caller, ilFunction callee);
|
||||
bool insertCallGraph(Function *caller, ilFunction callee);
|
||||
void insertArc(ilFunction newProc);
|
||||
};
|
||||
//#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||
//extern std::list<Function> pProcList;
|
||||
//extern FunctionListType pProcList;
|
||||
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
typedef struct _callGraph {
|
||||
PPROC proc; /* Pointer to procedure in pProcList */
|
||||
Int numOutEdges; /* # of out edges (ie. # procs invoked) */
|
||||
Int numAlloc; /* # of out edges allocated */
|
||||
struct _callGraph **outEdges; /* array of out edges */
|
||||
} CALL_GRAPH;
|
||||
typedef CALL_GRAPH *PCALL_GRAPH;
|
||||
#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||
|
||||
extern PPROC pProcList; /* Pointer to the head of the procedure list */
|
||||
extern PPROC pLastProc; /* Pointer to last node of the proc list */
|
||||
extern PCALL_GRAPH callGraph; /* Pointer to the head of the call graph */
|
||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
|
||||
/* Procedure FLAGS */
|
||||
#define PROC_BADINST 0x000100 /* Proc contains invalid or 386 instruction */
|
||||
#define PROC_IJMP 0x000200 /* Proc incomplete due to indirect jmp */
|
||||
#define PROC_ICALL 0x000400 /* Proc incomplete due to indirect call */
|
||||
#define PROC_HLL 0x001000 /* Proc is likely to be from a HLL */
|
||||
#define CALL_PASCAL 0x002000 /* Proc uses Pascal calling convention */
|
||||
#define CALL_C 0x004000 /* Proc uses C calling convention */
|
||||
#define CALL_UNKNOWN 0x008000 /* Proc uses unknown calling convention */
|
||||
#define PROC_NEAR 0x010000 /* Proc exits with near return */
|
||||
#define PROC_FAR 0x020000 /* Proc exits with far return */
|
||||
#define GRAPH_IRRED 0x100000 /* Proc generates an irreducible graph */
|
||||
#define SI_REGVAR 0x200000 /* SI is used as a stack variable */
|
||||
#define DI_REGVAR 0x400000 /* DI is used as a stack variable */
|
||||
#define PROC_IS_FUNC 0x800000 /* Proc is a function */
|
||||
#define REG_ARGS 0x1000000 /* Proc has registers as arguments */
|
||||
#define PROC_VARARG 0x2000000 /* Proc has variable arguments */
|
||||
#define PROC_OUTPUT 0x4000000 /* C for this proc has been output */
|
||||
#define PROC_RUNTIME 0x8000000 /* Proc is part of the runtime support */
|
||||
#define PROC_ISLIB 0x10000000 /* Proc is a library function */
|
||||
#define PROC_ASM 0x20000000 /* Proc is an intrinsic assembler routine */
|
||||
#define PROC_IS_HLL 0x40000000 /* Proc has HLL prolog code */
|
||||
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
|
||||
/* duVal FLAGS */
|
||||
#define DEF 0x0010 /* Variable was first defined than used */
|
||||
#define USE 0x0100 /* Variable was first used than defined */
|
||||
#define VAL 0x1000 /* Variable has an initial value. 2 cases:
|
||||
* 1. When variable is used first (ie. global)
|
||||
* 2. When a value is moved into the variable
|
||||
* for the first time. */
|
||||
#define USEVAL 0x1100 /* Use and Val */
|
||||
|
||||
|
||||
/**** Global variables ****/
|
||||
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
@@ -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 */
|
||||
Int newByteWordRegId (LOCAL_ID *, hlType t, byte regi);
|
||||
Int newByteWordStkId (LOCAL_ID *, hlType t, Int off, byte regOff);
|
||||
Int newIntIdxId (LOCAL_ID *, int16 seg, int16 off, byte regi, Int, hlType);
|
||||
Int newLongRegId (LOCAL_ID *, hlType t, byte regH, byte regL, Int idx);
|
||||
Int newLongStkId (LOCAL_ID *, hlType t, Int offH, Int offL);
|
||||
Int newLongId (LOCAL_ID *, opLoc sd, PICODE, hlFirst, Int idx, operDu, Int);
|
||||
boolT checkLongEq (LONG_STKID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **,
|
||||
COND_EXPR **, Int);
|
||||
boolT checkLongRegEq (LONGID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **,
|
||||
COND_EXPR **, Int);
|
||||
byte otherLongRegi (byte, Int, LOCAL_ID *);
|
||||
void insertIdx (IDX_ARRAY *, Int);
|
||||
void propLongId (LOCAL_ID *, byte, byte, char *);
|
||||
|
||||
|
||||
/* Exported funcions from locident.c */
|
||||
boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
|
||||
boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
|
||||
eReg otherLongRegi(eReg, int, LOCAL_ID *);
|
||||
|
||||
|
||||
extern const char *indentStr(int level);
|
||||
|
||||
@@ -2,32 +2,7 @@
|
||||
* dcc project disassembler header
|
||||
* (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 */
|
||||
@@ -44,10 +19,10 @@ public:
|
||||
#ifdef _CONSOLE
|
||||
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
|
||||
#define KEY_LEFT 0x4B
|
||||
#define KEY_UP 0x48
|
||||
#define KEY_RIGHT 0x4D
|
||||
#define KEY_NPAGE 0x51
|
||||
#define KEY_PPAGE 0x49
|
||||
#define KEY_UP 0x48
|
||||
#define KEY_RIGHT 0x4D
|
||||
#define KEY_NPAGE 0x51
|
||||
#define KEY_PPAGE 0x49
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX__
|
||||
|
||||
@@ -5,34 +5,34 @@
|
||||
**************************************************************************/
|
||||
|
||||
/* Type definitions for intel 80x86 architecture */
|
||||
typedef unsigned int uint16_t; /* 16 bits */
|
||||
typedef unsigned char uint8_t; /* 8 bits */
|
||||
typedef unsigned int Word; /* 16 bits */
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
typedef union {
|
||||
unsigned long dW;
|
||||
uint16_t wL, wH; /* 2 words */
|
||||
Word wL, wH; /* 2 words */
|
||||
} Dword; /* 32 bits */
|
||||
|
||||
/* Structure to access high and low bits of a uint8_t or uint16_t variable */
|
||||
/* Structure to access high and low bits of a Byte or Word variable */
|
||||
typedef struct {
|
||||
/* low uint8_t */
|
||||
uint16_t lowBitWord : 1;
|
||||
uint16_t filler1 : 6;
|
||||
uint16_t highBitByte : 1;
|
||||
/* high uint8_t */
|
||||
uint16_t lowBitByte : 1;
|
||||
uint16_t filler2 : 6;
|
||||
uint16_t highBitWord : 1;
|
||||
/* low byte */
|
||||
Word lowBitWord : 1;
|
||||
Word filler1 : 6;
|
||||
Word highBitByte : 1;
|
||||
/* high byte */
|
||||
Word lowBitByte : 1;
|
||||
Word filler2 : 6;
|
||||
Word highBitWord : 1;
|
||||
} wordBits;
|
||||
|
||||
/* Low and high bits of a uint8_t or uint16_t variable */
|
||||
/* Low and high bits of a Byte or Word variable */
|
||||
#define lowBit(a) ((wordBits)(a).lowBitWord)
|
||||
#define highBitByte(a) ((wordBits)(a).highBitByte)
|
||||
#define lowBitByte(a) ((wordBits)(a).lowBitByte)
|
||||
#define highBit(a) (sizeof(a) == sizeof(uint16_t) ? \
|
||||
#define highBit(a) (sizeof(a) == sizeof(Word) ? \
|
||||
((wordBits)(a).highBitWord):\
|
||||
((wordBits)(a).highBitByte))
|
||||
|
||||
/* uint16_t register variables */
|
||||
/* Word register variables */
|
||||
#define ax regs.x.ax
|
||||
#define bx regs.x.bx
|
||||
#define cx regs.x.cx
|
||||
@@ -52,7 +52,7 @@ typedef struct {
|
||||
#define carry regs.x.cflags
|
||||
#define overF regs.x.flags /***** check *****/
|
||||
|
||||
/* uint8_t register variables */
|
||||
/* Byte register variables */
|
||||
#define ah regs.h.ah
|
||||
#define al regs.h.al
|
||||
#define bh regs.h.bh
|
||||
@@ -64,8 +64,8 @@ typedef struct {
|
||||
|
||||
|
||||
/* High and low words of a Dword */
|
||||
#define highWord(w) (*((uint16_t*)&(w) + 1))
|
||||
#define lowWord(w) ((uint16_t)(w))
|
||||
#define highWord(w) (*((Word*)&(w) + 1))
|
||||
#define lowWord(w) ((Word)(w))
|
||||
|
||||
#define MAXByte 0xFF
|
||||
#define MAXWord 0xFFFF
|
||||
@@ -74,4 +74,7 @@ typedef struct {
|
||||
#define MAXSignWord 0x7FFF
|
||||
#define MINSignWord 0x8001
|
||||
|
||||
/* Booleans */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
|
||||
@@ -2,35 +2,32 @@
|
||||
* Error codes
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
|
||||
/* These definitions refer to errorMessage in error.c */
|
||||
enum eErrorId
|
||||
{
|
||||
NO_ERR =0,
|
||||
USAGE,
|
||||
INVALID_ARG,
|
||||
INVALID_OPCODE,
|
||||
INVALID_386OP,
|
||||
FUNNY_SEGOVR,
|
||||
FUNNY_REP,
|
||||
CANNOT_OPEN,
|
||||
CANNOT_READ,
|
||||
MALLOC_FAILED,
|
||||
NEWEXE_FORMAT,
|
||||
|
||||
NO_BB,
|
||||
INVALID_SYNTHETIC_BB,
|
||||
INVALID_INT_BB,
|
||||
IP_OUT_OF_RANGE,
|
||||
DEF_NOT_FOUND,
|
||||
JX_NOT_DEF,
|
||||
NOT_DEF_USE,
|
||||
REPEAT_FAIL,
|
||||
WHILE_FAIL
|
||||
};
|
||||
#define USAGE 0
|
||||
#define INVALID_ARG 1
|
||||
#define INVALID_OPCODE 2
|
||||
#define INVALID_386OP 3
|
||||
#define FUNNY_SEGOVR 4
|
||||
#define FUNNY_REP 5
|
||||
#define CANNOT_OPEN 6
|
||||
#define CANNOT_READ 7
|
||||
#define MALLOC_FAILED 8
|
||||
#define NEWEXE_FORMAT 9
|
||||
|
||||
#define NO_BB 10
|
||||
#define INVALID_SYNTHETIC_BB 11
|
||||
#define INVALID_INT_BB 12
|
||||
#define IP_OUT_OF_RANGE 13
|
||||
#define DEF_NOT_FOUND 14
|
||||
#define JX_NOT_DEF 15
|
||||
#define NOT_DEF_USE 16
|
||||
#define REPEAT_FAIL 17
|
||||
#define WHILE_FAIL 18
|
||||
|
||||
|
||||
void fatalError(eErrorId errId, ...);
|
||||
void reportError(eErrorId errId, ...);
|
||||
void fatalError(Int errId, ...);
|
||||
void reportError(Int errId, ...);
|
||||
|
||||
|
||||
173
include/graph.h
173
include/graph.h
@@ -2,49 +2,37 @@
|
||||
* CFG, BB and interval related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
struct Function;
|
||||
|
||||
|
||||
/* Types of basic block nodes */
|
||||
/* Real basic blocks: type defined according to their out-edges */
|
||||
enum eBBKind
|
||||
{
|
||||
ONE_BRANCH = 0, /* unconditional branch */
|
||||
TWO_BRANCH = 1, /* conditional branch */
|
||||
MULTI_BRANCH=2, /* case branch */
|
||||
FALL_NODE=3, /* fall through */
|
||||
RETURN_NODE=4, /* procedure/program return */
|
||||
CALL_NODE=5, /* procedure call */
|
||||
LOOP_NODE=6, /* loop instruction */
|
||||
REP_NODE=7, /* repeat instruction */
|
||||
INTERVAL_NODE=8, /* contains interval list */
|
||||
#define ONE_BRANCH 0 /* unconditional branch */
|
||||
#define TWO_BRANCH 1 /* conditional branch */
|
||||
#define MULTI_BRANCH 2 /* case branch */
|
||||
#define FALL_NODE 3 /* fall through */
|
||||
#define RETURN_NODE 4 /* procedure/program return */
|
||||
#define CALL_NODE 5 /* procedure call */
|
||||
#define LOOP_NODE 6 /* loop instruction */
|
||||
#define REP_NODE 7 /* repeat instruction */
|
||||
#define INTERVAL_NODE 8 /* contains interval list */
|
||||
|
||||
TERMINATE_NODE=11, /* Exit to DOS */
|
||||
NOWHERE_NODE=12 /* No outedges going anywhere */
|
||||
};
|
||||
#define TERMINATE_NODE 11 /* Exit to DOS */
|
||||
#define NOWHERE_NODE 12 /* No outedges going anywhere */
|
||||
|
||||
|
||||
/* Depth-first traversal constants */
|
||||
enum eDFS
|
||||
{
|
||||
DFS_NONE,
|
||||
DFS_DISP=1, /* Display graph pass */
|
||||
DFS_MERGE=2, /* Merge nodes pass */
|
||||
DFS_NUM=3, /* DFS numbering pass */
|
||||
DFS_CASE=4, /* Case pass */
|
||||
DFS_ALPHA=5, /* Alpha code generation*/
|
||||
DFS_JMP=9 /* rmJMP pass - must be largest flag */
|
||||
};
|
||||
#define DFS_DISP 1 /* Display graph pass */
|
||||
#define DFS_MERGE 2 /* Merge nodes pass */
|
||||
#define DFS_NUM 3 /* DFS numbering pass */
|
||||
#define DFS_CASE 4 /* Case pass */
|
||||
#define DFS_ALPHA 5 /* Alpha code generation*/
|
||||
#define DFS_JMP 9 /* rmJMP pass - must be largest flag */
|
||||
|
||||
/* Control flow analysis constants */
|
||||
enum eNodeHeaderType
|
||||
{
|
||||
NO_TYPE=0, /* node is not a loop header*/
|
||||
WHILE_TYPE=1, /* node is a while header */
|
||||
REPEAT_TYPE=2, /* node is a repeat header */
|
||||
ENDLESS_TYPE=3 /* endless loop header */
|
||||
};
|
||||
#define NO_TYPE 0 /* node is not a loop header*/
|
||||
#define WHILE_TYPE 1 /* node is a while header */
|
||||
#define REPEAT_TYPE 2 /* node is a repeat header */
|
||||
#define ENDLESS_TYPE 3 /* endless loop header */
|
||||
|
||||
/* Uninitialized values for certain fields */
|
||||
#define NO_NODE MAX /* node has no associated node */
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* File: hlIcode.h
|
||||
* Purpose: module definitions for high-level icodes
|
||||
* Date: September 1993
|
||||
@@ -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;
|
||||
|
||||
|
||||
808
include/icode.h
808
include/icode.h
@@ -2,489 +2,367 @@
|
||||
* I-code related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <bitset>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <llvm/CodeGen/MachineInstr.h>
|
||||
#include <llvm/MC/MCInst.h>
|
||||
#include <llvm/MC/MCAsmInfo.h>
|
||||
#include <llvm/Value.h>
|
||||
#include <llvm/Instruction.h>
|
||||
#include <boost/range.hpp>
|
||||
#include "libdis.h"
|
||||
#include "Enums.h"
|
||||
|
||||
|
||||
/* LOW_LEVEL icode flags */
|
||||
#define B 0x000001 /* Byte operands (value implicitly used) */
|
||||
#define I 0x000002 /* Immed. source */
|
||||
#define NOT_HLL 0x000004 /* Not HLL inst. */
|
||||
#define FLOAT_OP 0x000008 /* ESC or WAIT */
|
||||
|
||||
#define SEG_IMMED 0x000010 /* Number is relocated segment value */
|
||||
#define IMPURE 0x000020 /* Instruction modifies code */
|
||||
#define WORD_OFF 0x000040 /* Inst has word offset ie.could be address */
|
||||
#define TERMINATES 0x000080 /* Instruction terminates program */
|
||||
|
||||
#define CASE 0x000100 /* Label as case part of switch */
|
||||
#define SWITCH 0x000200 /* Treat indirect JMP as switch stmt */
|
||||
#define TARGET 0x000400 /* Jump target */
|
||||
#define SYNTHETIC 0x000800 /* Synthetic jump instruction */
|
||||
#define NO_LABEL 0x001000 /* Immed. jump cannot be linked to a label */
|
||||
#define NO_CODE 0x002000 /* Hole in Icode array */
|
||||
#define SYM_USE 0x004000 /* Instruction uses a symbol */
|
||||
#define SYM_DEF 0x008000 /* Instruction defines a symbol */
|
||||
|
||||
#define NO_SRC 0x010000 /* Opcode takes no source */
|
||||
#define NO_OPS 0x020000 /* Opcode takes no operands */
|
||||
#define IM_OPS 0x040000 /* Opcode takes implicit operands */
|
||||
#define SRC_B 0x080000 /* Source operand is byte (dest is word) */
|
||||
#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */
|
||||
#define HLL_LABEL 0x100000 /* Icode has a high level language label */
|
||||
#define IM_DST 0x200000 /* Implicit DST for opcode (SIGNEX) */
|
||||
#define IM_SRC 0x400000 /* Implicit SRC for opcode (dx:ax) */
|
||||
#define IM_TMP_DST 0x800000 /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
|
||||
#define JMP_ICODE 0x1000000 /* Jmp dest immed.op converted to icode index */
|
||||
#define JX_LOOP 0x2000000 /* Cond jump is part of loop conditional exp */
|
||||
#define REST_STK 0x4000000 /* Stack needs to be restored after CALL */
|
||||
|
||||
/* Parser flags */
|
||||
#define TO_REG 0x000100 /* rm is source */
|
||||
#define S 0x000200 /* sign extend */
|
||||
#define OP386 0x000400 /* 386 op-code */
|
||||
#define NSP 0x000800 /* NOT_HLL if SP is src or dst */
|
||||
#define ICODEMASK 0xFF00FF /* Masks off parser flags */
|
||||
|
||||
/* LOW_LEVEL icode, DU flag bits */
|
||||
#define Cf 1
|
||||
#define Sf 2
|
||||
#define Zf 4
|
||||
#define Df 8
|
||||
|
||||
/* Machine registers */
|
||||
#define rAX 1 /* These are numbered relative to real 8086 */
|
||||
#define rCX 2
|
||||
#define rDX 3
|
||||
#define rBX 4
|
||||
#define rSP 5
|
||||
#define rBP 6
|
||||
#define rSI 7
|
||||
#define rDI 8
|
||||
|
||||
#define rES 9
|
||||
#define rCS 10
|
||||
#define rSS 11
|
||||
#define rDS 12
|
||||
|
||||
#define rAL 13
|
||||
#define rCL 14
|
||||
#define rDL 15
|
||||
#define rBL 16
|
||||
#define rAH 17
|
||||
#define rCH 18
|
||||
#define rDH 19
|
||||
#define rBH 20
|
||||
|
||||
#define rTMP 21 /* temp register for DIV/IDIV/MOD */
|
||||
#define INDEXBASE 22 /* Indexed modes go from INDEXBASE to
|
||||
* INDEXBASE+7 */
|
||||
|
||||
/* Byte and Word registers */
|
||||
static char *byteReg[9] = {"al", "cl", "dl", "bl",
|
||||
"ah", "ch", "dh", "bh", "tmp" };
|
||||
static char *wordReg[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
|
||||
"si", "di", "es", "cs", "ss", "ds",
|
||||
"", "", "", "", "", "", "", "", "tmp"};
|
||||
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
|
||||
//enum condId;
|
||||
/* Types of icodes */
|
||||
typedef enum {
|
||||
NOT_SCANNED = 0, /* not even scanned yet */
|
||||
LOW_LEVEL, /* low-level icode */
|
||||
HIGH_LEVEL /* high-level icode */
|
||||
} icodeType;
|
||||
|
||||
struct LOCAL_ID;
|
||||
struct BB;
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct CIcodeRec;
|
||||
struct ICODE;
|
||||
struct bundle;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
typedef std::list<ICODE>::reverse_iterator riICODE;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
extern std::bitset<32> duReg[30];
|
||||
/* uint8_t and uint16_t registers */
|
||||
|
||||
/* LOW_LEVEL icode opcodes */
|
||||
typedef enum {
|
||||
iCBW, /* 0 */
|
||||
iAAA,
|
||||
iAAD,
|
||||
iAAM,
|
||||
iAAS,
|
||||
iADC,
|
||||
iADD,
|
||||
iAND,
|
||||
iBOUND,
|
||||
iCALL,
|
||||
iCALLF, /* 10 */
|
||||
iCLC,
|
||||
iCLD,
|
||||
iCLI,
|
||||
iCMC,
|
||||
iCMP,
|
||||
iCMPS,
|
||||
iREPNE_CMPS,
|
||||
iREPE_CMPS,
|
||||
iDAA,
|
||||
iDAS, /* 20 */
|
||||
iDEC,
|
||||
iDIV,
|
||||
iENTER,
|
||||
iESC,
|
||||
iHLT,
|
||||
iIDIV,
|
||||
iIMUL,
|
||||
iIN,
|
||||
iINC,
|
||||
iINS, /* 30 */
|
||||
iREP_INS,
|
||||
iINT,
|
||||
iIRET,
|
||||
iJB,
|
||||
iJBE,
|
||||
iJAE,
|
||||
iJA,
|
||||
iJE,
|
||||
iJNE,
|
||||
iJL, /* 40 */
|
||||
iJGE,
|
||||
iJLE,
|
||||
iJG,
|
||||
iJS,
|
||||
iJNS,
|
||||
iJO,
|
||||
iJNO,
|
||||
iJP,
|
||||
iJNP,
|
||||
iJCXZ, /* 50 */
|
||||
iJMP,
|
||||
iJMPF,
|
||||
iLAHF,
|
||||
iLDS,
|
||||
iLEA,
|
||||
iLEAVE,
|
||||
iLES,
|
||||
iLOCK,
|
||||
iLODS,
|
||||
iREP_LODS, /* 60 */
|
||||
iLOOP,
|
||||
iLOOPE,
|
||||
iLOOPNE,
|
||||
iMOV, /* 64 */
|
||||
iMOVS,
|
||||
iREP_MOVS,
|
||||
iMUL, /* 67 */
|
||||
iNEG,
|
||||
iNOT,
|
||||
iOR, /* 70 */
|
||||
iOUT,
|
||||
iOUTS,
|
||||
iREP_OUTS,
|
||||
iPOP,
|
||||
iPOPA,
|
||||
iPOPF,
|
||||
iPUSH,
|
||||
iPUSHA,
|
||||
iPUSHF,
|
||||
iRCL, /* 80 */
|
||||
iRCR,
|
||||
iROL,
|
||||
iROR,
|
||||
iRET, /* 84 */
|
||||
iRETF,
|
||||
iSAHF,
|
||||
iSAR,
|
||||
iSHL,
|
||||
iSHR,
|
||||
iSBB, /* 90 */
|
||||
iSCAS,
|
||||
iREPNE_SCAS,
|
||||
iREPE_SCAS,
|
||||
iSIGNEX,
|
||||
iSTC,
|
||||
iSTD,
|
||||
iSTI,
|
||||
iSTOS,
|
||||
iREP_STOS,
|
||||
iSUB, /* 100 */
|
||||
iTEST,
|
||||
iWAIT,
|
||||
iXCHG,
|
||||
iXLAT,
|
||||
iXOR,
|
||||
iINTO,
|
||||
iNOP,
|
||||
iREPNE,
|
||||
iREPE,
|
||||
iMOD, /* 110 */
|
||||
} llIcode;
|
||||
|
||||
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
typedef enum {
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
HLI_RET, /* Return from procedure */
|
||||
/* pseudo high-level icodes */
|
||||
HLI_POP, /* Pop expression */
|
||||
HLI_PUSH, /* Push expression */
|
||||
} hlIcode;
|
||||
|
||||
|
||||
/* Operand is defined, used or both flag */
|
||||
typedef enum {
|
||||
DEF, /* Operand is defined */
|
||||
USE, /* Operand is used */
|
||||
USE_DEF, /* Operand is used and defined */
|
||||
NONE, /* No operation is required on this operand */
|
||||
} operDu;
|
||||
|
||||
// I can't believe these are necessary!
|
||||
#define E_DEF (operDu)DEF
|
||||
#define E_USE (operDu)USE
|
||||
#define E_NONE (operDu)NONE
|
||||
#define E_USE_DEF (operDu)USE_DEF
|
||||
|
||||
/* Def/use of flags - low 4 bits represent flags */
|
||||
struct DU
|
||||
{
|
||||
uint8_t d;
|
||||
uint8_t u;
|
||||
};
|
||||
typedef struct {
|
||||
byte d;
|
||||
byte u;
|
||||
} DU;
|
||||
typedef DU *PDU;
|
||||
|
||||
/* Def/Use of registers and stack variables */
|
||||
typedef struct {
|
||||
dword def; /* For Registers: position in dword is reg index*/
|
||||
dword lastDefRegi;/* Bit set if last def of this register in BB */
|
||||
dword use; /* For Registers: position in dword is reg index*/
|
||||
}DU_ICODE;
|
||||
|
||||
|
||||
/* Definition-use chain for level 1 (within a basic block) */
|
||||
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
|
||||
#define MAX_REGS_DEF 2 /* 2 regs def'd for long-reg vars */
|
||||
#define MAX_USES 5
|
||||
|
||||
typedef struct {
|
||||
Int numRegsDef; /* # registers defined by this inst */
|
||||
byte regi[MAX_REGS_DEF]; /* registers defined by this inst */
|
||||
Int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
|
||||
} DU1;
|
||||
|
||||
|
||||
struct COND_EXPR;
|
||||
struct HlTypeSupport
|
||||
{
|
||||
//hlIcode opcode; /* hlIcode opcode */
|
||||
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
|
||||
virtual std::string writeOut(Function *pProc, int *numLoc)=0;
|
||||
protected:
|
||||
void performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree);
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom5 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom5() {}
|
||||
Idiom5(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom6 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom6() {}
|
||||
Idiom6(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom18 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[4];
|
||||
bool m_is_dec;
|
||||
public:
|
||||
Idiom18(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 4;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom19 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
bool m_is_dec;
|
||||
public:
|
||||
Idiom19(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom20 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[4];
|
||||
bool m_is_dec;
|
||||
public:
|
||||
Idiom20(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 4;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
struct CallIdiom : public Idiom
|
||||
{
|
||||
protected:
|
||||
int m_param_count;
|
||||
public:
|
||||
virtual ~CallIdiom() {}
|
||||
CallIdiom(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
struct Idiom3 : public CallIdiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom3() {}
|
||||
Idiom3(Function *f) : CallIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom17 : public CallIdiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
public:
|
||||
virtual ~Idiom17() {}
|
||||
Idiom17(Function *f) : CallIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
struct EpilogIdiom : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::deque<iICODE> m_icodes; // deque to push_front optional icodes from popStkVars
|
||||
void popStkVars (iICODE pIcode);
|
||||
public:
|
||||
virtual ~EpilogIdiom() {}
|
||||
EpilogIdiom(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
struct Idiom2 : public EpilogIdiom
|
||||
{
|
||||
virtual ~Idiom2() {}
|
||||
Idiom2(Function *f) : EpilogIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom4 : public EpilogIdiom
|
||||
{
|
||||
protected:
|
||||
int m_param_count;
|
||||
public:
|
||||
virtual ~Idiom4() {}
|
||||
Idiom4(Function *f) : EpilogIdiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
#include "icode.h"
|
||||
#include "Procedure.h"
|
||||
struct Idiom
|
||||
{
|
||||
protected:
|
||||
Function *m_func;
|
||||
iICODE m_end;
|
||||
public:
|
||||
Idiom(Function *f) : m_func(f),m_end(f->Icode.end())
|
||||
{
|
||||
}
|
||||
virtual uint8_t minimum_match_length()=0;
|
||||
virtual bool match(iICODE at)=0;
|
||||
virtual int action()=0;
|
||||
int operator ()(iICODE at)
|
||||
{
|
||||
if(match(at))
|
||||
return action();
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "idiom.h"
|
||||
struct Idiom1 : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
int m_min_off;
|
||||
int checkStkVars (iICODE pIcode);
|
||||
public:
|
||||
Idiom1(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE picode);
|
||||
int action();
|
||||
size_t match_length() {return m_icodes.size();}
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom14 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
eReg m_regL;
|
||||
eReg m_regH;
|
||||
public:
|
||||
virtual ~Idiom14() {}
|
||||
Idiom14(Function *f) : Idiom(f),m_regL(rUNDEF),m_regH(rUNDEF)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom13 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
eReg m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom13() {}
|
||||
Idiom13(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom11 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[3];
|
||||
public:
|
||||
virtual ~Idiom11() {}
|
||||
Idiom11(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom16 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[3];
|
||||
public:
|
||||
virtual ~Idiom16() {}
|
||||
Idiom16(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 3;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom8 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
uint8_t m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom8() {}
|
||||
Idiom8(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom15 : public Idiom
|
||||
{
|
||||
protected:
|
||||
std::vector<iICODE> m_icodes;
|
||||
public:
|
||||
virtual ~Idiom15() {}
|
||||
Idiom15(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom12 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
uint8_t m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom12() {}
|
||||
Idiom12(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
|
||||
struct Idiom9 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
uint8_t m_loaded_reg;
|
||||
public:
|
||||
virtual ~Idiom9() {}
|
||||
Idiom9(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "idiom.h"
|
||||
#include "icode.h"
|
||||
#include <deque>
|
||||
|
||||
struct Idiom21 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom21() {}
|
||||
Idiom21(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 2;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
|
||||
struct Idiom7 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icode;
|
||||
public:
|
||||
virtual ~Idiom7() {}
|
||||
Idiom7(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
struct Idiom10 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[2];
|
||||
public:
|
||||
virtual ~Idiom10() {}
|
||||
Idiom10(Function *f) : Idiom(f)
|
||||
{
|
||||
}
|
||||
uint8_t minimum_match_length() {return 1;}
|
||||
bool match(iICODE pIcode);
|
||||
int action();
|
||||
};
|
||||
@@ -5,134 +5,106 @@
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* Type definition */
|
||||
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
|
||||
// TODO: why ?
|
||||
struct COND_EXPR;
|
||||
struct ICODE;
|
||||
struct LLInst;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
struct IDX_ARRAY : public std::vector<iICODE>
|
||||
{
|
||||
bool inList(iICODE idx)
|
||||
{
|
||||
return std::find(begin(),end(),idx)!=end();
|
||||
}
|
||||
};
|
||||
typedef struct {
|
||||
Int csym; /* # symbols used */
|
||||
Int alloc; /* # symbols allocated */
|
||||
Int *idx; /* Array of integer indexes */
|
||||
} IDX_ARRAY;
|
||||
|
||||
/* Type definitions used in the decompiled program */
|
||||
typedef enum {
|
||||
TYPE_UNKNOWN = 0, /* unknown so far */
|
||||
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
|
||||
TYPE_BYTE_UNSIGN, /* unsigned byte */
|
||||
TYPE_WORD_SIGN, /* signed word (16 bits) */
|
||||
TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */
|
||||
TYPE_LONG_SIGN, /* signed long (32 bits) */
|
||||
TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */
|
||||
TYPE_RECORD, /* record structure */
|
||||
TYPE_PTR, /* pointer (32 bit ptr) */
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE, /* double precision float */
|
||||
} hlType;
|
||||
|
||||
static char *hlTypes[13] = {"", "char", "unsigned char", "int", "unsigned int",
|
||||
"long", "unsigned long", "record", "int *", "char *",
|
||||
"", "float", "double"};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STK_FRAME, /* For stack vars */
|
||||
REG_FRAME, /* For register variables */
|
||||
GLB_FRAME /* For globals */
|
||||
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;
|
||||
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
/* Machine registers */
|
||||
enum eReg
|
||||
{
|
||||
rUNDEF = 0,
|
||||
rAX = 1, /* These are numbered relative to real 8086 */
|
||||
rCX = 2,
|
||||
rDX = 3,
|
||||
rBX = 4,
|
||||
rSP = 5,
|
||||
rBP = 6,
|
||||
rSI = 7,
|
||||
rDI = 8,
|
||||
|
||||
rES = 9,
|
||||
rCS = 10,
|
||||
rSS = 11,
|
||||
rDS = 12,
|
||||
|
||||
rAL = 13,
|
||||
rCL = 14,
|
||||
rDL = 15,
|
||||
rBL = 16,
|
||||
rAH = 17,
|
||||
rCH = 18,
|
||||
rDH = 19,
|
||||
rBH = 20,
|
||||
|
||||
rTMP= 21, /* temp register for DIV/IDIV/MOD */
|
||||
/* Indexed modes go from INDEXBASE to INDEXBASE+7 */
|
||||
INDEX_BX_SI = 22, // "bx+si"
|
||||
INDEX_BX_DI, // "bx+di"
|
||||
INDEX_BP_SI, // "bp+si"
|
||||
INDEX_BP_DI, // "bp+di"
|
||||
INDEX_SI, // "si"
|
||||
INDEX_DI, // "di"
|
||||
INDEX_BP, // "bp"
|
||||
INDEX_BX, // "bx"
|
||||
LAST_REG
|
||||
};
|
||||
class SourceMachine
|
||||
{
|
||||
public:
|
||||
virtual bool physicalReg(eReg r)=0;
|
||||
|
||||
};
|
||||
//class Machine_X86_Disassembler
|
||||
//{
|
||||
// void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm);
|
||||
//};
|
||||
class Machine_X86 : public SourceMachine
|
||||
{
|
||||
public:
|
||||
Machine_X86();
|
||||
virtual ~Machine_X86() {}
|
||||
static const std::string ®Name(eReg r);
|
||||
static const std::string &opcodeName(unsigned r);
|
||||
static const std::string &floatOpName(unsigned r);
|
||||
bool physicalReg(eReg r);
|
||||
/* Writes the registers that are set in the bitvector */
|
||||
//TODO: move this into Machine_X86 ?
|
||||
static void writeRegVector (std::ostream &ostr,const std::bitset<32> ®i)
|
||||
{
|
||||
int j;
|
||||
for (j = rAX; j < INDEX_BX_SI; j++)
|
||||
{
|
||||
if (regi.test(j-1))
|
||||
ostr << regName(eReg(j))<<" ";
|
||||
}
|
||||
}
|
||||
static eReg subRegH(eReg reg); //TODO: move these into machine_x86
|
||||
static eReg subRegL(eReg reg);
|
||||
|
||||
static bool isMemOff(eReg r);
|
||||
static bool isSubRegisterOf(eReg reg, eReg parent);
|
||||
|
||||
};
|
||||
@@ -1,41 +1,34 @@
|
||||
#pragma once
|
||||
/* Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
//#define bool unsigned char
|
||||
#define uint8_t unsigned char
|
||||
#define uint16_t unsigned short
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define bool unsigned char
|
||||
#define byte unsigned char
|
||||
#define word unsigned short
|
||||
|
||||
/* Prototypes */
|
||||
void hashParams(int NumEntry, int EntryLen, int SetSize, char SetMin,
|
||||
int NumVert); /* Set the parameters for the hash table */
|
||||
void hashCleanup(void); /* Frees memory allocated by hashParams() */
|
||||
void map(void); /* Part 1 of creating the tables */
|
||||
void assign(void); /* Part 2 of creating the tables */
|
||||
int hash(byte *s); /* Hash the string to an int 0 .. NUMENTRY-1 */
|
||||
|
||||
word *readT1(void); /* Returns a pointer to the T1 table */
|
||||
word *readT2(void); /* Returns a pointer to the T2 table */
|
||||
word *readG(void); /* Returns a pointer to the g table */
|
||||
|
||||
|
||||
/* The application must provide these functions: */
|
||||
void getKey(int i, uint8_t **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void getKey(int i, byte **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void dispKey(int i); /* Display the key */
|
||||
class PatternHasher
|
||||
{
|
||||
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
int *graphNode; /* The array of edges */
|
||||
int *graphNext; /* Linked list of edges */
|
||||
int *graphFirst;/* First edge at a vertex */
|
||||
public:
|
||||
uint16_t *readT1(void); /* Returns a pointer to the T1 table */
|
||||
uint16_t *readT2(void); /* Returns a pointer to the T2 table */
|
||||
uint16_t *readG(void); /* Returns a pointer to the g table */
|
||||
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
|
||||
void cleanup();
|
||||
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
|
||||
};
|
||||
extern PatternHasher g_pattern_hasher;
|
||||
/* Macro reads a LH uint16_t from the image regardless of host convention */
|
||||
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
#ifndef LH
|
||||
#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
|
||||
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
|
||||
#endif
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include "symtab.h"
|
||||
#include "BinaryImage.h"
|
||||
struct Function;
|
||||
struct SourceMachine;
|
||||
struct CALL_GRAPH;
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
|
||||
struct Project
|
||||
{
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
|
||||
std::string m_fname;
|
||||
FunctionListType pProcList;
|
||||
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
Project() {}
|
||||
// no copies
|
||||
Project(const Project&) = delete;
|
||||
const Project &operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(Project && l)
|
||||
{
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
}
|
||||
Project &operator=(Project && l)
|
||||
{
|
||||
if(this == &l)
|
||||
return *this;
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
ilFunction funcIter(Function *to_find);
|
||||
ilFunction findByEntry(uint32_t entry);
|
||||
ilFunction createFunction();
|
||||
bool valid(ilFunction iter);
|
||||
|
||||
int getSymIdxByAdd(uint32_t adr);
|
||||
bool validSymIdx(size_t idx);
|
||||
size_t symbolSize(size_t idx);
|
||||
hlType symbolType(size_t idx);
|
||||
const std::string &symbolName(size_t idx);
|
||||
const SYM &getSymByIdx(size_t idx) const;
|
||||
|
||||
static Project *get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
|
||||
protected:
|
||||
void writeGlobSymTable();
|
||||
};
|
||||
//extern Project g_proj;
|
||||
@@ -1,12 +1,38 @@
|
||||
#pragma once
|
||||
/* Scanner functions
|
||||
* (C) Cristina Cifuentes, Jeff Ledermann
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
|
||||
#define REG(x) ((uint8_t)(x & 0x38) >> 3)
|
||||
|
||||
struct ICODE;
|
||||
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
|
||||
|
||||
extern eErrorId scan(uint32_t ip, ICODE &p);
|
||||
static void rm(Int i);
|
||||
static void modrm(Int i);
|
||||
static void segrm(Int i);
|
||||
static void data1(Int i);
|
||||
static void data2(Int i);
|
||||
static void regop(Int i);
|
||||
static void segop(Int i);
|
||||
static void strop(Int i);
|
||||
static void escop(Int i);
|
||||
static void axImp(Int i);
|
||||
static void alImp(Int i);
|
||||
static void axSrcIm(Int i);
|
||||
static void memImp(Int i);
|
||||
static void memReg0(Int i);
|
||||
static void memOnly(Int i);
|
||||
static void dispM(Int i);
|
||||
static void dispS(Int i);
|
||||
static void dispN(Int i);
|
||||
static void dispF(Int i);
|
||||
static void prefix(Int i);
|
||||
static void immed(Int i);
|
||||
static void shift(Int i);
|
||||
static void arith(Int i);
|
||||
static void trans(Int i);
|
||||
static void const1(Int i);
|
||||
static void const3(Int i);
|
||||
static void none1(Int i);
|
||||
static void none2(Int i);
|
||||
static void checkInt(Int i);
|
||||
|
||||
/* Extracts reg bits from middle of mod-reg-rm byte */
|
||||
#define REG(x) ((byte)(x & 0x38) >> 3)
|
||||
|
||||
@@ -2,34 +2,18 @@
|
||||
* dcc project header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* STATE TABLE */
|
||||
struct STATE
|
||||
typedef struct
|
||||
{
|
||||
uint32_t IP; /* Offset into Image */
|
||||
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
|
||||
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
|
||||
dword IP; /* Offset into Image */
|
||||
int16 r[INDEXBASE]; /* Value of segs and AX */
|
||||
byte f[INDEXBASE]; /* True if r[.] has a value */
|
||||
struct
|
||||
{ /* For case stmt indexed reg */
|
||||
uint8_t regi; /* Last conditional jump */
|
||||
int16_t immed; /* Contents of the previous register */
|
||||
{ /* 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;
|
||||
|
||||
|
||||
118
include/symtab.h
118
include/symtab.h
@@ -2,112 +2,42 @@
|
||||
* Symbol table prototypes
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
struct COND_EXPR;
|
||||
struct TypeContainer;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
/* Symbol table structs and protos */
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
struct SymbolCommon
|
||||
{
|
||||
std::string name; /* New name for this variable/symbol/argument */
|
||||
int size; /* Size/maximum size */
|
||||
hlType type; /* probable type */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
SymbolCommon() : size(0),type(TYPE_UNKNOWN)
|
||||
{}
|
||||
};
|
||||
struct SYM : public SymbolCommon
|
||||
{
|
||||
SYM() : label(0),flg(0)
|
||||
{
|
||||
|
||||
}
|
||||
int32_t label; /* physical address (20 bit) */
|
||||
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
};
|
||||
/* STACK FRAME */
|
||||
struct STKSYM : public SymbolCommon
|
||||
typedef struct
|
||||
{
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16_t label; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro; /* This type needs a macro */
|
||||
std::string macro; /* Macro name */
|
||||
bool invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
STKSYM()
|
||||
{
|
||||
actual=regs=0;
|
||||
label=0;
|
||||
regOff=0;
|
||||
invalid=hasMacro = false;
|
||||
}
|
||||
void setArgName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "arg%d", i);
|
||||
name = buf;
|
||||
}
|
||||
};
|
||||
template<class T>
|
||||
class SymbolTableCommon : public std::vector<T>
|
||||
{
|
||||
public:
|
||||
typedef typename std::vector<T>::iterator iterator;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
iterator findByLabel(int lab)
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
const_iterator findByLabel(int lab) const
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](const T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
char *pSymName; /* Ptr to symbolic name or comment */
|
||||
dword symOff; /* Symbol image offset */
|
||||
PPROC symProc; /* Procedure pointer */
|
||||
word preHash; /* Hash value before the modulo */
|
||||
word postHash; /* Hash value after the modulo */
|
||||
word nextOvf; /* Next entry this hash bucket, or -1 */
|
||||
word prevOvf; /* Back link in Ovf chain */
|
||||
} SYMTABLE;
|
||||
|
||||
};
|
||||
/* SYMBOL TABLE */
|
||||
class SYMTAB : public SymbolTableCommon<SYM>
|
||||
{
|
||||
|
||||
public:
|
||||
void updateSymType(uint32_t symbol, const TypeContainer &tc);
|
||||
SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new);
|
||||
};
|
||||
struct Function;
|
||||
struct SYMTABLE
|
||||
{
|
||||
std::string pSymName; /* Ptr to symbolic name or comment */
|
||||
uint32_t symOff; /* Symbol image offset */
|
||||
Function *symProc; /* Procedure pointer */
|
||||
SYMTABLE() : symOff(0),symProc(0) {}
|
||||
SYMTABLE(uint32_t _sym,Function *_proc) : symOff(_sym),symProc(_proc)
|
||||
{}
|
||||
bool operator == (const SYMTABLE &other) const
|
||||
{
|
||||
// does not yse pSymName, to ease finding by symOff/symProc combo
|
||||
// in map<SYMTABLE,X>
|
||||
return (symOff==other.symOff) && symProc==(other.symProc);
|
||||
}
|
||||
};
|
||||
|
||||
enum tableType /* The table types */
|
||||
enum _tableType /* The table types */
|
||||
{
|
||||
Label=0, /* The label table */
|
||||
Comment, /* The comment table */
|
||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||
};
|
||||
};
|
||||
|
||||
typedef enum _tableType tableType; /* For convenience */
|
||||
|
||||
void createSymTables(void);
|
||||
void destroySymTables(void);
|
||||
boolT readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc);
|
||||
void enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo);
|
||||
boolT readSym (char *symName, dword *pSymOff, PPROC *pSymProc);
|
||||
boolT readVal (char *symName, dword symOff, PPROC symProc);
|
||||
void deleteSym(char *symName);
|
||||
void deleteVal(dword symOff, PPROC symProc, boolT bSymToo);
|
||||
boolT findVal(dword symOff, PPROC symProc, word *pIndex);
|
||||
word symHash(char *name, word *pre);
|
||||
word valHash(dword off, PPROC proc, word *pre);
|
||||
void selectTable(tableType); /* Select a particular table */
|
||||
|
||||
char *addStrTbl(char *pStr); /* Add string to string table */
|
||||
|
||||
|
||||
@@ -2,19 +2,34 @@
|
||||
* 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 */
|
||||
typedef unsigned char byte; /* 8 bits */
|
||||
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];
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user