Only 2 differences with original release: add return type to main int disassem.cpp popPosStack() add cast to intptr_t
325 lines
15 KiB
C
325 lines
15 KiB
C
/****************************************************************************
|
|
* dcc project general header
|
|
* (C) Cristina Cifuentes, Mike van Emmerik
|
|
****************************************************************************/
|
|
|
|
|
|
#include "types.h"
|
|
#include "ast.h"
|
|
#include "icode.h"
|
|
#include "locident.h"
|
|
#include "error.h"
|
|
#include "graph.h"
|
|
#include "bundle.h"
|
|
|
|
|
|
/* 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 */
|
|
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 */
|
|
|
|
typedef struct { /* Command line option flags */
|
|
unsigned verbose : 1;
|
|
unsigned VeryVerbose : 1;
|
|
unsigned asm1 : 1; /* Early disassembly listing */
|
|
unsigned asm2 : 1; /* Disassembly listing after restruct */
|
|
unsigned Map : 1;
|
|
unsigned Stats : 1;
|
|
unsigned Interact : 1; /* Interactive mode */
|
|
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 */
|
|
|
|
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 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 */
|
|
#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 */
|
|
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 ****/
|
|
|
|
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 */
|
|
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 */
|
|
boolT LibCheck(PPROC p); /* chklib.c */
|
|
|
|
/* Exported functions from procs.c */
|
|
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 */
|
|
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 */
|
|
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 *);
|
|
|
|
|