Exemple #1
0
void StatementList::makeIsect(StatementList &a, LocationSet &b)
{
    if (this == &a) { // *this = *this isect b
        for (auto it = a.begin(); it != a.end();) {
            assert((*it)->isAssignment());
            Assignment *as = static_cast<Assignment *>(*it);

            if (!b.contains(as->getLeft())) {
                it = m_list.erase(it);
            }
            else {
                it++;
            }
        }
    }
    else { // normal assignment
        clear();
        for (Statement *stmt : a) {
            assert(stmt->isAssignment());
            Assignment *as = static_cast<Assignment *>(stmt);

            if (b.contains(as->getLeft())) {
                append(as);
            }
        }
    }
}
void LocationSetTest::testEmpty()
{
    LocationSet set;
    QVERIFY(set.empty());

    set.insert(Location::regOf(REG_PENT_EDI));
    QVERIFY(!set.empty());
}
void LocationSetTest::testContains()
{
    LocationSet set;

    QVERIFY(!set.contains(nullptr));

    set.insert(Location::regOf(REG_PENT_ESI));
    QVERIFY(set.contains(Location::regOf(REG_PENT_ESI)));
    QVERIFY(!set.contains(Location::regOf(REG_PENT_EDI)));
}
void LocationSetTest::testInsert()
{
    LocationSet set;

    set.insert(Location::regOf(REG_PENT_ESI));
    QCOMPARE(set, LocationSet({ Location::regOf(REG_PENT_ESI) }));

    set.insert(Location::regOf(REG_PENT_ESI));
    QCOMPARE(set, LocationSet({ Location::regOf(REG_PENT_ESI) }));

    set.insert(Location::regOf(REG_PENT_EDI));
    QCOMPARE(set, LocationSet({ Location::regOf(REG_PENT_ESI), Location::regOf(REG_PENT_EDI) }));
}
Exemple #5
0
// Remove locations defined by any of the given set of statements
// Used for killing in liveness sets
void LocationSet::removeIfDefines(StatementSet& given)
{
    StatementSet::iterator it;
    for (it = given.begin(); it != given.end(); ++it)
        {
            Statement* s = (Statement*)*it;
            LocationSet defs;
            s->getDefinitions(defs);
            LocationSet::iterator dd;
            for (dd = defs.begin(); dd != defs.end(); ++dd)
                lset.erase(*dd);
        }
}
Exemple #6
0
// Substitute s into all members of the set
void LocationSet::substitute(Assign& a)
{
    Exp* lhs = a.getLeft();
    if (lhs == NULL) return;
    Exp* rhs = a.getRight();
    if (rhs == NULL) return;		// ? Will this ever happen?
    std::set<Exp*, lessExpStar>::iterator it;
    // Note: it's important not to change the pointer in the set of pointers to expressions, without removing and
    // inserting again. Otherwise, the set becomes out of order, and operations such as set comparison fail!
    // To avoid any funny behaviour when iterating the loop, we use the following two sets
    LocationSet removeSet;			// These will be removed after the loop
    LocationSet removeAndDelete;	// These will be removed then deleted
    LocationSet insertSet;			// These will be inserted after the loop
    bool change;
    for (it = lset.begin(); it != lset.end(); it++)
        {
            Exp* loc = *it;
            Exp* replace;
            if (loc->search(lhs, replace))
                {
                    if (rhs->isTerminal())
                        {
                            // This is no longer a location of interest (e.g. %pc)
                            removeSet.insert(loc);
                            continue;
                        }
                    loc = loc->clone()->searchReplaceAll(lhs, rhs, change);
                    if (change)
                        {
                            loc = loc->simplifyArith();
                            loc = loc->simplify();
                            // If the result is no longer a register or memory (e.g.
                            // r[28]-4), then delete this expression and insert any
                            // components it uses (in the example, just r[28])
                            if (!loc->isRegOf() && !loc->isMemOf())
                                {
                                    // Note: can't delete the expression yet, because the
                                    // act of insertion into the remove set requires silent
                                    // calls to the compare function
                                    removeAndDelete.insert(*it);
                                    loc->addUsedLocs(insertSet);
                                    continue;
                                }
                            // Else we just want to replace it
                            // Regardless of whether the top level expression pointer has
                            // changed, remove and insert it from the set of pointers
                            removeSet.insert(*it);		// Note: remove the unmodified ptr
                            insertSet.insert(loc);
                        }
                }
        }
    makeDiff(removeSet);	   // Remove the items to be removed
    makeDiff(removeAndDelete); // These are to be removed as well
    makeUnion(insertSet);	   // Insert the items to be added
    // Now delete the expressions that are no longer needed
    std::set<Exp*, lessExpStar>::iterator dd;
    for (dd = removeAndDelete.lset.begin(); dd != removeAndDelete.lset.end();
            dd++)
        delete *dd;				// Plug that memory leak
}
Exemple #7
0
/*!
 * Whether a location set is a pointer type or not
 */
