123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639 |
- /*
- * File: hlIcode.c
- * Purpose: High-level icode routines
- * Date: September-October 1993
- * (C) Cristina Cifuentes
- */
- #include "dcc.h"
- #include <QtCore/QDebug>
- #include <QtCore/QString>
- #include <cassert>
- #include <string.h>
- #include <string>
- #include <sstream>
- using namespace std;
- /* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
- void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
- {
- assert(lhs);
- set(lhs,rhs);
- }
- void ICODE::checkHlCall()
- {
- //assert((ll()->immed.proc.cb != 0) or ll()->immed.proc.proc!=0);
- }
- /* Places the new HLI_CALL high-level operand in the high-level icode array */
- void ICODE::newCallHl()
- {
- type = HIGH_LEVEL;
- hlU()->setCall(ll()->src().proc.proc);
- if (ll()->src().proc.cb != 0)
- hlU()->call.args->cb = ll()->src().proc.cb;
- else if(hl()->call.proc)
- hlU()->call.args->cb = hl()->call.proc->cbParam;
- else
- {
- printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
- hl()->call.args->cb = 0;
- }
- }
- /* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
- * array */
- void ICODE::setUnary(hlIcode op, Expr *_exp)
- {
- type = HIGH_LEVEL;
- hlU()->set(op,_exp);
- }
- /* Places the new HLI_JCOND high-level operand in the high-level icode array */
- void ICODE::setJCond(Expr *cexp)
- {
- type = HIGH_LEVEL;
- hlU()->set(HLI_JCOND,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)
- */
- bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
- {
- int numDefs;
- numDefs = du1.getNumRegsDef();
- if (numDefs == thisDefIdx)
- {
- for ( ; numDefs > 0; numDefs--)
- {
- if (du1.used(numDefs-1) or (du.lastDefRegi.testReg(regi)))
- break;
- }
- }
- if (numDefs == 0)
- {
- invalidate();
- return true;
- }
- HlTypeSupport *p=hlU()->get();
- if(p and p->removeRegFromLong(regi,locId))
- {
- du1.removeDef(regi); //du1.numRegsDef--;
- //du.def &= maskDuReg[regi];
- du.def.clrReg(regi);
- }
- return false;
- }
- HLTYPE LLInst::createCall()
- {
- HLTYPE res(HLI_CALL);
- res.call.proc = src().proc.proc;
- res.call.args = new STKFRAME;
- if (src().proc.cb != 0)
- res.call.args->cb = src().proc.cb;
- else if(res.call.proc)
- res.call.args->cb =res.call.proc->cbParam;
- else
- {
- printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
- res.call.args->cb = 0;
- }
- return res;
- }
- #if 0
- HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
- {
- HLTYPE res(HLI_INVALID);
- if ( testFlags(NOT_HLL) )
- return res;
- flg = getFlag();
- switch (getOpcode())
- {
- case iADD:
- rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
- res.setAsgn(lhs, rhs);
- break;
- case iAND:
- rhs = COND_EXPR::boolOp (lhs, rhs, AND);
- res.setAsgn(lhs, rhs);
- break;
- case iCALL:
- case iCALLF:
- //TODO: this is noop pIcode->checkHlCall();
- res=createCall();
- break;
- case iDEC:
- rhs = AstIdent::idKte (1, 2);
- rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
- res.setAsgn(lhs, rhs);
- break;
- case iDIV:
- case iIDIV:/* should be signed div */
- rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
- if ( ll->testFlags(B) )
- {
- lhs = AstIdent::idReg (rAL, 0, &localId);
- pIcode->setRegDU( rAL, eDEF);
- }
- else
- {
- lhs = AstIdent::idReg (rAX, 0, &localId);
- pIcode->setRegDU( rAX, eDEF);
- }
- res.setAsgn(lhs, rhs);
- break;
- case iIMUL:
- rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
- lhs = AstIdent::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
- res.setAsgn(lhs, rhs);
- break;
- case iINC:
- rhs = AstIdent::idKte (1, 2);
- rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
- res.setAsgn(lhs, rhs);
- break;
- case iLEA:
- rhs = COND_EXPR::unary (ADDRESSOF, rhs);
- res.setAsgn(lhs, rhs);
- break;
- case iMOD:
- rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
- if ( ll->testFlags(B) )
- {
- lhs = AstIdent::idReg (rAH, 0, &localId);
- pIcode->setRegDU( rAH, eDEF);
- }
- else
- {
- lhs = AstIdent::idReg (rDX, 0, &localId);
- pIcode->setRegDU( rDX, eDEF);
- }
- res.setAsgn(lhs, rhs);
- break;
- case iMOV: res.setAsgn(lhs, rhs);
- break;
- case iMUL:
- rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
- lhs = AstIdent::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
- res.setAsgn(lhs, rhs);
- break;
- case iNEG:
- rhs = COND_EXPR::unary (NEGATION, lhs);
- res.setAsgn(lhs, rhs);
- break;
- case iNOT:
- rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
- res.setAsgn(lhs, rhs);
- break;
- case iOR:
- rhs = COND_EXPR::boolOp (lhs, rhs, OR);
- res.setAsgn(lhs, rhs);
- break;
- case iPOP: res.set(HLI_POP, lhs);
- break;
- case iPUSH: res.set(HLI_PUSH, lhs);
- break;
- case iRET:
- case iRETF:
- res.set(HLI_RET, NULL);
- break;
- case iSHL:
- rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
- res.setAsgn(lhs, rhs);
- break;
- case iSAR: /* signed */
- case iSHR:
- rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
- res.setAsgn(lhs, rhs);
- break;
- case iSIGNEX:
- res.setAsgn(lhs, rhs);
- break;
- case iSUB:
- rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
- res.setAsgn(lhs, rhs);
- break;
- case iXCHG:
- break;
- case iXOR:
- rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
- res.setAsgn(lhs, rhs);
- break;
- }
- return res;
- }
- #endif
- static bool needsLhs(unsigned opc)
- {
- switch (opc)
- {
- case iCALL:
- case iCALLF:
- case iRET:
- case iRETF:
- default: return false;
- case iADD:
- case iAND:
- case iDEC:
- case iDIV:
- case iIDIV:/* should be signed div */
- case iIMUL:
- case iINC:
- case iLEA:
- case iMOD:
- case iMOV:
- case iMUL:
- case iNEG:
- case iNOT:
- case iOR:
- case iPOP:
- case iPUSH:
- case iSHL:
- case iSAR: /* signed */
- case iSHR:
- case iSIGNEX:
- case iSUB:
- case iXCHG:
- case iXOR:
- return true;
- }
- }
- /* 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()
- {
- size_t numIcode; /* number of icode instructions */
- iICODE pIcode; /* ptr to current icode node */
- Expr *rhs; /* left- and right-hand side of expression */
- uint32_t _flg; /* icode flags */
- numIcode = Icode.size();
- for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
- {
- Expr *lhs=nullptr;
- assert(numIcode==Icode.size());
- pIcode = i; //Icode.GetIcode(i)
- LLInst *ll = pIcode->ll();
- LLOperand *dst_ll = ll->get(DST);
- LLOperand *src_ll = ll->get(SRC);
- if ( ll->testFlags(NOT_HLL) )
- pIcode->invalidate();
- if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
- continue;
- _flg = ll->getFlag();
- if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
- if ( not ll->testFlags(NO_OPS) ) /* if there are opers */
- {
- if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
- rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
- if(ll->m_dst.isSet() or (ll->getOpcode()==iMOD))
- lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
- }
- if(ll->getOpcode()==iPUSH) {
- if(ll->testFlags(I)) {
- lhs = new Constant(src_ll->opz,src_ll->byteWidth());
- }
- // lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
- }
- if(needsLhs(ll->getOpcode()))
- assert(lhs!=nullptr);
- switch (ll->getOpcode())
- {
- case iADD:
- rhs = new BinaryOperator(ADD,lhs, rhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iAND:
- rhs = BinaryOperator::And(lhs, rhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iCALL:
- case iCALLF:
- pIcode->type = HIGH_LEVEL;
- pIcode->hl( ll->createCall() );
- break;
- case iDEC:
- rhs = new BinaryOperator(SUB,lhs, new Constant(1, 2));
- pIcode->setAsgn(lhs, rhs);
- break;
- case iDIV:
- case iIDIV:/* should be signed div */
- {
- eReg v = ( dst_ll->byteWidth()==1) ? rAL:rAX;
- rhs = new BinaryOperator(DIV,lhs, rhs);
- lhs = new RegisterNode(LLOperand(v, dst_ll->byteWidth()), &localId);
- pIcode->setRegDU( v, eDEF);
- pIcode->setAsgn(lhs, rhs);
- }
- break;
- case iIMUL:
- rhs = new BinaryOperator(MUL,lhs, rhs);
- lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iINC:
- rhs = new BinaryOperator(ADD,lhs, new Constant(1, 2));
- pIcode->setAsgn(lhs, rhs);
- break;
- case iLEA:
- rhs =UnaryOperator::Create(ADDRESSOF, rhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iMOD:
- {
- rhs = new BinaryOperator(MOD,lhs, rhs);
- eReg lhs_reg = (dst_ll->byteWidth()==1) ? rAH : rDX;
- lhs = new RegisterNode(LLOperand(lhs_reg, dst_ll->byteWidth()), &localId);
- pIcode->setRegDU( lhs_reg, eDEF);
- pIcode->setAsgn(lhs, rhs);
- }
- break;
- case iMOV: pIcode->setAsgn(lhs, rhs);
- break;
- case iMUL:
- rhs = new BinaryOperator(MUL,lhs, rhs);
- lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iNEG:
- rhs = UnaryOperator::Create(NEGATION, lhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iNOT:
- rhs = new BinaryOperator(NOT,nullptr, rhs); // TODO: change this to unary NOT ?
- pIcode->setAsgn(lhs, rhs);
- break;
- case iOR:
- rhs = new BinaryOperator(OR,lhs, rhs);
- 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, nullptr);
- break;
- case iSHL:
- rhs = new BinaryOperator(SHL,lhs, rhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iSAR: /* signed */
- case iSHR:
- rhs = new BinaryOperator(SHR,lhs, rhs); /* unsigned*/
- pIcode->setAsgn(lhs, rhs);
- break;
- case iSIGNEX: pIcode->setAsgn(lhs, rhs);
- break;
- case iSUB:
- rhs = new BinaryOperator(SUB,lhs, rhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- case iXCHG:
- break;
- case iXOR:
- rhs = new BinaryOperator(XOR,lhs, rhs);
- pIcode->setAsgn(lhs, rhs);
- break;
- }
- }
- }
- /**
- \fn COND_EXPR::inverse
- 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.
- */
- /* Returns the string that represents the procedure call of tproc (ie. with
- * actual parameters) */
- QString Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
- {
- //string condExp;
- QString ostr;
- ostr+=tproc->name+" (";
- for(const STKSYM &sym : args)
- {
- if(sym.actual)
- ostr += sym.actual->walkCondExpr(this, numLoc);
- else
- ostr += "";
- if((&sym)!=&(args.back()))
- ostr += ", ";
- }
- ostr += ")";
- return ostr;
- }
- /* Displays the output of a HLI_JCOND icode. */
- QString writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
- {
- if(h.opcode==HLI_INVALID)
- {
- return "if (*HLI_INVALID*) {\n";
- }
- assert(h.expr());
- Expr *inverted=h.expr()->inverse();
- //inverseCondOp (&h.exp);
- QString inverted_form = inverted->walkCondExpr (pProc, numLoc);
- delete inverted;
- return QString("if %1 {\n").arg(inverted_form);
- }
- /* 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. */
- QString writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
- {
- QString _form;
- if(h.expr()==nullptr)
- _form = "( *failed condition recovery* )";
- else
- _form = h.expr()->walkCondExpr (pProc, numLoc);
- return QString("if %1 {\n").arg(_form);
- }
- QString AssignType::writeOut(Function *pProc, int *numLoc) const
- {
- return QString("%1 = %2;\n")
- .arg(m_lhs->walkCondExpr (pProc, numLoc))
- .arg(rhs->walkCondExpr (pProc, numLoc));
- }
- QString CallType::writeOut(Function *pProc, int *numLoc) const
- {
- return pProc->writeCall (proc, *args, numLoc) + ";\n";
- }
- QString ExpType::writeOut(Function *pProc, int *numLoc) const
- {
- if(v==nullptr)
- return "";
- return v->walkCondExpr (pProc, numLoc);
- }
- void HLTYPE::set(Expr *l, Expr *r)
- {
- assert(l);
- assert(r);
- opcode = HLI_ASSIGN;
- //assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
- assert(dynamic_cast<UnaryOperator *>(l));
- asgn.m_lhs=l;
- asgn.rhs=r;
- }
- /* 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. */
- QString HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
- {
- const HlTypeSupport *p = get();
- switch (opcode)
- {
- case HLI_ASSIGN:
- return p->writeOut(pProc,numLoc);
- case HLI_CALL:
- return p->writeOut(pProc,numLoc);
- case HLI_RET:
- {
- QString e;
- e = p->writeOut(pProc,numLoc);
- if (not e.isEmpty())
- return QString("return (%1);\n").arg(e);
- break;
- }
- case HLI_POP:
- return QString("HLI_POP %1\n").arg(p->writeOut(pProc,numLoc));
- case HLI_PUSH:
- return QString("HLI_PUSH %1\n").arg(p->writeOut(pProc,numLoc));
- case HLI_JCOND: //Handled elsewhere
- break;
- default:
- qCritical() << " HLTYPE::write1HlIcode - Unhandled opcode" << opcode;
- }
- return "";
- }
- //TODO: replace all "< (INDEX_BX_SI-1)" with machine_x86::lastReg
- //TODO: replace all >= INDEX_BX_SI with machine_x86::isRegExpression
- /* Writes the registers/stack variables that are used and defined by this
- * instruction. */
- void ICODE::writeDU()
- {
- int my_idx = loc_ip;
- {
- QString ostr_contents;
- {
- QTextStream ostr(&ostr_contents);
- Machine_X86::writeRegVector(ostr,du.def);
- }
- if (not ostr_contents.isEmpty())
- qDebug() << QString("Def (reg) = %1\n").arg(ostr_contents);
- }
- {
- QString ostr_contents;
- {
- QTextStream ostr(&ostr_contents);
- Machine_X86::writeRegVector(ostr,du.use);
- }
- if (not ostr_contents.isEmpty())
- qDebug() << QString("Use (reg) = %1\n").arg(ostr_contents);
- }
- /* Print du1 chain */
- printf ("# regs defined = %d\n", du1.getNumRegsDef());
- for (int i = 0; i < MAX_REGS_DEF; i++)
- {
- if (not du1.used(i))
- continue;
- printf ("%d: du1[%d][] = ", my_idx, i);
- for(auto j : du1.idx[i].uses)
- {
- printf ("%d ", j->loc_ip);
- }
- printf ("\n");
- }
- /* For HLI_CALL, print # parameter bytes */
- if (hl()->opcode == HLI_CALL)
- printf ("# param bytes = %d\n", hl()->call.args->cb);
- printf ("\n");
- }
|