Exemplo n.º 1
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
}
Exemplo n.º 2
0
Exp *ExpTransformer::applyAllTo(Exp *p, bool &bMod)
{
	for (std::list<Exp*>::iterator it = cache.begin(); it != cache.end(); it++)
		if (*(*it)->getSubExp1() == *p)
			return (*it)->getSubExp2()->clone();

	Exp *e = p->clone();
	Exp *subs[3];
	subs[0] = e->getSubExp1();
	subs[1] = e->getSubExp2();
	subs[2] = e->getSubExp3();

	for (int i = 0; i < 3; i++)
		if (subs[i]) {
			bool mod = false;
			subs[i] = applyAllTo(subs[i], mod);
			if (mod && i == 0)
				e->setSubExp1(subs[i]);
			if (mod && i == 1)
				e->setSubExp2(subs[i]);
			if (mod && i == 2)
				e->setSubExp3(subs[i]);
			bMod |= mod;
//			if (mod) i--;
		}

#if 0
	LOG << "applyAllTo called on " << e << "\n";
#endif
	bool mod;
	//do {
		mod = false;
		for (std::list<ExpTransformer *>::iterator it = transformers.begin(); it != transformers.end(); it++) {
			e = (*it)->applyTo(e, mod);
			bMod |= mod;
		}
	//} while (mod);

	cache.push_back(new Binary(opEquals, p->clone(), e->clone()));
	return e;
}
Exemplo n.º 3
0
Exp *GenericExpTransformer::applyFuncs(Exp *rhs)
{
	Exp *call, *callw = new Binary(opFlagCall, new Const((char *)"memberAtOffset"), new Terminal(opWild));
	if (rhs->search(callw, call)) {
		assert(call->getSubExp2()->getOper() == opList);
		Exp *p1 = applyFuncs(call->getSubExp2()->getSubExp1());
		Exp *p2 = applyFuncs(call->getSubExp2()->getSubExp2()->getSubExp1());
		assert(p1->getOper() == opTypeVal);
		assert(p2->getOper() == opIntConst);
#if 0
		Type *ty = p1->getType();
		assert(ty && ty->resolvesToCompound());
#else
		Type *ty = NULL;  // Note: will cause a segfault
#endif
		// probably need to make this func take bits in future
		int offset = ((Const *)p2)->getInt() * 8;
		const char *member = ty->asCompound()->getNameAtOffset(offset);
		Exp *result = new Const((char *)member);
		bool change;
		rhs = rhs->searchReplace(callw->clone(), result->clone(), change);
		assert(change);
#if 0
		LOG << "replaced " << call << " with " << result << "\n";
#endif
	}
	callw = new Binary(opFlagCall, new Const((char *)"offsetToMember"), new Terminal(opWild));
	if (rhs->search(callw, call)) {
		assert(call->getSubExp2()->getOper() == opList);
		Exp *p1 = applyFuncs(call->getSubExp2()->getSubExp1());
		Exp *p2 = applyFuncs(call->getSubExp2()->getSubExp2()->getSubExp1());
		assert(p1->getOper() == opTypeVal);
		assert(p2->getOper() == opStrConst);
#if 0 // ADHOC TA
		Type *ty = p1->getType();
		assert(ty && ty->resolvesToCompound());
#else
		Type *ty = NULL;  // Note: will cause a segfault
#endif
		char *member = ((Const *)p2)->getStr();
		int offset = ty->asCompound()->getOffsetTo(member) / 8;
		Exp *result = new Const(offset);
		bool change;
		rhs = rhs->searchReplace(callw->clone(), result->clone(), change);
		assert(change);
#if 0
		LOG << "replaced " << call << " with " << result << "\n";
#endif
	}
	callw = new Binary(opFlagCall, new Const((char *)"plus"), new Terminal(opWild));
	if (rhs->search(callw, call)) {
		assert(call->getSubExp2()->getOper() == opList);
		Exp *p1 = applyFuncs(call->getSubExp2()->getSubExp1());
		Exp *p2 = applyFuncs(call->getSubExp2()->getSubExp2()->getSubExp1());
		assert(p1->getOper() == opIntConst);
		assert(p2->getOper() == opIntConst);
		int a = ((Const *)p1)->getInt();
		int b = ((Const *)p2)->getInt();
		Exp *result = new Const(a + b);
		bool change;
		rhs = rhs->searchReplace(callw->clone(), result->clone(), change);
		assert(change);
#if 0
		LOG << "replaced " << call << " with " << result << "\n";
#endif
	}
	callw = new Binary(opFlagCall, new Const((char *)"neg"), new Terminal(opWild));
	if (rhs->search(callw, call)) {
		Exp *p1 = applyFuncs(call->getSubExp2());
		assert(p1->getOper() == opIntConst);
		int a = ((Const *)p1)->getInt();
		Exp *result = new Const(-a);
		bool change;
		rhs = rhs->searchReplace(callw->clone(), result->clone(), change);
		assert(change);
#if 0
		LOG << "replaced " << call << " with " << result << "\n";
#endif
	}
	return rhs;
}
Exemplo n.º 4
0
bool GenericExpTransformer::checkCond(Exp *cond, Exp *bindings)
{
	switch (cond->getOper()) {
	case opAnd:
		return checkCond(cond->getSubExp1(), bindings)
		    && checkCond(cond->getSubExp2(), bindings);
	case opEquals:
		{
			Exp *lhs = cond->getSubExp1(), *rhs = cond->getSubExp2();
			for (Exp *l = bindings; l->getOper() != opNil; l = l->getSubExp2()) {
				Exp *e = l->getSubExp1();
				bool change = false;
				lhs = lhs->searchReplaceAll(e->getSubExp1()->clone(), e->getSubExp2()->clone(), change);
#if 0
				if (change)
					LOG << "replaced " << e->getSubExp1() << " with " << e->getSubExp2() << "\n";
#endif
				change = false;
				rhs = rhs->searchReplaceAll(e->getSubExp1()->clone(), e->getSubExp2()->clone(), change);
#if 0
				if (change)
					LOG << "replaced " << e->getSubExp1() << " with " << e->getSubExp2() << "\n";
#endif
			}
			if (lhs->getOper() == opTypeOf) {
#if 0 // ADHOC TA
				Type *ty = lhs->getSubExp1()->getType();
#else
				Type *ty = NULL;
#endif
				if (ty == NULL) {
#if 0
					if (VERBOSE)
						LOG << "no type for typeof " << lhs << "\n";
#endif
					return false;
				}
				lhs = new TypeVal(ty);
#if 0
				LOG << "got typeval: " << lhs << "\n";
#endif
			}
			if (lhs->getOper() == opKindOf) {
				OPER op = lhs->getSubExp1()->getOper();
				lhs = new Const(operStrings[op]);
			}
			rhs = applyFuncs(rhs);

#if 0
			LOG << "check equals in cond: " << lhs << " == " << rhs << "\n";
#endif

			if (lhs->getOper() == opVar) {
				Exp *le;
				for (le = bindings; le->getOper() != opNil && le->getSubExp2()->getOper() != opNil; le = le->getSubExp2())
					;
				assert(le->getOper() != opNil);
				le->setSubExp2(new Binary(opList, new Binary(opEquals, lhs->clone(), rhs->clone()), new Terminal(opNil)));
#if 0
				LOG << "bindings now: " << bindings << "\n";
#endif
				return true;
			}

			if (*lhs == *rhs)
				return true;

#if 0 // ADHOC TA
			if (lhs->getOper() == opTypeVal
			 && rhs->getOper() == opTypeVal
			 && lhs->getType()->resolvesToCompound()
			 && rhs->getType()->isCompound())
				return true;
#endif

			Exp *new_bindings = lhs->match(rhs);
			if (new_bindings == NULL)
				return false;

#if 0
			LOG << "matched lhs with rhs, bindings: " << new_bindings << "\n";
#endif

			Exp *le;
			for (le = bindings; le->getOper() != opNil && le->getSubExp2()->getOper() != opNil; le = le->getSubExp2())
				;
			assert(le->getOper() != opNil);
			le->setSubExp2(new_bindings);

#if 0
			LOG << "bindings now: " << bindings << "\n";
#endif

			return true;
		}
	default:
		LOG << "don't know how to handle oper "
		    << operStrings[cond->getOper()] << " in cond.\n";
	}
	return false;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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
Exemplo n.º 7
0
void BlockSyntaxNode::addSuccessors(SyntaxNode *root, std::vector<SyntaxNode *> &successors)
{
	for (unsigned i = 0; i < statements.size(); i++) {
		if (statements[i]->isBlock()) {
			//BlockSyntaxNode *b = (BlockSyntaxNode*)statements[i];
			// can move previous statements into this block
			if (i > 0) {
				std::cerr << "successor: move previous statement into block" << std::endl;
				SyntaxNode *n = root->clone();
				n->setDepth(root->getDepth() + 1);
				BlockSyntaxNode *b1 = (BlockSyntaxNode *)this->clone();
				BlockSyntaxNode *nb = (BlockSyntaxNode *)b1->getStatement(i);
				b1 = (BlockSyntaxNode *)b1->replace(statements[i - 1], NULL);
				nb->prependStatement(statements[i - 1]->clone());
				n = n->replace(this, b1);
				successors.push_back(n);
				//PRINT_BEFORE_AFTER
			}
		} else {
			if (statements.size() != 1) {
				// can replace statement with a block containing that statement
				std::cerr << "successor: replace statement with a block containing the statement" << std::endl;
				BlockSyntaxNode *b = new BlockSyntaxNode();
				b->addStatement(statements[i]->clone());
				SyntaxNode *n = root->clone();
				n->setDepth(root->getDepth() + 1);
				n = n->replace(statements[i], b);
				successors.push_back(n);
				//PRINT_BEFORE_AFTER
			}
		}
		// "jump over" style of if-then
		if (i < statements.size() - 2 && statements[i]->isBranch()) {
			SyntaxNode *b = statements[i];
			if (b->getOutEdge(root, 0) == statements[i + 2]
			 && (statements[i + 1]->getOutEdge(root, 0) == statements[i + 2]
			  || statements[i + 1]->endsWithGoto())) {
				std::cerr << "successor: jump over style if then" << std::endl;
				BlockSyntaxNode *b1 = (BlockSyntaxNode *)this->clone();
				b1 = (BlockSyntaxNode *)b1->replace(statements[i + 1], NULL);
				IfThenSyntaxNode *nif = new IfThenSyntaxNode();
				Exp *cond = b->getBB()->getCond();
				cond = new Unary(opLNot, cond->clone());
				cond = cond->simplify();
				nif->setCond(cond);
				nif->setThen(statements[i + 1]->clone());
				nif->setBB(b->getBB());
				b1->setStatement(i, nif);
				SyntaxNode *n = root->clone();
				n->setDepth(root->getDepth() + 1);
				n = n->replace(this, b1);
				successors.push_back(n);
				//PRINT_BEFORE_AFTER
			}
		}
		// if then else
		if (i < statements.size() - 2 && statements[i]->isBranch()) {
			SyntaxNode *tThen = statements[i]->getOutEdge(root, 0);
			SyntaxNode *tElse = statements[i]->getOutEdge(root, 1);

			assert(tThen && tElse);
			if (((tThen == statements[i + 2] && tElse == statements[i + 1])
			  || (tThen == statements[i + 1] && tElse == statements[i + 2]))
			 && tThen->getNumOutEdges() == 1 && tElse->getNumOutEdges() == 1) {
				SyntaxNode *else_out = tElse->getOutEdge(root, 0);
				SyntaxNode *then_out = tThen->getOutEdge(root, 0);

				if (else_out == then_out) {
					std::cerr << "successor: if then else" << std::endl;
					SyntaxNode *n = root->clone();
					n->setDepth(root->getDepth() + 1);
					n = n->replace(tThen, NULL);
					n = n->replace(tElse, NULL);
					IfThenElseSyntaxNode *nif = new IfThenElseSyntaxNode();
					nif->setCond(statements[i]->getBB()->getCond()->clone());
					nif->setBB(statements[i]->getBB());
					nif->setThen(tThen->clone());
					nif->setElse(tElse->clone());
					n = n->replace(statements[i], nif);
					successors.push_back(n);
					//PRINT_BEFORE_AFTER
				}
			}
		}

		// pretested loop
		if (i < statements.size() - 2 && statements[i]->isBranch()) {
			SyntaxNode *tBody = statements[i]->getOutEdge(root, 0);
			SyntaxNode *tFollow =  statements[i]->getOutEdge(root, 1);

			assert(tBody && tFollow);
			if (tBody == statements[i + 1] && tFollow == statements[i + 2]
			 && tBody->getNumOutEdges() == 1
			 && tBody->getOutEdge(root, 0) == statements[i]) {
				std::cerr << "successor: pretested loop" << std::endl;
				SyntaxNode *n = root->clone();
				n->setDepth(root->getDepth() + 1);
				n = n->replace(tBody, NULL);
				PretestedLoopSyntaxNode *nloop = new PretestedLoopSyntaxNode();
				nloop->setCond(statements[i]->getBB()->getCond()->clone());
				nloop->setBB(statements[i]->getBB());
				nloop->setBody(tBody->clone());
				n = n->replace(statements[i], nloop);
				successors.push_back(n);
				//PRINT_BEFORE_AFTER
			}
		}

		// posttested loop
		if (i > 0 && i < statements.size() - 1 && statements[i]->isBranch()) {
			SyntaxNode *tBody = statements[i]->getOutEdge(root, 0);
			SyntaxNode *tFollow =  statements[i]->getOutEdge(root, 1);

			assert(tBody && tFollow);
			if (tBody == statements[i - 1] && tFollow == statements[i + 1]
			 && tBody->getNumOutEdges() == 1
			 && tBody->getOutEdge(root, 0) == statements[i]) {
				std::cerr << "successor: posttested loop" << std::endl;
				SyntaxNode *n = root->clone();
				n->setDepth(root->getDepth() + 1);
				n = n->replace(tBody, NULL);
				PostTestedLoopSyntaxNode *nloop = new PostTestedLoopSyntaxNode();
				nloop->setCond(statements[i]->getBB()->getCond()->clone());
				nloop->setBB(statements[i]->getBB());
				nloop->setBody(tBody->clone());
				n = n->replace(statements[i], nloop);
				successors.push_back(n);
				//PRINT_BEFORE_AFTER
			}
		}

		// infinite loop
		if (statements[i]->getNumOutEdges() == 1
		 && statements[i]->getOutEdge(root, 0) == statements[i]) {
			std::cerr << "successor: infinite loop" << std::endl;
			SyntaxNode *n = root->clone();
			n->setDepth(root->getDepth() + 1);
			InfiniteLoopSyntaxNode *nloop = new InfiniteLoopSyntaxNode();
			nloop->setBody(statements[i]->clone());
			n = n->replace(statements[i], nloop);
			successors.push_back(n);
			PRINT_BEFORE_AFTER
		}

		statements[i]->addSuccessors(root, successors);
	}
Exemplo n.º 8
0
std::list<Statement *> *RTLInstDict::transformPostVars(std::list<Statement *> *rts, bool optimise)
{
    std::list<Statement *>::iterator rt;

    // Map from var (could be any expression really) to details
    std::map<Exp *, transPost, lessExpStar> vars;
    int tmpcount = 1;  // For making temp names unique
    // Exp *matchParam(1, idParam);  // ? Was never used anyway

#ifdef DEBUG_POSTVAR
    std::cout << "Transforming from:\n";
    for (Exp_CIT p = rts->begin(); p != rts->end(); p++) {
        std::cout << setw(8) << " ";
        (*p)->print(std::cout);
        std::cout << "\n";
    }
#endif

    // First pass: Scan for post-variables and usages of their referents
    for (rt = rts->begin(); rt != rts->end(); rt++) {
        // ss appears to be a list of expressions to be searched
        // It is either the LHS and RHS of an assignment, or it's the parameters of a flag call
        Binary *ss;
        if ((*rt)->isAssign()) {
            Exp *lhs = ((Assign *)*rt)->getLeft();
            Exp *rhs = ((Assign *)*rt)->getRight();

            // Look for assignments to post-variables
            if (lhs && lhs->isPostVar()) {
                if (vars.find(lhs) == vars.end()) {
                    // Add a record in the map for this postvar
                    transPost &el = vars[lhs];
                    el.used = false;
                    el.type = ((Assign *)*rt)->getType();

                    // Constuct a temporary. We should probably be smarter and actually check that it's not otherwise
                    // used here.
                    std::string tmpname = el.type->getTempName() + (tmpcount++) + "post" ;
                    el.tmp = Location::tempOf(new Const(tmpname.c_str()));

                    // Keep a copy of the referrent. For example, if the lhs is r[0]', base is r[0]
                    el.base = lhs->getSubExp1();
                    el.post = lhs;  // The whole post-var, e.g. r[0]'
                    el.isNew = true;

                    // The emulator generator sets optimise false
                    // I think this forces always generating the temps (MVE)
                    if (!optimise) {
                        el.used = true;
                        el.isNew = false;
                    }

                }
            }
            // For an assignment, the two expressions to search are the left and right hand sides (could just put the
            // whole assignment on, I suppose)
            ss = new Binary(opList,
                            lhs->clone(),
                            new Binary(opList,
                                       rhs->clone(),
                                       new Terminal(opNil)));
        } else if ((*rt)->isFlagAssgn()) {
            // An opFlagCall is assumed to be a Binary with a string and an opList of parameters
            ss = (Binary *)((Binary *)*rt)->getSubExp2();
        } else
            ss = NULL;

        /* Look for usages of post-variables' referents
         * Trickier than you'd think, as we need to make sure to skip over the post-variables themselves. ie match
         * r[0] but not r[0]'
         * Note: back with SemStrs, we could use a match expression which was a wildcard prepended to the base
         * expression; this would match either the base (r[0]) or the post-var (r[0]').
         * Can't really use this with Exps, so we search twice; once for the base, and once for the post, and if we
         * get more with the former, then we have a use of the base (consider r[0] + r[0]')
         */
        for (std::map<Exp *, transPost, lessExpStar>::iterator sr = vars.begin(); sr != vars.end(); sr++) {
            if (sr->second.isNew) {
                // Make sure we don't match a var in its defining statement
                sr->second.isNew = false;
                continue;
            }
            Binary *cur;
            for (cur = ss; !cur->isNil(); cur = (Binary *)cur->getSubExp2()) {
                if (sr->second.used)
                    break;  // Don't bother; already know it's used
                Exp *s = cur->getSubExp1();
                if (!s) continue;
                if (*s == *sr->second.base) {
                    sr->second.used = true;
                    break;
                }
                std::list<Exp *> res1, res2;
                s->searchAll(sr->second.base, res1);
                s->searchAll(sr->second.post, res2);
                // Each match of a post will also match the base.
                // But if there is a bare (non-post) use of the base, there will be a result in res1 that is not in res2
                if (res1.size() > res2.size())
                    sr->second.used = true;
            }
        }
    }

    // Second pass: Replace post-variables with temporaries where needed
    for (rt = rts->begin(); rt != rts->end(); rt++) {
        for (std::map<Exp *, transPost, lessExpStar>::iterator sr = vars.begin(); sr != vars.end(); sr++) {
            if (sr->second.used) {
                (*rt)->searchAndReplace(sr->first, sr->second.tmp);
            } else {
                (*rt)->searchAndReplace(sr->first, sr->second.base);
            }
        }
    }

    // Finally: Append assignments where needed from temps to base vars
    // Example: esp' = esp-4; m[esp'] = modrm; FLAG(esp)
    // all the esp' are replaced with say tmp1, you need a "esp = tmp1" at the end to actually make the change
    for (std::map<Exp *, transPost, lessExpStar>::iterator sr = vars.begin(); sr != vars.end(); sr++) {
        if (sr->second.used) {
            Assign *te = new Assign(sr->second.type,
                                    sr->second.base->clone(),
                                    sr->second.tmp);
            rts->push_back(te);
        } else {
            // The temp is either used (uncloned) in the assignment, or is deleted here
            //delete sr->second.tmp;
        }
    }

#ifdef DEBUG_POSTVAR
    std::cout << "\nTo =>\n";
    for (std::list<Exp *>::iterator p = rts->begin(); p != rts->end(); p++) {
        std::cout << setw(8) << " ";
        (*p)->print(std::cout);
        std::cout << "\n";
    }
    std::cout << "\n";
#endif

    return rts;
}
Exemplo n.º 9
0
bool Constraints::solve(std::list<ConstraintMap>& solns) {
LOG << conSet.size() << " constraints:";
std::ostringstream os; conSet.print(os); LOG << os.str().c_str();
	// Replace Ta[loc] = ptr(alpha) with
	//		   Tloc = alpha
	LocationSet::iterator cc;
	for (cc = conSet.begin(); cc != conSet.end(); cc++) {
		Exp* c = *cc;
		if (!c->isEquality()) continue;
		Exp* left = ((Binary*)c)->getSubExp1();
		if (!left->isTypeOf()) continue;
		Exp* leftSub = ((Unary*)left)->getSubExp1();
		if (!leftSub->isAddrOf()) continue;
		Exp* right = ((Binary*)c)->getSubExp2();
		if (!right->isTypeVal()) continue;
		Type* t = ((TypeVal*)right)->getType();
		if (!t->isPointer()) continue;
		// Don't modify a key in a map
		Exp* clone = c->clone();
		// left is typeof(addressof(something)) -> typeof(something)
		left = ((Binary*)clone)->getSubExp1();
		leftSub = ((Unary*)left)->getSubExp1();
		Exp* something = ((Unary*)leftSub)->getSubExp1();
		((Unary*)left)->setSubExp1ND(something);
		((Unary*)leftSub)->setSubExp1ND(NULL);
		delete leftSub;
		// right is <alpha*> -> <alpha>
		right = ((Binary*)clone)->getSubExp2();
		t = ((TypeVal*)right)->getType();
		((TypeVal*)right)->setType(((PointerType*)t)->getPointsTo()->clone());
		delete t;
		conSet.remove(c);
		conSet.insert(clone);
		delete c;
	}

	// Sort constraints into a few categories. Disjunctions go to a special
	// list, always true is just ignored, and constraints of the form
	// typeof(x) = y (where y is a type value) go to a map called fixed.
	// Constraint terms of the form Tx = Ty go into a map of LocationSets
	// called equates for fast lookup
	for (cc = conSet.begin(); cc != conSet.end(); cc++) {
		Exp* c = *cc;
		if (c->isTrue()) continue;
		if (c->isFalse()) {
			if (VERBOSE || DEBUG_TA)
				LOG << "Constraint failure: always false constraint\n";
			return false;
		}
		if (c->isDisjunction()) {
			disjunctions.push_back(c);
			continue;
		}
		// Break up conjunctions into terms
		Exp* rem = c, *term;
		while ((term = nextConjunct(rem)) != NULL) {
			assert(term->isEquality());
			Exp* lhs = ((Binary*)term)->getSubExp1();
			Exp* rhs = ((Binary*)term)->getSubExp2();
			if (rhs->isTypeOf()) {
				// Of the form typeof(x) = typeof(z)
				// Insert into equates 
				equates.addEquate(lhs, rhs);
			} else {
				// Of the form typeof(x) = <typeval>
				// Insert into fixed
				assert(rhs->isTypeVal());
				fixed[lhs] = rhs;
			}
		}
	}

	{LOG << "\n" << (unsigned)disjunctions.size() << " disjunctions: "; std::list<Exp*>::iterator dd;
	 for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) LOG << *dd << ",\n"; LOG << "\n";}
	LOG << fixed.size() << " fixed: " << fixed.prints();
	LOG << equates.size() << " equates: " << equates.prints();

	// Substitute the fixed types into the disjunctions
	substIntoDisjuncts(fixed);

	// Substitute the fixed types into the equates. This may generate more
	// fixed types
	substIntoEquates(fixed);

	LOG << "\nAfter substitute fixed into equates:\n";
	{LOG << "\n" << (unsigned)disjunctions.size() << " disjunctions: "; std::list<Exp*>::iterator dd;
	 for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) LOG << *dd << ",\n"; LOG << "\n";}
	LOG << fixed.size() << " fixed: " << fixed.prints();
	LOG << equates.size() << " equates: " << equates.prints();
	// Substitute again the fixed types into the disjunctions
	// (since there may be more fixed types from the above)
	substIntoDisjuncts(fixed);

	LOG << "\nAfter second substitute fixed into disjunctions:\n";
	{LOG << "\n" << (unsigned)disjunctions.size() << " disjunctions: "; std::list<Exp*>::iterator dd;
	 for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) LOG << *dd << ",\n"; LOG << "\n";}
	LOG << fixed.size() << " fixed: " << fixed.prints();
	LOG << equates.size() << " equates: " << equates.prints();

	ConstraintMap soln;
	bool ret = doSolve(disjunctions.begin(), soln, solns);
	if (ret) {
		// For each solution, we need to find disjunctions of the form
		// <alphaN> = <type>	  or
		// <type>	= <alphaN>
		// and substitute these into each part of the solution
		std::list<ConstraintMap>::iterator it;
		for (it = solns.begin(); it != solns.end(); it++)
			it->substAlpha();
	}
	return ret;
}