/db/statement.cpp
C++ | 5122 lines | 3885 code | 366 blank | 871 comment | 1381 complexity | 92b892dc0f15b915633bc027ee5d4e2a MD5 | raw file
Possible License(s): BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (C) 2002-2006, Trent Waddington and Mike Van Emmerik
- *
- * See the file "LICENSE.TERMS" for information on usage and
- * redistribution of this file, and for a DISCLAIMER OF ALL
- * WARRANTIES.
- *
- */
- /*==============================================================================
- * FILE: statement.cpp
- * OVERVIEW: Implementation of the Statement and related classes.
- * (Was dataflow.cpp a long time ago)
- *============================================================================*/
- /*
- * $Revision: 1.234 $ // 1.148.2.38
- * 03 Jul 02 - Trent: Created
- * 25 Jul 03 - Mike: dataflow.cpp, hrtl.cpp -> statement.cpp
- */
- /*==============================================================================
- * Dependencies.
- *============================================================================*/
- #include <assert.h>
- #include <iomanip> // For setfill etc
- #include <sstream>
- #include <algorithm>
- #include "statement.h"
- #include "exp.h"
- #include "cfg.h"
- #include "proc.h"
- #include "prog.h"
- #include "boomerang.h"
- #include "rtl.h" // For debugging code
- #include "util.h"
- #include "signature.h"
- #include "visitor.h"
- #include "dataflow.h"
- #include "log.h"
- #include <string.h>
- extern char debug_buffer[]; // For prints functions
- #if defined(_MSC_VER) && _MSC_VER < 1310 // Ugh - MSC 7.0 doesn't have advance
- #define my_advance(aa, n) \
- for (int zz = 0; zz < n; zz++) \
- aa++;
- #else
- #define my_advance(aa, n) \
- advance(aa, n);
- #endif
- void Statement::setProc(UserProc *p)
- {
- proc = p;
- LocationSet exps;
- addUsedLocs(exps);
- LocationSet defs;
- getDefinitions(defs);
- exps.makeUnion(defs);
- LocationSet::iterator ll;
- for (ll = exps.begin(); ll != exps.end(); ll++) {
- Location *l = dynamic_cast<Location*>(*ll);
- if (l) {
- l->setProc(p);
- }
- }
- }
- Exp *Statement::getExpAtLex(unsigned int begin, unsigned int end)
- {
- return NULL;
- }
- bool Statement::mayAlias(Exp *e1, Exp *e2, int size) {
- if (*e1 == *e2) return true;
- // Pass the expressions both ways. Saves checking things like m[exp] vs m[exp+K] and m[exp+K] vs m[exp] explicitly
- // (only need to check one of these cases)
- bool b = (calcMayAlias(e1, e2, size) && calcMayAlias(e2, e1, size));
- if (b && VERBOSE) {
- LOG << "May alias: " << e1 << " and " << e2 << " size " << size << "\n";
- }
- return b;
- }
- // returns true if e1 may alias e2
- bool Statement::calcMayAlias(Exp *e1, Exp *e2, int size) {
- // currently only considers memory aliasing..
- if (!e1->isMemOf() || !e2->isMemOf()) {
- return false;
- }
- Exp *e1a = e1->getSubExp1();
- Exp *e2a = e2->getSubExp1();
- // constant memory accesses
- if (e1a->isIntConst() && e2a->isIntConst()) {
- ADDRESS a1 = ((Const*)e1a)->getAddr();
- ADDRESS a2 = ((Const*)e2a)->getAddr();
- int diff = a1 - a2;
- if (diff < 0) diff = -diff;
- if (diff*8 >= size) return false;
- }
- // same left op constant memory accesses
- if (e1a->getArity() == 2 && e1a->getOper() == e2a->getOper() && e1a->getSubExp2()->isIntConst() &&
- e2a->getSubExp2()->isIntConst() && *e1a->getSubExp1() == *e2a->getSubExp1()) {
- int i1 = ((Const*)e1a->getSubExp2())->getInt();
- int i2 = ((Const*)e2a->getSubExp2())->getInt();
- int diff = i1 - i2;
- if (diff < 0) diff = -diff;
- if (diff*8 >= size) return false;
- }
- // [left] vs [left +/- constant] memory accesses
- if ((e2a->getOper() == opPlus || e2a->getOper() == opMinus) && *e1a == *e2a->getSubExp1() &&
- e2a->getSubExp2()->isIntConst()) {
- int i1 = 0;
- int i2 = ((Const*)e2a->getSubExp2())->getInt();
- int diff = i1 - i2;
- if (diff < 0) diff = -diff;
- if (diff*8 >= size) return false;
- }
- // Don't need [left +/- constant ] vs [left] because called twice with
- // args reversed
- return true;
- }
- RangeMap Statement::getInputRanges()
- {
- if (!isFirstStatementInBB()) {
- savedInputRanges = getPreviousStatementInBB()->getRanges();
- return savedInputRanges;
- }
- assert(pbb && pbb->getNumInEdges() <= 1);
- RangeMap input;
- if (pbb->getNumInEdges() == 0) {
- // setup input for start of procedure
- Range ra24(1, 0, 0, new Unary(opInitValueOf, Location::regOf(24)));
- Range ra25(1, 0, 0, new Unary(opInitValueOf, Location::regOf(25)));
- Range ra26(1, 0, 0, new Unary(opInitValueOf, Location::regOf(26)));
- Range ra27(1, 0, 0, new Unary(opInitValueOf, Location::regOf(27)));
- Range ra28(1, 0, 0, new Unary(opInitValueOf, Location::regOf(28)));
- Range ra29(1, 0, 0, new Unary(opInitValueOf, Location::regOf(29)));
- Range ra30(1, 0, 0, new Unary(opInitValueOf, Location::regOf(30)));
- Range ra31(1, 0, 0, new Unary(opInitValueOf, Location::regOf(31)));
- Range rpc(1, 0, 0, new Unary(opInitValueOf, new Terminal(opPC)));
- input.addRange(Location::regOf(24), ra24);
- input.addRange(Location::regOf(25), ra25);
- input.addRange(Location::regOf(26), ra26);
- input.addRange(Location::regOf(27), ra27);
- input.addRange(Location::regOf(28), ra28);
- input.addRange(Location::regOf(29), ra29);
- input.addRange(Location::regOf(30), ra30);
- input.addRange(Location::regOf(31), ra31);
- input.addRange(new Terminal(opPC), rpc);
- } else {
- PBB pred = pbb->getInEdges()[0];
- Statement *last = pred->getLastStmt();
- assert(last);
- if (pred->getNumOutEdges() != 2) {
- input = last->getRanges();
- } else {
- assert(pred->getNumOutEdges() == 2);
- assert(last->isBranch());
- input = ((BranchStatement*)last)->getRangesForOutEdgeTo(pbb);
- }
- }
- savedInputRanges = input;
- return input;
- }
- void Statement::updateRanges(RangeMap &output, std::list<Statement*> &execution_paths, bool notTaken)
- {
- if (!output.isSubset(notTaken ? ((BranchStatement*)this)->getRanges2Ref() : ranges)) {
- if (notTaken)
- ((BranchStatement*)this)->setRanges2(output);
- else
- ranges = output;
- if (isLastStatementInBB()) {
- if (pbb->getNumOutEdges()) {
- int arc = 0;
- if (isBranch()) {
- if (pbb->getOutEdge(0)->getLowAddr() != ((BranchStatement*)this)->getFixedDest())
- arc = 1;
- if (notTaken)
- arc ^= 1;
- }
- execution_paths.push_back(pbb->getOutEdge(arc)->getFirstStmt());
- }
- } else
- execution_paths.push_back(getNextStatementInBB());
- }
- }
- void Statement::rangeAnalysis(std::list<Statement*> &execution_paths)
- {
- RangeMap output = getInputRanges();
- updateRanges(output, execution_paths);
- }
- void Assign::rangeAnalysis(std::list<Statement*> &execution_paths)
- {
- RangeMap output = getInputRanges();
- Exp *a_lhs = lhs->clone();
- if (a_lhs->isFlags()) {
- // special hacks for flags
- assert(rhs->isFlagCall());
- Exp *a_rhs = rhs->clone();
- if (a_rhs->getSubExp2()->getSubExp1()->isMemOf())
- a_rhs->getSubExp2()->getSubExp1()->setSubExp1(
- output.substInto(a_rhs->getSubExp2()->getSubExp1()->getSubExp1()));
- if (!a_rhs->getSubExp2()->getSubExp2()->isTerminal() &&
- a_rhs->getSubExp2()->getSubExp2()->getSubExp1()->isMemOf())
- a_rhs->getSubExp2()->getSubExp2()->getSubExp1()->setSubExp1(
- output.substInto(a_rhs->getSubExp2()->getSubExp2()->getSubExp1()->getSubExp1()));
- Range ra(1, 0, 0, a_rhs);
- output.addRange(a_lhs, ra);
- } else {
- if (a_lhs->isMemOf())
- a_lhs->setSubExp1(output.substInto(a_lhs->getSubExp1()->clone()));
- Exp *a_rhs = output.substInto(rhs->clone());
- if (a_rhs->isMemOf() && a_rhs->getSubExp1()->getOper() == opInitValueOf &&
- a_rhs->getSubExp1()->getSubExp1()->isRegOfK() &&
- ((Const*)a_rhs->getSubExp1()->getSubExp1()->getSubExp1())->getInt() == 28)
- a_rhs = new Unary(opInitValueOf, new Terminal(opPC)); // nice hack
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "a_rhs is " << a_rhs << "\n";
- if (a_rhs->isMemOf() && a_rhs->getSubExp1()->isIntConst()) {
- ADDRESS c = ((Const*)a_rhs->getSubExp1())->getInt();
- if (proc->getProg()->isDynamicLinkedProcPointer(c)) {
- char *nam = (char*)proc->getProg()->GetDynamicProcName(c);
- if (nam) {
- a_rhs = new Const(nam);
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "a_rhs is a dynamic proc pointer to " << nam << "\n";
- }
- } else if (proc->getProg()->isReadOnly(c)) {
- switch(type->getSize()) {
- case 8:
- a_rhs = new Const(proc->getProg()->readNative1(c));
- break;
- case 16:
- a_rhs = new Const(proc->getProg()->readNative2(c));
- break;
- case 32:
- a_rhs = new Const(proc->getProg()->readNative4(c));
- break;
- default:
- LOG << "error: unhandled type size " << type->getSize() << " for reading native address\n";
- }
- } else
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << c << " is not dynamically linked proc pointer or in read only memory\n";
- }
- if ((a_rhs->getOper() == opPlus || a_rhs->getOper() == opMinus) &&
- a_rhs->getSubExp2()->isIntConst() && output.hasRange(a_rhs->getSubExp1())) {
- Range &r = output.getRange(a_rhs->getSubExp1());
- int c = ((Const*)a_rhs->getSubExp2())->getInt();
- if (a_rhs->getOper() == opPlus) {
- Range ra(1, r.getLowerBound() != Range::MIN ? r.getLowerBound() + c : Range::MIN,
- r.getUpperBound() != Range::MAX? r.getUpperBound() + c : Range::MAX, r.getBase());
- output.addRange(a_lhs, ra);
- } else {
- Range ra(1, r.getLowerBound() != Range::MIN ? r.getLowerBound() - c : Range::MIN,
- r.getUpperBound() != Range::MAX ? r.getUpperBound() - c : Range::MAX, r.getBase());
- output.addRange(a_lhs, ra);
- }
- } else {
- if (output.hasRange(a_rhs)) {
- output.addRange(a_lhs, output.getRange(a_rhs));
- } else {
- Exp *result;
- if (a_rhs->getMemDepth() == 0 && !a_rhs->search(new Unary(opRegOf, new Terminal(opWild)), result) &&
- !a_rhs->search(new Unary(opTemp, new Terminal(opWild)), result)) {
- if (a_rhs->isIntConst()) {
- Range ra(1, ((Const*)a_rhs)->getInt(), ((Const*)a_rhs)->getInt(), new Const(0));
- output.addRange(a_lhs, ra);
- }
- else {
- Range ra(1, 0, 0, a_rhs);
- output.addRange(a_lhs, ra);
- }
- } else {
- Range empty;
- output.addRange(a_lhs, empty);
- }
- }
- }
- }
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "added " << a_lhs << " -> " << output.getRange(a_lhs) << "\n";
- updateRanges(output, execution_paths);
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << this << "\n";
- }
- void BranchStatement::limitOutputWithCondition(RangeMap &output, Exp *e)
- {
- assert(e);
- if (output.hasRange(e->getSubExp1())) {
- Range &r = output.getRange(e->getSubExp1());
- if (e->getSubExp2()->isIntConst() && r.getBase()->isIntConst() && ((Const*)r.getBase())->getInt() == 0) {
- int c = ((Const*)e->getSubExp2())->getInt();
- switch(e->getOper()) {
- case opLess:
- case opLessUns: {
- Range ra(r.getStride(), r.getLowerBound() >= c ? c - 1 : r.getLowerBound(),
- r.getUpperBound() >= c ? c - 1 : r.getUpperBound(), r.getBase());
- output.addRange(e->getSubExp1(), ra);
- break;
- }
- case opLessEq:
- case opLessEqUns: {
- Range ra(r.getStride(), r.getLowerBound() > c ? c : r.getLowerBound(),
- r.getUpperBound() > c ? c : r.getUpperBound(), r.getBase());
- output.addRange(e->getSubExp1(), ra);
- break;
- }
- case opGtr:
- case opGtrUns: {
- Range ra(r.getStride(), r.getLowerBound() <= c ? c + 1 : r.getLowerBound(),
- r.getUpperBound() <= c ? c + 1 : r.getUpperBound(), r.getBase());
- output.addRange(e->getSubExp1(), ra);
- break;
- }
- case opGtrEq:
- case opGtrEqUns: {
- Range ra(r.getStride(), r.getLowerBound() < c ? c : r.getLowerBound(),
- r.getUpperBound() < c ? c : r.getUpperBound(), r.getBase());
- output.addRange(e->getSubExp1(), ra);
- break;
- }
- case opEquals: {
- Range ra(r.getStride(), c, c, r.getBase());
- output.addRange(e->getSubExp1(), ra);
- break;
- }
- case opNotEqual: {
- Range ra(r.getStride(), r.getLowerBound() == c ? c + 1 : r.getLowerBound(),
- r.getUpperBound() == c ? c - 1 : r.getUpperBound(), r.getBase());
- output.addRange(e->getSubExp1(), ra);
- break;
- }
- default:
- break;
- }
- }
- }
- }
- void BranchStatement::rangeAnalysis(std::list<Statement*> &execution_paths)
- {
- RangeMap output = getInputRanges();
- Exp *e = NULL;
- // try to hack up a useful expression for this branch
- OPER op = pCond->getOper();
- if (op == opLess || op == opLessEq || op == opGtr || op == opGtrEq ||
- op == opLessUns || op == opLessEqUns || op == opGtrUns || op == opGtrEqUns ||
- op == opEquals || op == opNotEqual) {
- if (pCond->getSubExp1()->isFlags() && output.hasRange(pCond->getSubExp1())) {
- Range &r = output.getRange(pCond->getSubExp1());
- if (r.getBase()->isFlagCall() &&
- r.getBase()->getSubExp2()->getOper() == opList &&
- r.getBase()->getSubExp2()->getSubExp2()->getOper() == opList) {
- e = new Binary(op, r.getBase()->getSubExp2()->getSubExp1()->clone(), r.getBase()->getSubExp2()->getSubExp2()->getSubExp1()->clone());
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "calculated condition " << e << "\n";
- }
- }
- }
- if (e)
- limitOutputWithCondition(output, e);
- updateRanges(output, execution_paths);
- output = getInputRanges();
- if (e)
- limitOutputWithCondition(output, (new Unary(opNot, e))->simplify());
- updateRanges(output, execution_paths, true);
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << this << "\n";
- }
- void JunctionStatement::rangeAnalysis(std::list<Statement*> &execution_paths)
- {
- RangeMap input;
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "unioning {\n";
- for (int i = 0; i < pbb->getNumInEdges(); i++) {
- Statement *last = pbb->getInEdges()[i]->getLastStmt();
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << " in BB: " << pbb->getInEdges()[i]->getLowAddr() << " " << last << "\n";
- if (last->isBranch()) {
- input.unionwith(((BranchStatement*)last)->getRangesForOutEdgeTo(pbb));
- } else {
- if (last->isCall()) {
- Proc *d = ((CallStatement*)last)->getDestProc();
- if (d && !d->isLib() && ((UserProc*)d)->getCFG()->findRetNode() == NULL) {
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "ignoring ranges from call to proc with no ret node\n";
- } else
- input.unionwith(last->getRanges());
- } else
- input.unionwith(last->getRanges());
- }
- }
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << "}\n";
- if (!input.isSubset(ranges)) {
- RangeMap output = input;
- if (output.hasRange(Location::regOf(28))) {
- Range &r = output.getRange(Location::regOf(28));
- if (r.getLowerBound() != r.getUpperBound() && r.getLowerBound() != Range::MIN) {
- if (VERBOSE)
- LOG << "stack height assumption violated " << r << " my bb: " << pbb->getLowAddr() << "\n";
- proc->printToLog();
- assert(false);
- }
- }
- if (isLoopJunction()) {
- output = ranges;
- output.widenwith(input);
- }
- updateRanges(output, execution_paths);
- }
- if (VERBOSE && DEBUG_RANGE_ANALYSIS)
- LOG << this << "\n";
- }
- void CallStatement::rangeAnalysis(std::list<Statement*> &execution_paths)
- {
- RangeMap output = getInputRanges();
- if (this->procDest == NULL) {
- // note this assumes the call is only to one proc.. could be bad.
- Exp *d = output.substInto(getDest()->clone());
- if (d->isIntConst() || d->isStrConst()) {
- if (d->isIntConst()) {
- ADDRESS dest = ((Const*)d)->getInt();
- procDest = proc->getProg()->setNewProc(dest);
- } else {
- procDest = proc->getProg()->getLibraryProc(((Const*)d)->getStr());
- }
- if (procDest) {
- Signature *sig = procDest->getSignature();
- pDest = d;
- arguments.clear();
- for (unsigned i = 0; i < sig->getNumParams(); i++) {
- Exp* a = sig->getParamExp(i);
- Assign* as = new Assign(new VoidType(), a->clone(), a->clone());
- as->setProc(proc);
- as->setBB(pbb);
- arguments.append(as);
- }
- signature = procDest->getSignature()->clone();
- m_isComputed = false;
- proc->undoComputedBB(this);
- proc->addCallee(procDest);
- LOG << "replaced indirect call with call to " << procDest->getName() << "\n";
- }
- }
- }
- if (output.hasRange(Location::regOf(28))) {
- Range &r = output.getRange(Location::regOf(28));
- int c = 4;
- if (procDest == NULL) {
- LOG << "using push count hack to guess number of params\n";
- Statement *prev = this->getPreviousStatementInBB();
- while(prev) {
- if (prev->isAssign() && ((Assign*)prev)->getLeft()->isMemOf() &&
- ((Assign*)prev)->getLeft()->getSubExp1()->isRegOfK() &&
- ((Const*)((Assign*)prev)->getLeft()->getSubExp1()->getSubExp1())->getInt() == 28 &&
- ((Assign*)prev)->getRight()->getOper() != opPC) {
- c += 4;
- }
- prev = prev->getPreviousStatementInBB();
- }
- } else if (procDest->getSignature()->getConvention() == CONV_PASCAL)
- c += procDest->getSignature()->getNumParams() * 4;
- else if (!strncmp(procDest->getName(), "__imp_", 6)) {
- Statement *first = ((UserProc*)procDest)->getCFG()->getEntryBB()->getFirstStmt();
- assert(first && first->isCall());
- Proc *d = ((CallStatement*)first)->getDestProc();
- if (d->getSignature()->getConvention() == CONV_PASCAL)
- c += d->getSignature()->getNumParams() * 4;
- } else if (!procDest->isLib()) {
- UserProc *p = (UserProc*)procDest;
- if (VERBOSE) {
- LOG << "== checking for number of bytes popped ==\n";
- p->printToLog();
- LOG << "== end it ==\n";
- }
- Exp *eq = p->getProven(Location::regOf(28));
- if (eq) {
- if (VERBOSE)
- LOG << "found proven " << eq << "\n";
- if (eq->getOper() == opPlus && *eq->getSubExp1() == *Location::regOf(28) &&
- eq->getSubExp2()->isIntConst()) {
- c = ((Const*)eq->getSubExp2())->getInt();
- } else
- eq = NULL;
- }
- PBB retbb = p->getCFG()->findRetNode();
- if (retbb && eq == NULL) {
- Statement *last = retbb->getLastStmt();
- assert(last);
- if (last->isReturn()) {
- last->setBB(retbb);
- last = last->getPreviousStatementInBB();
- }
- if (last == NULL) {
- // call followed by a ret, sigh
- for (int i = 0; i < retbb->getNumInEdges(); i++) {
- last = retbb->getInEdges()[i]->getLastStmt();
- if (last->isCall())
- break;
- }
- if (last->isCall()) {
- Proc *d = ((CallStatement*)last)->getDestProc();
- if (d && d->getSignature()->getConvention() == CONV_PASCAL)
- c += d->getSignature()->getNumParams() * 4;
- }
- last = NULL;
- }
- if (last && last->isAssign()) {
- //LOG << "checking last statement " << last << " for number of bytes popped\n";
- Assign *a = (Assign*)last;
- assert(a->getLeft()->isRegOfK() && ((Const*)a->getLeft()->getSubExp1())->getInt() == 28);
- Exp *t = a->getRight()->clone()->simplifyArith();
- assert(t->getOper() == opPlus &&
- t->getSubExp1()->isRegOfK() &&
- ((Const*)t->getSubExp1()->getSubExp1())->getInt() == 28);
- assert(t->getSubExp2()->isIntConst());
- c = ((Const*)t->getSubExp2())->getInt();
- }
- }
- }
- Range ra(r.getStride(), r.getLowerBound() == Range::MIN ? Range::MIN : r.getLowerBound() + c,
- r.getUpperBound() == Range::MAX ? Range::MAX : r.getUpperBound() + c, r.getBase());
- output.addRange(Location::regOf(28), ra);
- }
- updateRanges(output, execution_paths);
- }
- bool JunctionStatement::isLoopJunction()
- {
- for (int i = 0; i < pbb->getNumInEdges(); i++)
- if (pbb->isBackEdge(i))
- return true;
- return false;
- }
- RangeMap &BranchStatement::getRangesForOutEdgeTo(PBB out)
- {
- assert(this->getFixedDest() != NO_ADDRESS);
- if (out->getLowAddr() == this->getFixedDest())
- return ranges;
- return ranges2;
- }
- bool Statement::isFirstStatementInBB()
- {
- assert(pbb);
- assert(pbb->getRTLs());
- assert(pbb->getRTLs()->size());
- assert(pbb->getRTLs()->front());
- assert(pbb->getRTLs()->front()->getList().size());
- return this == pbb->getRTLs()->front()->getList().front();
- }
- bool Statement::isLastStatementInBB()
- {
- assert(pbb);
- return this == pbb->getLastStmt();
- }
- Statement* Statement::getPreviousStatementInBB()
- {
- assert(pbb);
- std::list<RTL*> *rtls = pbb->getRTLs();
- assert(rtls);
- Statement *previous = NULL;
- for (std::list<RTL*>::iterator rit = rtls->begin(); rit != rtls->end(); rit++) {
- RTL *rtl = *rit;
- for (RTL::iterator it = rtl->getList().begin(); it != rtl->getList().end(); it++) {
- if (*it == this)
- return previous;
- previous = *it;
- }
- }
- return NULL;
- }
- Statement *Statement::getNextStatementInBB()
- {
- assert(pbb);
- std::list<RTL*> *rtls = pbb->getRTLs();
- assert(rtls);
- bool wantNext = false;
- for (std::list<RTL*>::iterator rit = rtls->begin(); rit != rtls->end(); rit++) {
- RTL *rtl = *rit;
- for (RTL::iterator it = rtl->getList().begin(); it != rtl->getList().end(); it++) {
- if (wantNext)
- return *it;
- if (*it == this)
- wantNext = true;
- }
- }
- return NULL;
- }
- /*==============================================================================
- * FUNCTION: operator<<
- * OVERVIEW: Output operator for Statement*
- * Just makes it easier to use e.g. std::cerr << myStmtStar
- * PARAMETERS: os: output stream to send to
- * p: ptr to Statement to print to the stream
- * RETURNS: copy of os (for concatenation)
- *============================================================================*/
- std::ostream& operator<<(std::ostream& os, Statement* s) {
- if (s == NULL) {os << "NULL "; return os;}
- s->print(os);
- return os;
- }
- bool Statement::isFlagAssgn() {
- if (kind != STMT_ASSIGN)
- return false;
- OPER op = ((Assign*)this)->getRight()->getOper();
- return (op == opFlagCall);
- }
- char* Statement::prints() {
- std::ostringstream ost;
- print(ost);
- strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
- debug_buffer[DEBUG_BUFSIZE-1] = '\0';
- return debug_buffer;
- }
- // This version prints much better in gdb
- void Statement::dump() {
- print(std::cerr);
- std::cerr << "\n";
- }
- /* This function is designed to find basic flag calls, plus in addition two variations seen with Pentium FP code.
- These variations involve ANDing and/or XORing with constants. So it should return true for these values of e:
- ADDFLAGS(...)
- SETFFLAGS(...) & 0x45
- (SETFFLAGS(...) & 0x45) ^ 0x40
- FIXME: this may not be needed any more...
- */
- bool hasSetFlags(Exp* e) {
- if (e->isFlagCall()) return true;
- OPER op = e->getOper();
- if (op != opBitAnd && op != opBitXor) return false;
- Exp* left = ((Binary*)e)->getSubExp1();
- Exp* right = ((Binary*)e)->getSubExp2();
- if (!right->isIntConst()) return false;
- if (left->isFlagCall()) {
- std::cerr << "hasSetFlags returns true with " << e << "\n";
- return true;
- }
- op = left->getOper();
- if (op != opBitAnd && op != opBitXor) return false;
- right = ((Binary*)left)->getSubExp2();
- left = ((Binary*)left)->getSubExp1();
- if (!right->isIntConst()) return false;
- bool ret = left->isFlagCall();
- if (ret)
- std::cerr << "hasSetFlags returns true with " << e << "\n";
- return ret;
- }
- // Return true if can propagate to Exp* e (must be a RefExp to return true)
- // Note: does not consider whether e is able to be renamed (from a memory Primitive point of view), only if the
- // definition can be propagated TO this stmt
- // Note: static member function
- bool Statement::canPropagateToExp(Exp*e) {
- if (!e->isSubscript()) return false;
- if (((RefExp*)e)->isImplicitDef())
- // Can't propagate statement "-" or "0" (implicit assignments)
- return false;
- Statement* def = ((RefExp*)e)->getDef();
- // if (def == this)
- // Don't propagate to self! Can happen with %pc's (?!)
- // return false;
- if (def->isNullStatement())
- // Don't propagate a null statement! Can happen with %pc's (would have no effect, and would infinitely loop)
- return false;
- if (!def->isAssign()) return false; // Only propagate ordinary assignments (so far)
- Assign* adef = (Assign*)def;
- if (adef->getType()->isArray()) {
- // Assigning to an array, don't propagate (Could be alias problems?)
- return false;
- }
- return true;
- }
- // Return true if any change; set convert if an indirect call statement is converted to direct (else unchanged)
- // destCounts is a set of maps from location to number of times it is used this proc
- // usedByDomPhi is a set of subscripted locations used in phi statements
- static int progress = 0;
- bool Statement::propagateTo(bool& convert, std::map<Exp*, int, lessExpStar>* destCounts /* = NULL */,
- LocationSet* usedByDomPhi /* = NULL */, bool force /* = false */) {
- if (++progress > 1000) {
- std::cerr << 'p' << std::flush;
- progress = 0;
- }
- bool change;
- int changes = 0;
- // int sp = proc->getSignature()->getStackRegister(proc->getProg());
- // Exp* regSp = Location::regOf(sp);
- int propMaxDepth = Boomerang::get()->propMaxDepth;
- do {
- LocationSet exps;
- addUsedLocs(exps, true); // True to also add uses from collectors. For example, want to propagate into
- // the reaching definitions of calls. Third parameter defaults to false, to
- // find all locations, not just those inside m[...]
- LocationSet::iterator ll;
- change = false; // True if changed this iteration of the do/while loop
- // Example: m[r24{10}] := r25{20} + m[r26{30}]
- // exps has r24{10}, r25{30}, m[r26{30}], r26{30}
- for (ll = exps.begin(); ll != exps.end(); ll++) {
- Exp* e = *ll;
- if (!canPropagateToExp(e))
- continue;
- Assign* def = (Assign*)((RefExp*)e)->getDef();
- Exp* rhs = def->getRight();
- // If force is true, ignore the fact that a memof should not be propagated (for switch analysis)
- if (rhs->containsBadMemof(proc) && !(force && rhs->isMemOf()))
- // Must never propagate unsubscripted memofs, or memofs that don't yet have symbols. You could be
- // propagating past a definition, thereby invalidating the IR
- continue;
- Exp* lhs = def->getLeft();
- if (EXPERIMENTAL) {
- #if 0
- // This is the old "don't propagate x=f(x)" heuristic. Hopefully it will work better now that we always
- // propagate into memofs etc. However, it might need a "and we're inside the right kind of loop"
- // condition
- LocationSet used;
- def->addUsedLocs(used);
- RefExp left(def->getLeft(), (Statement*)-1);
- RefExp *right = dynamic_cast<RefExp*>(def->getRight());
- // Beware of x := x{something else} (because we do want to do copy propagation)
- if (used.exists(&left) && !(right && *right->getSubExp1() == *left.getSubExp1()))
- // We have something like eax = eax + 1
- continue;
- #else
- // This is Mike's experimental propagation limiting heuristic. At present, it is:
- // for each component of def->rhs
- // test if the base expression is in the set usedByDomPhi
- // if so, check if this statement OW overwrites a parameter (like ebx = ebx-1)
- // if so, check for propagating past this overwriting statement, i.e.
- // domNum(def) <= domNum(OW) && dimNum(OW) < domNum(def)
- // if so, don't propagate (heuristic takes effect)
- if (usedByDomPhi) {
- LocationSet rhsComps;
- rhs->addUsedLocs(rhsComps);
- LocationSet::iterator rcit;
- bool doNotPropagate = false;
- for (rcit = rhsComps.begin(); rcit != rhsComps.end(); ++rcit) {
- if (!(*rcit)->isSubscript()) continue; // Sometimes %pc sneaks in
- Exp* rhsBase = ((RefExp*)*rcit)->getSubExp1();
- // We don't know the statement number for the one definition in usedInDomPhi that might exist,
- // so we use findNS()
- Exp* OW = usedByDomPhi->findNS(rhsBase);
- if (OW) {
- Statement* OWdef = ((RefExp*)OW)->getDef();
- if (!OWdef->isAssign()) continue;
- Exp* lhsOWdef = ((Assign*)OWdef)->getLeft();
- LocationSet OWcomps;
- def->addUsedLocs(OWcomps);
- LocationSet::iterator cc;
- bool isOverwrite = false;
- for (cc = OWcomps.begin(); cc != OWcomps.end(); ++cc) {
- if (**cc *= *lhsOWdef) {
- isOverwrite = true;
- break;
- }
- }
- if (isOverwrite) {
- // Now check for propagating a component past OWdef
- if (def->getDomNumber() <= OWdef->getDomNumber() &&
- OWdef->getDomNumber() < dominanceNum)
- // The heuristic kicks in
- doNotPropagate = true;
- break;
- }
- if (OW) std::cerr << "Ow is " << OW << "\n";
- }
- }
- if (doNotPropagate) {
- if (VERBOSE)
- LOG << "% propagation of " << def->getNumber() << " into " << number << " prevented by the "
- "propagate past overwriting statement in loop heuristic\n";
- continue;
- }
- }
- }
- #endif
- // Check if the -l flag (propMaxDepth) prevents this propagation
- if (destCounts && !lhs->isFlags()) { // Always propagate to %flags
- std::map<Exp*, int, lessExpStar>::iterator ff = destCounts->find(e);
- if (ff != destCounts->end() && ff->second > 1 && rhs->getComplexityDepth(proc) >= propMaxDepth) {
- if (!def->getRight()->containsFlags()) {
- // This propagation is prevented by the -l limit
- continue;
- }
- }
- }
- change |= doPropagateTo(e, def, convert);
- }
- } while (change && ++changes < 10);
- // Simplify is very costly, especially for calls. I hope that doing one simplify at the end will not affect any
- // result...
- simplify();
- return changes > 0; // Note: change is only for the last time around the do/while loop
- }
- // Experimental: may want to propagate flags first, without tests about complexity or the propagation limiting heuristic
- bool Statement::propagateFlagsTo() {
- bool change = false, convert;
- int changes = 0;
- do {
- LocationSet exps;
- addUsedLocs(exps, true);
- LocationSet::iterator ll;
- for (ll = exps.begin(); ll != exps.end(); ll++) {
- Exp* e = *ll;
- if (!e->isSubscript()) continue; // e.g. %pc
- Assign* def = (Assign*)((RefExp*)e)->getDef();
- if (def == NULL || !def->isAssign()) continue;
- Exp* base = ((RefExp*)e)->getSubExp1();
- if (base->isFlags() || base->isMainFlag()) {
- change |= doPropagateTo(e, def, convert);
- }
- }
- } while (change && ++changes < 10);
- simplify();
- return change;
- }
- // Parameter convert is set true if an indirect call is converted to direct
- // Return true if a change made
- // Note: this procedure does not control what part of this statement is propagated to
- // Propagate to e from definition statement def.
- // Set convert to true if convert a call from indirect to direct.
- bool Statement::doPropagateTo(Exp* e, Assign* def, bool& convert) {
- // Respect the -p N switch
- if (Boomerang::get()->numToPropagate >= 0) {
- if (Boomerang::get()->numToPropagate == 0) return false;
- Boomerang::get()->numToPropagate--;
- }
- if (VERBOSE)
- LOG << "propagating " << def << "\n" << " into " << this << "\n";
- bool change = replaceRef(e, def, convert);
-
- if (VERBOSE) {
- LOG << " result " << this << "\n\n";
- }
- return change;
- }
- // replace a use of def->getLeft() by def->getRight() in this statement
- // return true if change
- bool Statement::replaceRef(Exp* e, Assign *def, bool& convert) {
- Exp* rhs = def->getRight();
- assert(rhs);
- Exp* base = ((RefExp*)e)->getSubExp1();
- // Could be propagating %flags into %CF
- Exp* lhs = def->getLeft();
- if (base->getOper() == opCF && lhs->isFlags()) {
- if (!rhs->isFlagCall())
- return false;
- char* str = ((Const*)((Binary*)rhs)->getSubExp1())->getStr();
- if (strncmp("SUBFLAGS", str, 8) == 0) {
- /* When the carry flag is used bare, and was defined in a subtract of the form lhs - rhs, then CF has
- the value (lhs <u rhs). lhs and rhs are the first and second parameters of the flagcall.
- Note: the flagcall is a binary, with a Const (the name) and a list of expressions:
- defRhs
- / \
- Const opList
- "SUBFLAGS" / \
- P1 opList
- / \
- P2 opList
- / \
- P3 opNil
- */
- Exp* relExp = new Binary(opLessUns,
- ((Binary*)rhs)->getSubExp2()->getSubExp1(),
- ((Binary*)rhs)->getSubExp2()->getSubExp2()->getSubExp1());
- searchAndReplace(new RefExp(new Terminal(opCF), def), relExp, true);
- return true;
- }
- }
- // need something similar for %ZF
- if (base->getOper() == opZF && lhs->isFlags()) {
- if (!rhs->isFlagCall())
- return false;
- char* str = ((Const*)((Binary*)rhs)->getSubExp1())->getStr();
- if (strncmp("SUBFLAGS", str, 8) == 0) {
- // for zf we're only interested in if the result part of the subflags is equal to zero
- Exp* relExp = new Binary(opEquals,
- ((Binary*)rhs)->getSubExp2()->getSubExp2()->getSubExp2()->getSubExp1(),
- new Const(0));
- searchAndReplace(new RefExp(new Terminal(opZF), def), relExp, true);
- return true;
- }
- }
- // do the replacement
- //bool convert = doReplaceRef(re, rhs);
- bool ret = searchAndReplace(e, rhs, true); // Last parameter true to change collectors
- // assert(ret);
- if (ret && isCall()) {
- convert |= ((CallStatement*)this)->convertToDirect();
- }
- return ret;
- }
- bool Statement::isNullStatement() {
- if (kind != STMT_ASSIGN) return false;
- Exp* right = ((Assign*)this)->getRight();
- if (right->isSubscript()) {
- // Must refer to self to be null
- return this == ((RefExp*)right)->getDef();
- }
- else
- // Null if left == right
- return *((Assign*)this)->getLeft() == *right;
- }
- bool Statement::isFpush() {
- if (kind != STMT_ASSIGN) return false;
- return ((Assign*)this)->getRight()->getOper() == opFpush;
- }
- bool Statement::isFpop() {
- if (kind != STMT_ASSIGN) return false;
- return ((Assign*)this)->getRight()->getOper() == opFpop;
- }
- /*
- * This code was in hrtl.cpp
- * Classes derived from Statement
- */
- #if defined(_MSC_VER) && _MSC_VER <= 1200
- #pragma warning(disable:4786)
- #endif
- /******************************************************************************
- * GotoStatement methods
- *****************************************************************************/
- /*==============================================================================
- * FUNCTION: GotoStatement::GotoStatement
- * OVERVIEW: Constructor.
- * PARAMETERS: listStmt: a list of Statements (not the same as an RTL)
- * to serve as the initial list of statements
- * RETURNS: N/a
- *============================================================================*/
- GotoStatement::GotoStatement()
- : pDest(NULL), m_isComputed(false) {
- kind = STMT_GOTO;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::GotoStatement
- * OVERVIEW: Construct a jump to a fixed address
- * PARAMETERS: uDest: native address of destination
- * RETURNS: N/a
- *============================================================================*/
- GotoStatement::GotoStatement(ADDRESS uDest) : m_isComputed(false) {
- kind = STMT_GOTO;
- pDest = new Const(uDest);
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::~GotoStatement
- * OVERVIEW: Destructor
- * PARAMETERS: None
- * RETURNS: N/a
- *============================================================================*/
- GotoStatement::~GotoStatement() {
- if (pDest) ;//delete pDest;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::getFixedDest
- * OVERVIEW: Get the fixed destination of this CTI. Assumes destination
- * simplication has already been done so that a fixed dest will
- * be of the Exp form:
- * opIntConst dest
- * PARAMETERS: <none>
- * RETURNS: Fixed dest or NO_ADDRESS if there isn't one
- *============================================================================*/
- ADDRESS GotoStatement::getFixedDest() {
- if (pDest->getOper() != opIntConst) return NO_ADDRESS;
- return ((Const*)pDest)->getAddr();
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::setDest
- * OVERVIEW: Set the destination of this jump to be a given expression.
- * PARAMETERS: addr - the new fixed address
- * RETURNS: Nothing
- *============================================================================*/
- void GotoStatement::setDest(Exp* pd) {
- pDest = pd;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::setDest
- * OVERVIEW: Set the destination of this jump to be a given fixed address.
- * PARAMETERS: addr - the new fixed address
- * RETURNS: <nothing>
- *============================================================================*/
- void GotoStatement::setDest(ADDRESS addr) {
- // This fails in FrontSparcTest, do you really want it to Mike? -trent
- // assert(addr >= prog.limitTextLow && addr < prog.limitTextHigh);
- // Delete the old destination if there is one
- if (pDest != NULL)
- ;//delete pDest;
- pDest = new Const(addr);
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::getDest
- * OVERVIEW: Returns the destination of this CTI.
- * PARAMETERS: None
- * RETURNS: Pointer to the SS representing the dest of this jump
- *============================================================================*/
- Exp* GotoStatement::getDest() {
- return pDest;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::adjustFixedDest
- * OVERVIEW: Adjust the destination of this CTI by a given amount. Causes
- * an error is this destination is not a fixed destination
- * (i.e. a constant offset).
- * PARAMETERS: delta - the amount to add to the destination (can be
- * negative)
- * RETURNS: <nothing>
- *============================================================================*/
- void GotoStatement::adjustFixedDest(int delta) {
- // Ensure that the destination is fixed.
- if (pDest == 0 || pDest->getOper() != opIntConst)
- LOG << "Can't adjust destination of non-static CTI\n";
- ADDRESS dest = ((Const*)pDest)->getAddr();
- ((Const*)pDest)->setAddr(dest + delta);
- }
- bool GotoStatement::search(Exp* search, Exp*& result) {
- result = NULL;
- if (pDest)
- return pDest->search(search, result);
- return false;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::searchAndReplace
- * OVERVIEW: Replace all instances of search with replace.
- * PARAMETERS: search - a location to search for
- * replace - the expression with which to replace it
- * cc - ignored
- * RETURNS: True if any change
- *============================================================================*/
- bool GotoStatement::searchAndReplace(Exp* search, Exp* replace, bool cc) {
- bool change = false;
- if (pDest) {
- pDest = pDest->searchReplaceAll(search, replace, change);
- }
- return change;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::searchAll
- * OVERVIEW: Find all instances of the search expression
- * PARAMETERS: search - a location to search for
- * result - a list which will have any matching exprs
- * appended to it
- * RETURNS: true if there were any matches
- *============================================================================*/
- bool GotoStatement::searchAll(Exp* search, std::list<Exp*> &result) {
- if (pDest) return pDest->searchAll(search, result);
- return false;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::print
- * OVERVIEW: Display a text reprentation of this RTL to the given stream
- * NOTE: Usually called from RTL::print, in which case the first 9
- * chars of the print have already been output to os
- * PARAMETERS: os: stream to write to
- * RETURNS: Nothing
- *============================================================================*/
- void GotoStatement::print(std::ostream& os, bool html) {
- os << std::setw(4) << std::dec << number << " ";
- if (html) {
- os << "</td><td>";
- os << "<a name=\"stmt" << std::dec << number << "\">";
- }
- os << "GOTO ";
- if (pDest == NULL)
- os << "*no dest*";
- else if (pDest->getOper() != opIntConst)
- pDest->print(os);
- else
- os << "0x" << std::hex << getFixedDest();
- if (html)
- os << "</a></td>";
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::setIsComputed
- * OVERVIEW: Sets the fact that this call is computed.
- * NOTE: This should really be removed, once CaseStatement and
- * HLNwayCall are implemented properly
- * PARAMETERS: <none>
- * RETURNS: <nothing>
- *============================================================================*/
- void GotoStatement::setIsComputed(bool b) {
- m_isComputed = b;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::isComputed
- * OVERVIEW: Returns whether or not this call is computed.
- * NOTE: This should really be removed, once CaseStatement and HLNwayCall
- * are implemented properly
- * PARAMETERS: <none>
- * RETURNS: this call is computed
- *============================================================================*/
- bool GotoStatement::isComputed() {
- return m_isComputed;
- }
- /*==============================================================================
- * FUNCTION: GotoStatement::clone
- * OVERVIEW: Deep copy clone
- * PARAMETERS: <none>
- * RETURNS: Pointer to a new Statement, a clone of this GotoStatement
- *============================================================================*/
- Statement* GotoStatement::clone() {
- GotoStatement* ret = new GotoStatement();
- ret->pDest = pDest->clone();
- ret->m_isComputed = m_isComputed;
- // Statement members
- ret->pbb = pbb;
- ret->proc = proc;
- ret->number = number;
- return ret;
- }
- // visit this Statement in the RTL
- bool GotoStatement::accept(StmtVisitor* visitor) {
- return visitor->visit(this);
- }
- void GotoStatement::generateCode(HLLCode *hll, BasicBlock *pbb, int indLevel) {
- // dont generate any code for jumps, they will be handled by the BB
- }
- void GotoStatement::simplify() {
- if (isComputed()) {
- pDest = pDest->simplifyArith();
- pDest = pDest->simplify();
- }
- }
- /**********************************
- * BranchStatement methods
- **********************************/
- /*==============================================================================
- * FUNCTION: BranchStatement::BranchStatement
- * OVERVIEW: Constructor.
- * PARAMETERS: None
- * RETURNS: N/a
- *============================================================================*/
- BranchStatement::BranchStatement() : jtCond((BRANCH_TYPE)0), pCond(NULL), bFloat(false), size(0) {
- kind = STMT_BRANCH;
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::~BranchStatement
- * OVERVIEW: Destructor
- * PARAMETERS: None
- * RETURNS: N/a
- *============================================================================*/
- BranchStatement::~BranchStatement() {
- if (pCond)
- ;//delete pCond;
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::setCondType
- * OVERVIEW: Sets the BRANCH_TYPE of this jcond as well as the flag
- * indicating whether or not the floating point condition codes
- * are used.
- * PARAMETERS: cond - the BRANCH_TYPE
- * usesFloat - this condional jump checks the floating point
- * condition codes
- * RETURNS: a semantic string
- *============================================================================*/
- void BranchStatement::setCondType(BRANCH_TYPE cond, bool usesFloat /*= false*/) {
- jtCond = cond;
- bFloat = usesFloat;
- // set pCond to a high level representation of this type
- Exp* p = NULL;
- switch(cond) {
- case BRANCH_JE:
- p = new Binary(opEquals, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JNE:
- p = new Binary(opNotEqual, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JSL:
- p = new Binary(opLess, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JSLE:
- p = new Binary(opLessEq, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JSGE:
- p = new Binary(opGtrEq, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JSG:
- p = new Binary(opGtr, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JUL:
- p = new Binary(opLessUns, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JULE:
- p = new Binary(opLessEqUns, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JUGE:
- p = new Binary(opGtrEqUns, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JUG:
- p = new Binary(opGtrUns, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JMI:
- p = new Binary(opLess, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JPOS:
- p = new Binary(opGtr, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JOF:
- p = new Binary(opLessUns, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JNOF:
- p = new Binary(opGtrUns, new Terminal(opFlags), new Const(0));
- break;
- case BRANCH_JPAR:
- // Can't handle this properly here; leave an impossible expression involving %flags so propagation will
- // still happen, and we can recognise this later in condToRelational()
- // Update: these expressions seem to get ignored ???
- p = new Binary(opEquals, new Terminal(opFlags), new Const(999));
- break;
- }
- // this is such a hack.. preferably we should actually recognise SUBFLAGS32(..,..,..) > 0 instead of just
- // SUBFLAGS32(..,..,..) but I'll leave this in here for the moment as it actually works.
- if (!Boomerang::get()->noDecompile)
- p = new Terminal(usesFloat ? opFflags : opFlags);
- assert(p);
- setCondExpr(p);
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::makeSigned
- * OVERVIEW: Change this from an unsigned to a signed branch
- * PARAMETERS: <none>
- * RETURNS: <nothing>
- *============================================================================*/
- void BranchStatement::makeSigned() {
- // Make this into a signed branch
- switch (jtCond)
- {
- case BRANCH_JUL : jtCond = BRANCH_JSL; break;
- case BRANCH_JULE: jtCond = BRANCH_JSLE; break;
- case BRANCH_JUGE: jtCond = BRANCH_JSGE; break;
- case BRANCH_JUG : jtCond = BRANCH_JSG; break;
- default:
- // Do nothing for other cases
- break;
- }
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::getCondExpr
- * OVERVIEW: Return the SemStr expression containing the HL condition.
- * PARAMETERS: <none>
- * RETURNS: ptr to an expression
- *============================================================================*/
- Exp* BranchStatement::getCondExpr() {
- return pCond;
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::setCondExpr
- * OVERVIEW: Set the SemStr expression containing the HL condition.
- * PARAMETERS: Pointer to Exp to set
- * RETURNS: <nothing>
- *============================================================================*/
- void BranchStatement::setCondExpr(Exp* e) {
- if (pCond) ;//delete pCond;
- pCond = e;
- }
- PBB BranchStatement::getFallBB()
- {
- ADDRESS a = getFixedDest();
- if (a == NO_ADDRESS)
- return NULL;
- if (pbb == NULL)
- return NULL;
- if (pbb->getNumOutEdges() != 2)
- return NULL;
- if (pbb->getOutEdge(0)->getLowAddr() == a)
- return pbb->getOutEdge(1);
- return pbb->getOutEdge(0);
- }
- // not that if you set the taken BB or fixed dest first, you will not be able to set the fall BB
- void BranchStatement::setFallBB(PBB bb)
- {
- ADDRESS a = getFixedDest();
- if (a == NO_ADDRESS)
- return;
- if (pbb == NULL)
- return;
- if (pbb->getNumOutEdges() != 2)
- return;
- if (pbb->getOutEdge(0)->getLowAddr() == a) {
- pbb->getOutEdge(1)->deleteInEdge(pbb);
- pbb->setOutEdge(1, bb);
- bb->addInEdge(pbb);
- } else {
- pbb->getOutEdge(0)->deleteInEdge(pbb);
- pbb->setOutEdge(0, bb);
- bb->addInEdge(pbb);
- }
- }
- PBB BranchStatement::getTakenBB()
- {
- ADDRESS a = getFixedDest();
- if (a == NO_ADDRESS)
- return NULL;
- if (pbb == NULL)
- return NULL;
- if (pbb->getNumOutEdges() != 2)
- return NULL;
- if (pbb->getOutEdge(0)->getLowAddr() == a)
- return pbb->getOutEdge(0);
- return pbb->getOutEdge(1);
- }
- void BranchStatement::setTakenBB(PBB bb)
- {
- ADDRESS a = getFixedDest();
- if (a == NO_ADDRESS)
- return;
- if (pbb == NULL)
- return;
- if (pbb->getNumOutEdges() != 2)
- return;
- if (pbb->getOutEdge(0)->getLowAddr() == a) {
- pbb->getOutEdge(0)->deleteInEdge(pbb);
- pbb->setOutEdge(0, bb);
- bb->addInEdge(pbb);
- } else {
- pbb->getOutEdge(1)->deleteInEdge(pbb);
- pbb->setOutEdge(1, bb);
- bb->addInEdge(pbb);
- }
- }
- bool BranchStatement::search(Exp* search, Exp*& result) {
- if (pCond) return pCond->search(search, result);
- result = NULL;
- return false;
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::searchAndReplace
- * OVERVIEW: Replace all instances of search with replace.
- * PARAMETERS: search - a location to search for
- * replace - the expression with which to replace it
- * cc - ignored
- * RETURNS: True if any change
- *============================================================================*/
- bool BranchStatement::searchAndReplace(Exp* search, Exp* replace, bool cc) {
- GotoStatement::searchAndReplace(search, replace, cc);
- bool change = false;
- if (pCond)
- pCond = pCond->searchReplaceAll(search, replace, change);
- return change;
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::searchAll
- * OVERVIEW: Find all instances of the search expression
- * PARAMETERS: search - a location to search for
- * result - a list which will have any matching exprs
- * appended to it
- * RETURNS: true if there were any matches
- *============================================================================*/
- bool BranchStatement::searchAll(Exp* search, std::list<Exp*> &result) {
- if (pCond) return pCond->searchAll(search, result);
- return false;
- }
- /*==============================================================================
- * FUNCTION: BranchStatement::print
- * OVERVIEW: Write a text representation to the given stream
- * PARAMETERS: os: stream
- * RETURNS: Nothing
- *============================================================================*/
- void BranchStatement::print(std::ostream& os, bool html) {
- os << std::setw(4) << std::dec << number << " ";
- if (html) {
- os << "</td><td>";
- os << "<a name=\"stmt" << std::dec << number << "\">";
- }
- os << "BRANCH ";
- if (pDest == NULL)
- os << "*no dest*";
- else if (!pDest->isIntConst())
- os << pDest;
- else {
- // Really we'd like to display the destination label here...
- os << "0x" << std::hex << getFixedDest();
- }
- os << ", condition ";
- switch (jtCond) {
- case BRANCH_JE: os << "equals"; break;
- ca…
Large files files are truncated, but you can click here to view the full file