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