bool ObjTypeInfo::isNonPtrFieldObj(const LocationSet& ls)
{
    if (isHeap() || isStaticObj())
        return false;

    llvm::Type* ety = getLLVMType();
    while (const ArrayType *AT= dyn_cast<ArrayType>(ety)) {
        ety = AT->getElementType();
    }

    if (isa<StructType>(ety) || isa<ArrayType>(ety)) {
        bool hasIntersection = false;
        const vector<FieldInfo> &infovec = SymbolTableInfo::Symbolnfo()->getFlattenFieldInfoVec(ety);
        vector<FieldInfo>::const_iterator it = infovec.begin();
        vector<FieldInfo>::const_iterator eit = infovec.end();
        for (; it != eit; ++it) {
            const FieldInfo& fieldLS = *it;
            if (ls.intersects(LocationSet(fieldLS))) {
                hasIntersection = true;
                if (fieldLS.getFlattenElemTy()->isPointerTy())
                    return false;
            }
        }
        assert(hasIntersection && "cannot find field of specified offset");
        return true;
    }
    else {
        if (isStaticObj() || isHeap()) {
            // TODO: Objects which cannot find proper field for a certain offset including
            //       arguments in main(), static objects allocated before main and heap
            //       objects. Right now they're considered to have infinite fields and we
            //       treat each field as pointers conservatively.
            //       Try to model static and heap objects more accurately in the future.
            return false;
        }
        else {
            // TODO: Using new memory model (locMM) may create objects with spurious offset
            //       as we simply return new offset by mod operation without checking its
            //       correctness in LocSymTableInfo::getModulusOffset(). So the following
            //       assertion may fail. Try to refine the new memory model.
            assert(ls.getOffset() == 0 && "cannot get a field from a non-struct type");
            return (hasPtrObj() == false);
        }
    }
}
Exemple #8
0
// Special intersection method: this := a intersect b
void StatementList::makeIsect(StatementList& a, LocationSet& b)
{
    slist.clear();
    for (iterator it = a.slist.begin(); it != a.slist.end(); ++it)
        {
            Assignment* as = (Assignment*)*it;
            if (b.exists(as->getLeft()))
                slist.push_back(as);
        }
}
bool
LocationSet::operator ==(const LocationSet &o) const
{
	// We want to compare the locations, not the pointers
	if (size() != o.size()) return false;
	for (auto it1 = lset.cbegin(), it2 = o.lset.cbegin(); it1 != lset.cend(); ++it1, ++it2) {
		if (!(**it1 == **it2)) return false;
	}
	return true;
}
// Special intersection method: this := a intersect b
void
StatementList::makeIsect(const StatementList &a, const LocationSet &b)
{
	slist.clear();
	for (const auto &s : a.slist) {
		auto as = (Assignment *)s;
		if (b.exists(as->getLeft()))
			slist.push_back(as);
	}
}
Exemple #11
0
bool LocationSet::operator==(const LocationSet& o) const
{
    // We want to compare the locations, not the pointers
    if (size() != o.size()) return false;
    std::set<Exp*, lessExpStar>::const_iterator it1, it2;
    for (it1 = lset.begin(), it2 = o.lset.begin(); it1 != lset.end(); it1++, it2++)
        {
            if (!(**it1 == **it2)) return false;
        }
    return true;
}
Exemple #12
0
void LocationSetTest::testRemove()
{
    LocationSet set;
    set.remove(nullptr);
    QVERIFY(set.empty());

    set.insert(Location::regOf(REG_PENT_ESI));
    set.remove(Location::regOf(REG_PENT_ESI));
    QVERIFY(set.empty());

    set.insert(Location::regOf(REG_PENT_ESI));
    set.insert(Location::regOf(REG_PENT_EDI));
    set.remove(Location::regOf(REG_PENT_EDI));
    QCOMPARE(set, LocationSet({ Location::regOf(REG_PENT_ESI) }));

    // removing element that does not exist
    set.remove(Location::regOf(REG_PENT_EDI));
    QCOMPARE(set, LocationSet({ Location::regOf(REG_PENT_ESI) }));
}
Exemple #13
0
void LocationSetTest::testContainsImplicit()
{
    LocationSet set;
    QVERIFY(!set.containsImplicit(nullptr));

    set.insert(Location::regOf(REG_PENT_ESI));
    QVERIFY(!set.containsImplicit(Location::regOf(REG_PENT_ESI)));
    QVERIFY(!set.containsImplicit(Location::regOf(REG_PENT_EDI)));

    set.insert(RefExp::get(Location::regOf(REG_PENT_EDI), nullptr));
    QVERIFY(set.containsImplicit(Location::regOf(REG_PENT_EDI)));
    QVERIFY(!set.containsImplicit(Location::regOf(REG_PENT_ESI)));
}
Exemple #14
0
void LocationSetTest::testSize()
{
    LocationSet set;
    QVERIFY(set.size() == 0);

    set.insert(Location::regOf(REG_PENT_ESI));
    QVERIFY(set.size() == 1);

    set.insert(Location::regOf(REG_PENT_EDI));
    QVERIFY(set.size() == 2);
}
Exemple #15
0
void LocationSetTest::testClear()
{
    LocationSet set;

    set.clear();
    QVERIFY(set.empty());

    set.insert(Location::regOf(REG_PENT_ESI));
    set.clear();
    QVERIFY(set.empty());
}
Exemple #16
0
/*!
 * Get modulus offset given the type information
 */
