996 lines
32 KiB
C++
996 lines
32 KiB
C++
/*
|
|
* File: ast.c
|
|
* Purpose: Support module for abstract syntax trees.
|
|
* Date: September 1993
|
|
* (C) Cristina Cifuentes
|
|
*/
|
|
#include <stdint.h>
|
|
#include <malloc.h> /* For free() */
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <cassert>
|
|
#include "types.h"
|
|
#include "dcc.h"
|
|
using namespace std;
|
|
/* Index registers **** temp solution */
|
|
static const char *idxReg[8] = {"bx+si", "bx+di", "bp+si", "bp+di",
|
|
"si", "di", "bp", "bx" };
|
|
/* Conditional operator symbols in C. Index by condOp enumeration type */
|
|
static const char *condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ",
|
|
" & ", " | ", " ^ ", " ~ ",
|
|
" + ", " - ", " * ", " / ",
|
|
" >> ", " << ", " % ", " && ", " || " };
|
|
|
|
#define EXP_SIZE 200 /* Size of the expression buffer */
|
|
|
|
/* Local expression stack */
|
|
//typedef struct _EXP_STK {
|
|
// COND_EXPR *exp;
|
|
// struct _EXP_STK *next;
|
|
//} EXP_STK;
|
|
typedef std::list<COND_EXPR *> EXP_STK;
|
|
static EXP_STK expStk; /* local expression stack */
|
|
|
|
|
|
/* Returns the integer i in C hexadecimal format */
|
|
static char *hexStr (uint16_t i)
|
|
{
|
|
static char buf[10];
|
|
// i &= 0xFFFF;
|
|
sprintf (buf, "%s%x", (i > 9) ? "0x" : "", i);
|
|
return (buf);
|
|
}
|
|
|
|
|
|
/* Sets the du record for registers according to the du flag */
|
|
void ICODE::setRegDU (byte regi, operDu du_in)
|
|
{
|
|
// printf("%s %d %x\n",__FUNCTION__,regi,int(du_in));
|
|
switch (du_in)
|
|
{
|
|
case eDEF:
|
|
du.def |= duReg[regi];
|
|
du1.numRegsDef++;
|
|
printf("%s du.def |= %x\n",__FUNCTION__,duReg[regi]);
|
|
break;
|
|
case eUSE:
|
|
du.use |= duReg[regi];
|
|
printf("%s du.use |= %x\n",__FUNCTION__,duReg[regi]);
|
|
break;
|
|
case USE_DEF:
|
|
du.def |= duReg[regi];
|
|
du1.numRegsDef++;
|
|
printf("%s du.def |= %x\n",__FUNCTION__,duReg[regi]);
|
|
printf("%s du.use |= %x\n",__FUNCTION__,duReg[regi]);
|
|
du.use |= duReg[regi];
|
|
break;
|
|
case NONE: /* do nothing */
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Copies the def, use, or def and use fields of duIcode into pIcode */
|
|
void copyDU (ICODE *pIcode, const ICODE *duIcode, operDu du, operDu duDu)
|
|
{
|
|
// printf("%s %d,%d from %d to %d\n",__FUNCTION__,int(du),int(duDu),duIcode->ic.ll.opcode,pIcode->ic.ll.opcode);
|
|
switch (du) {
|
|
case eDEF:
|
|
if (duDu == eDEF)
|
|
pIcode->du.def=duIcode->du.def;
|
|
else
|
|
pIcode->du.def=duIcode->du.use;
|
|
break;
|
|
case eUSE:
|
|
if (duDu == eDEF)
|
|
pIcode->du.use=duIcode->du.def;
|
|
else
|
|
pIcode->du.use =duIcode->du.use;
|
|
break;
|
|
case USE_DEF:
|
|
pIcode->du = duIcode->du;
|
|
break;
|
|
case NONE:
|
|
assert(false);
|
|
break;
|
|
}
|
|
printf("%s end: %x,%x\n",__FUNCTION__,pIcode->du.def,pIcode->du.use);
|
|
}
|
|
|
|
|
|
/* Creates a newExp conditional expression node of type t and returns it */
|
|
static COND_EXPR *newCondExp (condNodeType t)
|
|
{
|
|
//printf("%s:%d\n",__FUNCTION__,int(t));
|
|
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = new COND_EXPR;
|
|
//memset(newExp, 0, sizeof(COND_EXPR));
|
|
newExp->type = t;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Creates a conditional boolean expression and returns it */
|
|
COND_EXPR *COND_EXPR::boolOp(COND_EXPR *lhs, COND_EXPR *rhs, condOp op)
|
|
{
|
|
//printf("%s:%d\n",__FUNCTION__,int(op));
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (BOOLEAN_OP);
|
|
newExp->expr.boolExpr.op = op;
|
|
newExp->expr.boolExpr.lhs = lhs;
|
|
newExp->expr.boolExpr.rhs = rhs;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns a unary conditional expression node. This procedure should
|
|
* only be used with the following conditional node types: NEGATION,
|
|
* ADDRESSOF, DEREFERENCE, POST_INC, POST_DEC, PRE_INC, PRE_DEC */
|
|
COND_EXPR *COND_EXPR::unary(condNodeType t, COND_EXPR *sub_expr)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (t);
|
|
newExp->expr.unaryExp = sub_expr;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type GLOB_VAR */
|
|
COND_EXPR *COND_EXPR::idGlob (int16 segValue, int16 off)
|
|
{
|
|
COND_EXPR *newExp;
|
|
dword adr;
|
|
Int i;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = GLOB_VAR;
|
|
adr = opAdr(segValue, off);
|
|
for (i = 0; i < symtab.csym; i++)
|
|
if (symtab.sym[i].label == adr)
|
|
break;
|
|
if (i == symtab.csym)
|
|
printf ("Error, glob var not found in symtab\n");
|
|
newExp->expr.ident.idNode.globIdx = i;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type REGISTER */
|
|
COND_EXPR *COND_EXPR::idReg(byte regi, flags32 icodeFlg, LOCAL_ID *locsym)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = REGISTER;
|
|
if ((icodeFlg & B) || (icodeFlg & SRC_B))
|
|
{
|
|
newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg(TYPE_BYTE_SIGN, regi);
|
|
newExp->expr.ident.regiType = BYTE_REG;
|
|
}
|
|
else /* word */
|
|
{
|
|
newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg( TYPE_WORD_SIGN, regi);
|
|
newExp->expr.ident.regiType = WORD_REG;
|
|
}
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type REGISTER */
|
|
COND_EXPR *COND_EXPR::idRegIdx(Int idx, regType reg_type)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = REGISTER;
|
|
newExp->expr.ident.regiType = reg_type;
|
|
newExp->expr.ident.idNode.regiIdx = idx;
|
|
return (newExp);
|
|
}
|
|
|
|
/* Returns an identifier conditional expression node of type LOCAL_VAR */
|
|
COND_EXPR *COND_EXPR::idLoc(Int off, LOCAL_ID *localId)
|
|
{
|
|
COND_EXPR *newExp;
|
|
size_t i;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = LOCAL_VAR;
|
|
for (i = 0; i < localId->csym(); i++)
|
|
if ((localId->id_arr[i].id.bwId.off == off) &&
|
|
(localId->id_arr[i].id.bwId.regOff == 0))
|
|
break;
|
|
if (i == localId->csym())
|
|
printf ("Error, cannot find local var\n");
|
|
newExp->expr.ident.idNode.localIdx = i;
|
|
sprintf (localId->id_arr[i].name, "loc%ld", i);
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type PARAM */
|
|
COND_EXPR *COND_EXPR::idParam(Int off, const STKFRAME * argSymtab)
|
|
{
|
|
COND_EXPR *newExp;
|
|
size_t i;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = PARAM;
|
|
for (i = 0; i < argSymtab->sym.size(); i++)
|
|
if (argSymtab->sym[i].off == off)
|
|
break;
|
|
if (i == argSymtab->sym.size()) printf ("Error, cannot find argument var\n");
|
|
newExp->expr.ident.idNode.localIdx = i;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type GLOB_VAR_IDX.
|
|
* This global variable is indexed by regi. */
|
|
COND_EXPR *idCondExpIdxGlob (int16 segValue, int16 off, byte regi, const LOCAL_ID *locSym)
|
|
{
|
|
COND_EXPR *newExp;
|
|
size_t i;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = GLOB_VAR_IDX;
|
|
for (i = 0; i < locSym->csym(); i++)
|
|
if ((locSym->id_arr[i].id.bwGlb.seg == segValue) &&
|
|
(locSym->id_arr[i].id.bwGlb.off == off) &&
|
|
(locSym->id_arr[i].id.bwGlb.regi == regi))
|
|
break;
|
|
if (i == locSym->csym())
|
|
printf ("Error, indexed-glob var not found in local id table\n");
|
|
newExp->expr.ident.idNode.idxGlbIdx = i;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type CONSTANT */
|
|
COND_EXPR *COND_EXPR::idKte(dword kte, byte size)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = CONSTANT;
|
|
newExp->expr.ident.idNode.kte.kte = kte;
|
|
newExp->expr.ident.idNode.kte.size = size;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type LONG_VAR,
|
|
* that points to the given index idx. */
|
|
COND_EXPR *COND_EXPR::idLongIdx (Int idx)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = LONG_VAR;
|
|
newExp->expr.ident.idNode.longIdx = idx;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type LONG_VAR */
|
|
COND_EXPR *COND_EXPR::idLong(LOCAL_ID *localId, opLoc sd, ICODE *pIcode, hlFirst f, Int ix, operDu du, Int off)
|
|
{
|
|
COND_EXPR *newExp;
|
|
Int idx;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
|
|
/* Check for long constant and save it as a constant expression */
|
|
if ((sd == SRC) && ((pIcode->ic.ll.flg & I) == I)) /* constant */
|
|
{
|
|
newExp->expr.ident.idType = CONSTANT;
|
|
if (f == HIGH_FIRST)
|
|
newExp->expr.ident.idNode.kte.kte = (pIcode->ic.ll.immed.op << 16) +
|
|
(pIcode+off)->ic.ll.immed.op;
|
|
else /* LOW_FIRST */
|
|
newExp->expr.ident.idNode.kte.kte =
|
|
((pIcode+off)->ic.ll.immed.op << 16)+ pIcode->ic.ll.immed.op;
|
|
newExp->expr.ident.idNode.kte.size = 4;
|
|
}
|
|
/* Save it as a long expression (reg, stack or glob) */
|
|
else
|
|
{
|
|
idx = localId->newLong(sd, pIcode, f, ix, du, off);
|
|
newExp->expr.ident.idType = LONG_VAR;
|
|
newExp->expr.ident.idNode.longIdx = idx;
|
|
}
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type FUNCTION */
|
|
COND_EXPR *COND_EXPR::idFunc(Function * pproc, STKFRAME * args)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = FUNCTION;
|
|
newExp->expr.ident.idNode.call.proc = pproc;
|
|
newExp->expr.ident.idNode.call.args = args;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type OTHER.
|
|
* Temporary solution, should really be encoded as an indexed type (eg.
|
|
* arrays). */
|
|
COND_EXPR *COND_EXPR::idOther(byte seg, byte regi, int16 off)
|
|
{
|
|
COND_EXPR *newExp;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
newExp->expr.ident.idType = OTHER;
|
|
newExp->expr.ident.idNode.other.seg = seg;
|
|
newExp->expr.ident.idNode.other.regi = regi;
|
|
newExp->expr.ident.idNode.other.off = off;
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node of type TYPE_LONG or
|
|
* TYPE_WORD_SIGN */
|
|
COND_EXPR *COND_EXPR::idID (const ID *retVal, LOCAL_ID *locsym, Int ix)
|
|
{
|
|
COND_EXPR *newExp;
|
|
Int idx;
|
|
|
|
newExp = newCondExp (IDENTIFIER);
|
|
if (retVal->type == TYPE_LONG_SIGN)
|
|
{
|
|
idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->id.longId.h,retVal->id.longId.l, ix);
|
|
newExp->expr.ident.idType = LONG_VAR;
|
|
newExp->expr.ident.idNode.longIdx = idx;
|
|
}
|
|
else if (retVal->type == TYPE_WORD_SIGN)
|
|
{
|
|
newExp->expr.ident.idType = REGISTER;
|
|
newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg(TYPE_WORD_SIGN, retVal->id.regi);
|
|
newExp->expr.ident.regiType = WORD_REG;
|
|
}
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns an identifier conditional expression node, according to the given
|
|
* type.
|
|
* Arguments: i : index into the icode array, used for newLongRegId only.
|
|
* duIcode: icode instruction that needs the du set.
|
|
* du: operand is defined or used in current instruction. */
|
|
COND_EXPR *COND_EXPR::id(ICODE *pIcode, opLoc sd, Function * pProc, Int i,ICODE *duIcode, operDu du)
|
|
{
|
|
COND_EXPR *newExp;
|
|
ICODEMEM * pm;
|
|
Int idx; /* idx into pIcode->localId table */
|
|
|
|
pm = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
|
|
|
if (((sd == DST) && (pIcode->ic.ll.flg & IM_DST) == IM_DST) ||
|
|
((sd == SRC) && (pIcode->ic.ll.flg & IM_SRC)) ||
|
|
(sd == LHS_OP)) /* for MUL lhs */
|
|
{ /* implicit dx:ax */
|
|
idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, rDX, rAX, i);
|
|
newExp = COND_EXPR::idLongIdx (idx);
|
|
duIcode->setRegDU (rDX, du);
|
|
duIcode->setRegDU (rAX, du);
|
|
}
|
|
|
|
else if ((sd == DST) && (pIcode->ic.ll.flg & IM_TMP_DST) == IM_TMP_DST)
|
|
{ /* implicit tmp */
|
|
newExp = COND_EXPR::idReg (rTMP, 0, &pProc->localId);
|
|
duIcode->setRegDU(rTMP, (operDu)eUSE);
|
|
}
|
|
|
|
else if ((sd == SRC) && ((pIcode->ic.ll.flg & I) == I)) /* constant */
|
|
newExp = COND_EXPR::idKte (pIcode->ic.ll.immed.op, 2);
|
|
|
|
else if (pm->regi == 0) /* global variable */
|
|
newExp = COND_EXPR::idGlob(pm->segValue, pm->off);
|
|
|
|
else if (pm->regi < INDEXBASE) /* register */
|
|
{
|
|
newExp = COND_EXPR::idReg (pm->regi, (sd == SRC) ? pIcode->ic.ll.flg :
|
|
pIcode->ic.ll.flg & NO_SRC_B, &pProc->localId);
|
|
duIcode->setRegDU( pm->regi, du);
|
|
}
|
|
|
|
else if (pm->off) /* offset */
|
|
{
|
|
if ((pm->seg == rSS) && (pm->regi == INDEXBASE + 6)) /* idx on bp */
|
|
{
|
|
if (pm->off >= 0) /* argument */
|
|
newExp = COND_EXPR::idParam (pm->off, &pProc->args);
|
|
else /* local variable */
|
|
newExp = COND_EXPR::idLoc (pm->off, &pProc->localId);
|
|
}
|
|
else if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7)) /* bx */
|
|
{
|
|
if (pm->off > 0) /* global variable */
|
|
newExp = idCondExpIdxGlob (pm->segValue, pm->off, rBX,&pProc->localId);
|
|
else
|
|
newExp = COND_EXPR::idOther (pm->seg, pm->regi, pm->off);
|
|
duIcode->setRegDU( rBX, eUSE);
|
|
}
|
|
else /* idx <> bp, bx */
|
|
newExp = COND_EXPR::idOther (pm->seg, pm->regi, pm->off);
|
|
/**** check long ops, indexed global var *****/
|
|
}
|
|
|
|
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
|
{
|
|
if ((pm->seg == rDS) && (pm->regi > INDEXBASE + 3)) /* dereference */
|
|
{
|
|
switch (pm->regi) {
|
|
case INDEXBASE + 4: newExp = COND_EXPR::idReg(rSI, 0, &pProc->localId);
|
|
duIcode->setRegDU( rSI, du);
|
|
break;
|
|
case INDEXBASE + 5: newExp = COND_EXPR::idReg(rDI, 0, &pProc->localId);
|
|
duIcode->setRegDU( rDI, du);
|
|
break;
|
|
case INDEXBASE + 6: newExp = COND_EXPR::idReg(rBP, 0, &pProc->localId);
|
|
break;
|
|
case INDEXBASE + 7: newExp = COND_EXPR::idReg(rBX, 0, &pProc->localId);
|
|
duIcode->setRegDU( rBX, du);
|
|
break;
|
|
default:
|
|
newExp = 0;
|
|
assert(false);
|
|
}
|
|
newExp = COND_EXPR::unary (DEREFERENCE, newExp);
|
|
}
|
|
else
|
|
newExp = COND_EXPR::idOther (pm->seg, pm->regi, 0);
|
|
}
|
|
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Returns the identifier type */
|
|
condId ICODE::idType(opLoc sd)
|
|
{
|
|
ICODEMEM *pm;
|
|
|
|
pm = (sd == SRC) ? &ic.ll.src : &ic.ll.dst;
|
|
|
|
if ((sd == SRC) && ((ic.ll.flg & I) == I))
|
|
return (CONSTANT);
|
|
else if (pm->regi == 0)
|
|
return (GLOB_VAR);
|
|
else if (pm->regi < INDEXBASE)
|
|
return (REGISTER);
|
|
else if ((pm->seg == rSS) && (pm->regi == INDEXBASE))
|
|
{
|
|
if (pm->off >= 0)
|
|
return (PARAM);
|
|
else
|
|
return (LOCAL_VAR);
|
|
}
|
|
else
|
|
return (OTHER);
|
|
}
|
|
|
|
|
|
/* Size of hl types */
|
|
Int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4};
|
|
|
|
|
|
/* Returns the type of the expression */
|
|
Int hlTypeSize (const COND_EXPR *expr, Function * pproc)
|
|
{
|
|
Int first, second;
|
|
|
|
if (expr == NULL)
|
|
return (2); /* for TYPE_UNKNOWN */
|
|
|
|
switch (expr->type) {
|
|
case BOOLEAN_OP:
|
|
first = hlTypeSize (expr->expr.boolExpr.lhs, pproc);
|
|
second = hlTypeSize (expr->expr.boolExpr.rhs, pproc);
|
|
if (first > second)
|
|
return (first);
|
|
else
|
|
return (second);
|
|
|
|
case NEGATION: case ADDRESSOF:
|
|
case POST_INC: case POST_DEC:
|
|
case PRE_INC: case PRE_DEC:
|
|
case DEREFERENCE: return (hlTypeSize (expr->expr.unaryExp, pproc));
|
|
|
|
case IDENTIFIER:
|
|
switch (expr->expr.ident.idType)
|
|
{
|
|
case GLOB_VAR:
|
|
return (symtab.sym[expr->expr.ident.idNode.globIdx].size);
|
|
case REGISTER:
|
|
if (expr->expr.ident.regiType == BYTE_REG)
|
|
return (1);
|
|
else
|
|
return (2);
|
|
case LOCAL_VAR:
|
|
return (hlSize[pproc->localId.id_arr[expr->expr.ident.idNode.localIdx].type]);
|
|
case PARAM:
|
|
return (hlSize[pproc->args.sym[expr->expr.ident.idNode.paramIdx].type]);
|
|
case GLOB_VAR_IDX:
|
|
return (hlSize[pproc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].type]);
|
|
case CONSTANT:
|
|
return (expr->expr.ident.idNode.kte.size);
|
|
case STRING:
|
|
return (2);
|
|
case LONG_VAR:
|
|
return (4);
|
|
case FUNCTION:
|
|
return (hlSize[expr->expr.ident.idNode.call.proc->retVal.type]);
|
|
case OTHER:
|
|
return (2);
|
|
} /* eos */
|
|
break;
|
|
}
|
|
return 2; // CC: is this correct?
|
|
}
|
|
|
|
|
|
/* Returns the type of the expression */
|
|
hlType expType (const COND_EXPR *expr, Function * pproc)
|
|
{
|
|
hlType first, second;
|
|
|
|
if (expr == NULL)
|
|
return (TYPE_UNKNOWN);
|
|
|
|
switch (expr->type)
|
|
{
|
|
case BOOLEAN_OP:
|
|
first = expType (expr->expr.boolExpr.lhs, pproc);
|
|
second = expType (expr->expr.boolExpr.rhs, pproc);
|
|
if (first != second)
|
|
{
|
|
if (hlTypeSize (expr->expr.boolExpr.lhs, pproc) >
|
|
hlTypeSize (expr->expr.boolExpr.rhs, pproc))
|
|
return (first);
|
|
else
|
|
return (second);
|
|
}
|
|
else
|
|
return (first);
|
|
|
|
case POST_INC: case POST_DEC:
|
|
case PRE_INC: case PRE_DEC:
|
|
case NEGATION: return (expType (expr->expr.unaryExp, pproc));
|
|
|
|
case ADDRESSOF: return (TYPE_PTR); /***????****/
|
|
case DEREFERENCE: return (TYPE_PTR);
|
|
case IDENTIFIER:
|
|
switch (expr->expr.ident.idType)
|
|
{
|
|
case GLOB_VAR:
|
|
return (symtab.sym[expr->expr.ident.idNode.globIdx].type);
|
|
case REGISTER:
|
|
if (expr->expr.ident.regiType == BYTE_REG)
|
|
return (TYPE_BYTE_SIGN);
|
|
else
|
|
return (TYPE_WORD_SIGN);
|
|
case LOCAL_VAR:
|
|
return (pproc->localId.id_arr[expr->expr.ident.idNode.localIdx].type);
|
|
case PARAM:
|
|
return (pproc->args.sym[expr->expr.ident.idNode.paramIdx].type);
|
|
case GLOB_VAR_IDX:
|
|
return (pproc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].type);
|
|
case CONSTANT:
|
|
return (TYPE_CONST);
|
|
case STRING:
|
|
return (TYPE_STR);
|
|
case LONG_VAR:
|
|
return (pproc->localId.id_arr[expr->expr.ident.idNode.longIdx].type);
|
|
case FUNCTION:
|
|
return (expr->expr.ident.idNode.call.proc->retVal.type);
|
|
case OTHER:
|
|
return (TYPE_UNKNOWN);
|
|
} /* eos */
|
|
case UNKNOWN_OP:
|
|
assert(false);
|
|
return (TYPE_UNKNOWN);
|
|
}
|
|
return TYPE_UNKNOWN; // CC: Correct?
|
|
}
|
|
|
|
|
|
/* Removes the register from the tree. If the register was part of a long
|
|
* register (eg. dx:ax), the node gets transformed into an integer register
|
|
* node. */
|
|
void removeRegFromLong (byte regi, LOCAL_ID *locId, COND_EXPR *tree)
|
|
{
|
|
IDENTTYPE* ident; /* ptr to an identifier */
|
|
byte otherRegi; /* high or low part of long register */
|
|
|
|
switch (tree->type) {
|
|
case BOOLEAN_OP:
|
|
break;
|
|
case POST_INC: case POST_DEC:
|
|
case PRE_INC: case PRE_DEC:
|
|
case NEGATION: case ADDRESSOF:
|
|
case DEREFERENCE:
|
|
break;
|
|
case IDENTIFIER:
|
|
ident = &tree->expr.ident;
|
|
if (ident->idType == LONG_VAR)
|
|
{
|
|
otherRegi = otherLongRegi (regi, ident->idNode.longIdx, locId);
|
|
ident->idType = REGISTER;
|
|
ident->regiType = WORD_REG;
|
|
ident->idNode.regiIdx = locId->newByteWordReg(TYPE_WORD_SIGN,otherRegi);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Returns the string located in image, formatted in C format. */
|
|
static std::string getString (Int offset)
|
|
{
|
|
ostringstream o;
|
|
Int strLen, i;
|
|
|
|
strLen = strSize (&prog.Image[offset], '\0');
|
|
o << '"';
|
|
for (i = 0; i < strLen; i++)
|
|
o<<cChar(prog.Image[offset+i]);
|
|
o << "\"\0";
|
|
return (o.str());
|
|
}
|
|
|
|
|
|
/* Walks the conditional expression tree and returns the result on a string */
|
|
// TODO: use string stream here
|
|
string walkCondExpr (const COND_EXPR* expr, Function * pProc, Int* numLoc)
|
|
{
|
|
int16 off; /* temporal - for OTHER */
|
|
ID* id; /* Pointer to local identifier table */
|
|
char* o; /* Operand string pointer */
|
|
boolT needBracket; /* Determine whether parenthesis is needed */
|
|
BWGLB_TYPE* bwGlb; /* Ptr to BWGLB_TYPE (global indexed var) */
|
|
STKSYM * psym; /* Pointer to argument in the stack */
|
|
std::ostringstream outStr;
|
|
|
|
if (expr == NULL)
|
|
return "";
|
|
|
|
needBracket = TRUE;
|
|
switch (expr->type)
|
|
{
|
|
case BOOLEAN_OP:
|
|
outStr << "(";
|
|
outStr << walkCondExpr(expr->expr.boolExpr.lhs, pProc, numLoc);
|
|
outStr << condOpSym[expr->expr.boolExpr.op];
|
|
outStr << walkCondExpr(expr->expr.boolExpr.rhs, pProc, numLoc);
|
|
outStr << ")";
|
|
break;
|
|
|
|
case NEGATION:
|
|
if (expr->expr.unaryExp->type == IDENTIFIER)
|
|
{
|
|
needBracket = FALSE;
|
|
outStr << "!";
|
|
}
|
|
else
|
|
outStr << "! (";
|
|
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
|
if (needBracket == TRUE)
|
|
outStr << ")";
|
|
break;
|
|
|
|
case ADDRESSOF:
|
|
if (expr->expr.unaryExp->type == IDENTIFIER)
|
|
{
|
|
needBracket = FALSE;
|
|
outStr << "&";
|
|
}
|
|
else
|
|
outStr << "&(";
|
|
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
|
if (needBracket == TRUE)
|
|
outStr << ")";
|
|
break;
|
|
|
|
case DEREFERENCE:
|
|
outStr << "*";
|
|
if (expr->expr.unaryExp->type == IDENTIFIER)
|
|
needBracket = FALSE;
|
|
else
|
|
outStr << "(";
|
|
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
|
if (needBracket == TRUE)
|
|
outStr << ")";
|
|
break;
|
|
|
|
case POST_INC:
|
|
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "++";
|
|
break;
|
|
|
|
case POST_DEC:
|
|
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "--";
|
|
break;
|
|
|
|
case PRE_INC:
|
|
outStr << "++"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
|
break;
|
|
|
|
case PRE_DEC:
|
|
outStr << "--"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
|
break;
|
|
|
|
case IDENTIFIER:
|
|
std::ostringstream o;
|
|
switch (expr->expr.ident.idType)
|
|
{
|
|
case GLOB_VAR:
|
|
o << symtab.sym[expr->expr.ident.idNode.globIdx].name;
|
|
break;
|
|
case REGISTER:
|
|
id = &pProc->localId.id_arr[expr->expr.ident.idNode.regiIdx];
|
|
if (id->name[0] == '\0') /* no name */
|
|
{
|
|
sprintf (id->name, "loc%ld", ++(*numLoc));
|
|
if (id->id.regi < rAL)
|
|
cCode.appendDecl("%s %s; /* %s */\n",hlTypes[id->type], id->name,wordReg[id->id.regi - rAX]);
|
|
else
|
|
cCode.appendDecl("%s %s; /* %s */\n",hlTypes[id->type], id->name,byteReg[id->id.regi - rAL]);
|
|
}
|
|
if (id->hasMacro)
|
|
o << id->macro << "("<<id->name<<")";
|
|
else
|
|
o << id->name;
|
|
break;
|
|
|
|
case LOCAL_VAR:
|
|
o << pProc->localId.id_arr[expr->expr.ident.idNode.localIdx].name;
|
|
break;
|
|
|
|
case PARAM:
|
|
psym = &pProc->args.sym[expr->expr.ident.idNode.paramIdx];
|
|
if (psym->hasMacro)
|
|
o << psym->macro<<"("<<psym->name<< ")";
|
|
else
|
|
o << psym->name;
|
|
break;
|
|
|
|
case GLOB_VAR_IDX:
|
|
bwGlb = &pProc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].id.bwGlb;
|
|
o << (bwGlb->seg << 4) + bwGlb->off << "["<<wordReg[bwGlb->regi - rAX]<<"]";
|
|
break;
|
|
|
|
case CONSTANT:
|
|
if (expr->expr.ident.idNode.kte.kte < 1000)
|
|
o << expr->expr.ident.idNode.kte.kte;
|
|
else
|
|
o << "0x"<<std::hex << expr->expr.ident.idNode.kte.kte;
|
|
break;
|
|
|
|
case STRING:
|
|
o << getString (expr->expr.ident.idNode.strIdx);
|
|
break;
|
|
|
|
case LONG_VAR:
|
|
id = &pProc->localId.id_arr[expr->expr.ident.idNode.longIdx];
|
|
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
|
|
o << id->name;
|
|
else if (id->loc == REG_FRAME)
|
|
{
|
|
sprintf (id->name, "loc%ld", ++(*numLoc));
|
|
cCode.appendDecl("%s %s; /* %s:%s */\n",hlTypes[id->type], id->name,wordReg[id->id.longId.h - rAX],wordReg[id->id.longId.l - rAX]);
|
|
o << id->name;
|
|
pProc->localId.propLongId (id->id.longId.l,id->id.longId.h, id->name);
|
|
}
|
|
else /* GLB_FRAME */
|
|
{
|
|
if (id->id.longGlb.regi == 0) /* not indexed */
|
|
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
|
|
else if (id->id.longGlb.regi == rBX)
|
|
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
|
|
}
|
|
break;
|
|
|
|
case FUNCTION:
|
|
o << writeCall (expr->expr.ident.idNode.call.proc,expr->expr.ident.idNode.call.args, pProc, numLoc);
|
|
break;
|
|
|
|
case OTHER:
|
|
off = expr->expr.ident.idNode.other.off;
|
|
o << wordReg[expr->expr.ident.idNode.other.seg - rAX]<< "[";
|
|
o << idxReg[expr->expr.ident.idNode.other.regi - INDEXBASE];
|
|
if (off < 0)
|
|
o << "-"<< hexStr (-off);
|
|
else if (off>0)
|
|
o << "+"<< hexStr (off);
|
|
o << "]";
|
|
} /* eos */
|
|
outStr << o.str();
|
|
break;
|
|
}
|
|
|
|
return outStr.str();
|
|
}
|
|
|
|
|
|
/* Makes a copy of the given expression. Allocates newExp storage for each
|
|
* node. Returns the copy. */
|
|
COND_EXPR *COND_EXPR::clone()
|
|
{
|
|
COND_EXPR* newExp=0; /* Expression node copy */
|
|
|
|
switch (type)
|
|
{
|
|
case BOOLEAN_OP:
|
|
newExp = new COND_EXPR(*this);
|
|
newExp->expr.boolExpr.lhs = expr.boolExpr.lhs->clone();
|
|
newExp->expr.boolExpr.rhs = expr.boolExpr.rhs->clone();
|
|
break;
|
|
|
|
case NEGATION:
|
|
case ADDRESSOF:
|
|
case DEREFERENCE:
|
|
newExp = new COND_EXPR(*this);
|
|
newExp->expr.unaryExp = expr.unaryExp->clone();
|
|
break;
|
|
|
|
case IDENTIFIER:
|
|
newExp = new COND_EXPR(*this);
|
|
}
|
|
return (newExp);
|
|
}
|
|
|
|
|
|
/* Changes the boolean conditional operator at the root of this expression */
|
|
void COND_EXPR::changeBoolOp (condOp newOp)
|
|
{
|
|
expr.boolExpr.op = newOp;
|
|
}
|
|
|
|
|
|
/* Inserts the expression exp into the tree at the location specified by the
|
|
* register regi */
|
|
boolT insertSubTreeReg (COND_EXPR *expr, COND_EXPR **tree, byte regi,LOCAL_ID *locsym)
|
|
{
|
|
byte treeReg;
|
|
|
|
if (*tree == NULL)
|
|
return FALSE;
|
|
|
|
switch ((*tree)->type) {
|
|
case IDENTIFIER:
|
|
if ((*tree)->expr.ident.idType == REGISTER)
|
|
{
|
|
treeReg = locsym->id_arr[(*tree)->expr.ident.idNode.regiIdx].id.regi;
|
|
if (treeReg == regi) /* word reg */
|
|
{
|
|
*tree = expr;
|
|
return TRUE;
|
|
}
|
|
else if ((regi >= rAX) && (regi <= rBX)) /* word/byte reg */
|
|
{
|
|
if ((treeReg == (regi + rAL-1)) || (treeReg == (regi + rAH-1)))
|
|
{
|
|
*tree = expr;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
|
|
case BOOLEAN_OP:
|
|
if (insertSubTreeReg (expr, &(*tree)->expr.boolExpr.lhs, regi, locsym))
|
|
return TRUE;
|
|
if (insertSubTreeReg (expr, &(*tree)->expr.boolExpr.rhs, regi, locsym))
|
|
return TRUE;
|
|
return FALSE;
|
|
|
|
case NEGATION:
|
|
case ADDRESSOF:
|
|
case DEREFERENCE:
|
|
if (insertSubTreeReg(expr, &(*tree)->expr.unaryExp,regi, locsym))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* Inserts the expression exp into the tree at the location specified by the
|
|
* long register index longIdx*/
|
|
boolT insertSubTreeLongReg (COND_EXPR *exp, COND_EXPR **tree, Int longIdx)
|
|
{
|
|
switch ((*tree)->type) {
|
|
case IDENTIFIER: if ((*tree)->expr.ident.idNode.longIdx == longIdx)
|
|
{
|
|
*tree = exp;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
|
|
case BOOLEAN_OP: if (insertSubTreeLongReg (exp, &(*tree)->expr.boolExpr.lhs, longIdx))
|
|
return TRUE;
|
|
if (insertSubTreeLongReg (exp, &(*tree)->expr.boolExpr.rhs, longIdx))
|
|
return TRUE;
|
|
return FALSE;
|
|
|
|
case NEGATION:
|
|
case ADDRESSOF:
|
|
case DEREFERENCE: if (insertSubTreeLongReg (exp, &(*tree)->expr.unaryExp, longIdx))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* Recursively deallocates the abstract syntax tree rooted at *exp */
|
|
void COND_EXPR::release()
|
|
{
|
|
switch (type)
|
|
{
|
|
case BOOLEAN_OP:
|
|
expr.boolExpr.lhs->release();
|
|
expr.boolExpr.rhs->release();
|
|
break;
|
|
case NEGATION:
|
|
case ADDRESSOF:
|
|
case DEREFERENCE:
|
|
expr.unaryExp->release();
|
|
break;
|
|
}
|
|
delete (this);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* Expression stack functions
|
|
**************************************************************************/
|
|
|
|
/* Reinitalizes the expression stack (expStk) to NULL, by freeing all the
|
|
* space allocated (if any). */
|
|
void initExpStk()
|
|
{
|
|
expStk.clear();
|
|
}
|
|
|
|
|
|
/* Pushes the given expression onto the local stack (expStk). */
|
|
void pushExpStk (COND_EXPR *expr)
|
|
{
|
|
expStk.push_back(expr);
|
|
}
|
|
|
|
|
|
/* Returns the element on the top of the local expression stack (expStk),
|
|
* and deallocates the space allocated by this node.
|
|
* If there are no elements on the stack, returns NULL. */
|
|
COND_EXPR *popExpStk()
|
|
{
|
|
if(expStk.empty())
|
|
return 0;
|
|
COND_EXPR *topExp = expStk.back();
|
|
expStk.pop_back();
|
|
return topExp;
|
|
}
|
|
|
|
/* Returns the number of elements available in the expression stack */
|
|
Int numElemExpStk()
|
|
{
|
|
return expStk.size();
|
|
}
|
|
|
|
/* Returns whether the expression stack is empty or not */
|
|
boolT emptyExpStk()
|
|
{
|
|
return expStk.empty();
|
|
}
|