LocationSet SymbolTableInfo::getModulusOffset(ObjTypeInfo* tyInfo, const LocationSet& ls) {

    /// if the offset is negative, it's possible that we're looking for an obj node out of range
    /// of current struct. Make the offset positive so we can still get a node within current
    /// struct to represent this obj.

    Size_t offset = ls.getOffset();
    if(offset < 0) {
        wrnMsg("try to create a gep node with negative offset.");
        offset = abs(offset);
    }
    u32_t maxOffset = tyInfo->getMaxFieldOffsetLimit();
    if (maxOffset != 0)
        offset = offset % maxOffset;
    else
        offset = 0;

    return LocationSet(offset);
}
Exemple #17
0
void LocationSetTest::testFindNS()
{
    LocationSet set;
    QVERIFY(set.findNS(nullptr) == nullptr);

    set.insert(Location::regOf(REG_PENT_ESI));
    SharedExp e = set.findNS(Location::regOf(REG_PENT_ESI));
    QVERIFY(e == nullptr);

    set.insert(RefExp::get(Location::regOf(REG_PENT_EDI), nullptr));
    e = set.findNS(Location::regOf(REG_PENT_EDI));
    QVERIFY(e != nullptr);

    QCOMPARE(e->toString(), QString("r31{-}"));
}
Exemple #18
0
void LocationSetTest::testAddSubscript()
{
    LocationSet set;
    set.addSubscript(nullptr);
    QCOMPARE(set, LocationSet());

    set.insert(Location::regOf(REG_PENT_ECX));
    set.addSubscript(nullptr);
    QCOMPARE(set, LocationSet({ RefExp::get(Location::regOf(REG_PENT_ECX), nullptr) }));

    set.insert(Location::regOf(REG_PENT_ECX));
    Assign as(Location::regOf(REG_PENT_ECX), Location::regOf(REG_PENT_EDX));
    as.setNumber(42);
    set.addSubscript(&as);
    QCOMPARE(set, LocationSet({
        RefExp::get(Location::regOf(REG_PENT_ECX), nullptr),
        RefExp::get(Location::regOf(REG_PENT_ECX), &as) }));
}
Exemple #19
0
void BoolAssign::getDefinitions(LocationSet &defs, bool) const
{
    defs.insert(getLeft());
}
Exemple #20
0
// Helper function for UserProc::propagateStatements()
// Works on basic block n; call from UserProc with n=0 (entry BB)
// If an SSA location is in usedByDomPhi it means it is used in a phi that dominates its assignment
// However, it could turn out that the phi is dead, in which case we don't want to keep the associated entries in
// usedByDomPhi. So we maintain the map defdByPhi which maps locations defined at a phi to the phi statements. Every
// time we see a use of a location in defdByPhi, we remove that map entry. At the end of the procedure we therefore have
// only dead phi statements in the map, so we can delete the associated entries in defdByPhi and also remove the dead
// phi statements.
// We add to the set usedByDomPhi0 whenever we see a location referenced by a phi parameter. When we see a definition
// for such a location, we remove it from the usedByDomPhi0 set (to save memory) and add it to the usedByDomPhi set.
// For locations defined before they are used in a phi parameter, there will be no entry in usedByDomPhi, so we ignore
// it. Remember that each location is defined only once, so that's the time to decide if it is dominated by a phi use or
// not.
void DataFlow::findLiveAtDomPhi(int n, LocationSet& usedByDomPhi, LocationSet& usedByDomPhi0,
			std::map<Exp*, PhiAssign*, lessExpStar>& defdByPhi) {
	// For each statement this BB
	BasicBlock::rtlit rit; StatementList::iterator sit;
	PBB bb = BBs[n];
	Statement* S;
	for (S = bb->getFirstStmt(rit, sit); S; S = bb->getNextStmt(rit, sit)) {
		if (S->isPhi()) {
			// For each phi parameter, insert an entry into usedByDomPhi0
			PhiAssign* pa = (PhiAssign*)S;
			PhiAssign::iterator it;
			for (it = pa->begin(); it != pa->end(); ++it) {
				if (it->e) {
					RefExp* re = new RefExp(it->e, it->def);
					usedByDomPhi0.insert(re);
				}
			}
			// Insert an entry into the defdByPhi map
			RefExp* wrappedLhs = new RefExp(pa->getLeft(), pa);
			defdByPhi[wrappedLhs] = pa;
			// Fall through to the below, because phi uses are also legitimate uses
		}
		LocationSet ls;
		S->addUsedLocs(ls);
		// Consider uses of this statement
		LocationSet::iterator it;
		for (it = ls.begin(); it != ls.end(); ++it) {
			// Remove this entry from the map, since it is not unused
			defdByPhi.erase(*it);
		}
		// Now process any definitions
		ls.clear();
		S->getDefinitions(ls);
		for (it = ls.begin(); it != ls.end(); ++it) {
			RefExp* wrappedDef = new RefExp(*it, S);
			// If this definition is in the usedByDomPhi0 set, then it is in fact dominated by a phi use, so move it to
			// the final usedByDomPhi set
			if (usedByDomPhi0.find(wrappedDef) != usedByDomPhi0.end()) {
				usedByDomPhi0.remove(wrappedDef);
				usedByDomPhi.insert(wrappedDef);
			}
		}
	}

	// Visit each child in the dominator graph
	// Note: this is a linear search!
	// Note also that usedByDomPhi0 may have some irrelevant entries, but this will do no harm, and attempting to erase
	// the irrelevant ones would probably cost more than leaving them alone
	int sz = idom.size();
	for (int c = 0; c < sz; ++c) {
		if (idom[c] != n) continue;
		// Recurse to the child
		findLiveAtDomPhi(c, usedByDomPhi, usedByDomPhi0, defdByPhi);
	}
}
Exemple #21
0
bool DataFlow::renameBlockVars(UserProc* proc, int n, bool clearStacks /* = false */ ) {
	if (++progress > 200) {
		std::cerr << 'r' << std::flush;
		progress = 0;
	}
	bool changed = false;

	// Need to clear the Stacks of old, renamed locations like m[esp-4] (these will be deleted, and will cause compare
	// failures in the Stacks, so it can't be correctly ordered and hence balanced etc, and will lead to segfaults)
	if (clearStacks) Stacks.clear();

	// For each statement S in block n
	BasicBlock::rtlit rit; StatementList::iterator sit;
	PBB bb = BBs[n];
	Statement* S;
	for (S = bb->getFirstStmt(rit, sit); S; S = bb->getNextStmt(rit, sit)) {
		// if S is not a phi function (per Appel)
		/* if (!S->isPhi()) */ {
			// For each use of some variable x in S (not just assignments)
			LocationSet locs;
			if (S->isPhi()) {
				PhiAssign* pa = (PhiAssign*)S;
				Exp* phiLeft = pa->getLeft();
				if (phiLeft->isMemOf() || phiLeft->isRegOf())
					phiLeft->getSubExp1()->addUsedLocs(locs);
				// A phi statement may use a location defined in a childless call, in which case its use collector
				// needs updating
				PhiAssign::iterator pp;
				for (pp = pa->begin(); pp != pa->end(); ++pp) {
					Statement* def = pp->def;
					if (def && def->isCall())
						((CallStatement*)def)->useBeforeDefine(phiLeft->clone());
				}
			}
			else {				// Not a phi assignment
				S->addUsedLocs(locs);
			}
			LocationSet::iterator xx;
			for (xx = locs.begin(); xx != locs.end(); xx++) {
				Exp* x = *xx;
				// Don't rename memOfs that are not renamable according to the current policy
				if (!canRename(x, proc)) continue;
				Statement* def = NULL;
				if (x->isSubscript()) {					// Already subscripted?
					// No renaming required, but redo the usage analysis, in case this is a new return, and also because
					// we may have just removed all call livenesses
					// Update use information in calls, and in the proc (for parameters)
					Exp* base = ((RefExp*)x)->getSubExp1();
					def = ((RefExp*)x)->getDef();
					if (def && def->isCall()) {
						// Calls have UseCollectors for locations that are used before definition at the call
						((CallStatement*)def)->useBeforeDefine(base->clone());
						continue;
					}
					// Update use collector in the proc (for parameters)
					if (def == NULL)
						proc->useBeforeDefine(base->clone());
					continue;							// Don't re-rename the renamed variable
				}
				// Else x is not subscripted yet
				if (STACKS_EMPTY(x)) {
					if (!Stacks[defineAll].empty())
						def = Stacks[defineAll].top();
					else {
						// If the both stacks are empty, use a NULL definition. This will be changed into a pointer
						// to an implicit definition at the start of type analysis, but not until all the m[...]
						// have stopped changing their expressions (complicates implicit assignments considerably).
						def = NULL;
						// Update the collector at the start of the UserProc
						proc->useBeforeDefine(x->clone());
					}
				}
				else
					def = Stacks[x].top();
				if (def && def->isCall())
					// Calls have UseCollectors for locations that are used before definition at the call
					((CallStatement*)def)->useBeforeDefine(x->clone());
				// Replace the use of x with x{def} in S
				changed = true;
				if (S->isPhi()) {
					Exp* phiLeft = ((PhiAssign*)S)->getLeft();
					phiLeft->setSubExp1(phiLeft->getSubExp1()->expSubscriptVar(x, def /*, this*/));
				} else {
					S->subscriptVar(x, def /*, this */);
				}
			}
		}

		// MVE: Check for Call and Return Statements; these have DefCollector objects that need to be updated
		// Do before the below, so CallStatements have not yet processed their defines
		if (S->isCall() || S->isReturn()) {
			DefCollector* col;
			if (S->isCall())
				col = ((CallStatement*)S)->getDefCollector();
			else
				col = ((ReturnStatement*)S)->getCollector();
			col->updateDefs(Stacks, proc);
		}

		// For each definition of some variable a in S
		LocationSet defs;
		S->getDefinitions(defs);
		LocationSet::iterator dd;
		for (dd = defs.begin(); dd != defs.end(); dd++) {
			Exp* a = *dd;
			// Don't consider a if it cannot be renamed
			bool suitable = canRename(a, proc);
			if (suitable) {
				// Push i onto Stacks[a]
				// Note: we clone a because otherwise it could be an expression that gets deleted through various
				// modifications. This is necessary because we do several passes of this algorithm to sort out the
				// memory expressions
				Stacks[a->clone()].push(S);
				// Replace definition of a with definition of a_i in S (we don't do this)
			}
			// FIXME: MVE: do we need this awful hack?
			if (a->getOper() == opLocal) {
				Exp *a1 = S->getProc()->expFromSymbol(((Const*)a->getSubExp1())->getStr());
				assert(a1);
				a = a1;
				// Stacks already has a definition for a (as just the bare local)
				if (suitable) {
					Stacks[a->clone()].push(S);
				}
			}
		}
		// Special processing for define-alls (presently, only childless calls).
// But note that only everythings at the current memory level are defined!
		if (S->isCall() && ((CallStatement*)S)->isChildless() && !Boomerang::get()->assumeABI) {
			// S is a childless call (and we're not assuming ABI compliance)
			Stacks[defineAll];										// Ensure that there is an entry for defineAll
			std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator dd;
			for (dd = Stacks.begin(); dd != Stacks.end(); ++dd) {
// if (dd->first->isMemDepth(memDepth))
					dd->second.push(S);								// Add a definition for all vars
			}
		}
	}

	// For each successor Y of block n
	std::vector<PBB>& outEdges = bb->getOutEdges();
	unsigned numSucc = outEdges.size();
	for (unsigned succ = 0; succ < numSucc; succ++) {
		PBB Ybb = outEdges[succ];
		// Suppose n is the jth predecessor of Y
		int j = Ybb->whichPred(bb);
		// For each phi-function in Y
		Statement* S;
		for (S = Ybb->getFirstStmt(rit, sit); S; S = Ybb->getNextStmt(rit, sit)) {
			PhiAssign* pa = dynamic_cast<PhiAssign*>(S);
			// if S is not a phi function, then quit the loop (no more phi's)
			// Wrong: do not quit the loop: there's an optimisation that turns a PhiAssign into an ordinary Assign.
			// So continue, not break.
			if (!pa) continue;
			// Suppose the jth operand of the phi is a
			// For now, just get the LHS
			Exp* a = pa->getLeft();
			// Only consider variables that can be renamed
			if (!canRename(a, proc)) continue;
			Statement* def;
			if (STACKS_EMPTY(a))
				def = NULL;				// No reaching definition
			else
				def = Stacks[a].top();
			// "Replace jth operand with a_i"
			pa->putAt(j, def, a);
		}
	}

	// For each child X of n
	// Note: linear search!
	unsigned numBB = proc->getCFG()->getNumBBs();
	for (unsigned X=0; X < numBB; X++) {
		if (idom[X] == n)
			renameBlockVars(proc, X);
	}

	// For each statement S in block n
	// NOTE: Because of the need to pop childless calls from the Stacks, it is important in my algorithm to process the
	// statments in the BB *backwards*. (It is not important in Appel's algorithm, since he always pushes a definition
	// for every variable defined on the Stacks).
	BasicBlock::rtlrit rrit; StatementList::reverse_iterator srit;
	for (S = bb->getLastStmt(rrit, srit); S; S = bb->getPrevStmt(rrit, srit)) {
		// For each definition of some variable a in S
		LocationSet defs;
		S->getDefinitions(defs);
		LocationSet::iterator dd;
		for (dd = defs.begin(); dd != defs.end(); dd++) {
			if (canRename(*dd, proc)) {
				// if ((*dd)->getMemDepth() == memDepth)
				std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator ss = Stacks.find(*dd);
				if (ss == Stacks.end()) {
					std::cerr << "Tried to pop " << *dd << " from Stacks; does not exist\n";
 					assert(0);
				}
					ss->second.pop();
			}
		}
		// Pop all defs due to childless calls
		if (S->isCall() && ((CallStatement*)S)->isChildless()) {
			std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator sss;
			for (sss = Stacks.begin(); sss != Stacks.end(); ++sss) {
				if (!sss->second.empty() && sss->second.top() == S) {
					sss->second.pop();
				}
			}
		}
	}
	return changed;
}
Exemple #22
0
bool DataFlow::placePhiFunctions(UserProc* proc) {
	// First free some memory no longer needed
	dfnum.resize(0);
	semi.resize(0);
	ancestor.resize(0);
	samedom.resize(0);
	vertex.resize(0);
	parent.resize(0);
	best.resize(0);
	bucket.resize(0);
	defsites.clear();			// Clear defsites map,
	defallsites.clear();
	A_orig.clear();				// and A_orig,
	defStmts.clear();			// and the map from variable to defining Stmt 

	bool change = false;

	// Set the sizes of needed vectors
	unsigned numBB = indices.size();
	Cfg* cfg = proc->getCFG();
	assert(numBB == cfg->getNumBBs());
	A_orig.resize(numBB);

	// We need to create A_orig[n] for all n, the array of sets of locations defined at BB n
	// Recreate each call because propagation and other changes make old data invalid
	unsigned n;
	for (n=0; n < numBB; n++) {
		BasicBlock::rtlit rit; StatementList::iterator sit;
		PBB bb = BBs[n];
		for (Statement* s = bb->getFirstStmt(rit, sit); s; s = bb->getNextStmt(rit, sit)) {
			LocationSet ls;
			LocationSet::iterator it;
			s->getDefinitions(ls);
			if (s->isCall() && ((CallStatement*)s)->isChildless())		// If this is a childless call
				defallsites.insert(n);									// then this block defines every variable
			for (it = ls.begin(); it != ls.end(); it++) {
				if (canRename(*it, proc)) {
					A_orig[n].insert((*it)->clone());
					defStmts[*it] = s;
				}
			}
		}
	}

	// For each node n
	for (n=0; n < numBB; n++) {
		// For each variable a in A_orig[n]
		std::set<Exp*, lessExpStar>& s = A_orig[n];
		std::set<Exp*, lessExpStar>::iterator aa;
		for (aa = s.begin(); aa != s.end(); aa++) {
			Exp* a = *aa;
			defsites[a].insert(n);
		}
	}

	// For each variable a (in defsites, i.e. defined anywhere)
	std::map<Exp*, std::set<int>, lessExpStar>::iterator mm;
	for (mm = defsites.begin(); mm != defsites.end(); mm++) {
		Exp* a = (*mm).first;				// *mm is pair<Exp*, set<int>>

		// Special processing for define-alls
		// for each n in defallsites
		std::set<int>::iterator da;
		for (da = defallsites.begin(); da != defallsites.end(); ++da)
			defsites[a].insert(*da);

		// W <- defsites[a];
		std::set<int> W = defsites[a];		// set copy
		// While W not empty
		while (W.size()) {
			// Remove some node n from W
			int n = *W.begin();				// Copy first element
			W.erase(W.begin());				// Remove first element
			// for each y in DF[n]
			std::set<int>::iterator yy;
			std::set<int>& DFn = DF[n];
			for (yy = DFn.begin(); yy != DFn.end(); yy++) {
				int y = *yy;
				// if y not element of A_phi[a]
				std::set<int>& s = A_phi[a];
				if (s.find(y) == s.end()) {
					// Insert trivial phi function for a at top of block y: a := phi()
					change = true;
					Statement* as = new PhiAssign(a->clone());
					PBB Ybb = BBs[y];
					Ybb->prependStmt(as, proc);
					// A_phi[a] <- A_phi[a] U {y}
					s.insert(y);
					// if a !elementof A_orig[y]
					if (A_orig[y].find(a) == A_orig[y].end()) {
						// W <- W U {y}
						W.insert(y);
					}
				}
			}
		}
	}
	return change;
}		// end placePhiFunctions
Exemple #23
0
void LocationSetTest::testFindDifferentRef()
{
    LocationSet set;

    SharedExp result;
    QVERIFY(!set.findDifferentRef(nullptr, result));

    set.insert(Location::regOf(REG_PENT_EAX));
    QVERIFY(!set.findDifferentRef(RefExp::get(Location::regOf(REG_PENT_EAX), nullptr), result));

    set.insert(RefExp::get(Location::regOf(REG_PENT_EAX), nullptr));
    QVERIFY(!set.findDifferentRef(RefExp::get(Location::regOf(REG_PENT_EAX), nullptr), result));

    Assign as1(Location::regOf(REG_PENT_ECX), Location::regOf(REG_PENT_EDX));
    Assign as2(Location::regOf(REG_PENT_ECX), Location::regOf(REG_PENT_EDX));

    as1.setNumber(10);
    as2.setNumber(20);

    set.insert(RefExp::get(Location::regOf(REG_PENT_ECX), &as1));
    // no other ref
    QVERIFY(!set.findDifferentRef(RefExp::get(Location::regOf(REG_PENT_ECX), &as1), result));

    set.insert(RefExp::get(Location::regOf(REG_PENT_ECX), &as2));
    // return a different ref
    QVERIFY(set.findDifferentRef(RefExp::get(Location::regOf(REG_PENT_ECX), &as1), result));
    QCOMPARE(result->toString(), QString("r25{20}"));

    // should work even when the ref is not in the set
    set.remove(RefExp::get(Location::regOf(REG_PENT_ECX), &as1));
    QVERIFY(set.findDifferentRef(RefExp::get(Location::regOf(REG_PENT_ECX), &as1), result));
    QCOMPARE(result->toString(), QString("r25{20}"));
}