use of soot.toolkits.scalar.ValueUnitPair in project soot by Sable.
the class Shimple method redirectToPreds.
/**
* If you are removing a Unit from a Unit chain which contains
* PhiExpr's, you might want to call this utility function in
* order to update any PhiExpr pointers to the Unit to point to
* the Unit's predecessor(s). This function will not modify
* "branch target" UnitBoxes.
*
* <p> Normally you should not have to call this function
* directly, since patching is taken care of Shimple's internal
* implementation of PatchingChain.
*/
public static void redirectToPreds(Body body, Unit remove) {
boolean debug = Options.v().debug();
if (body instanceof ShimpleBody)
debug |= ((ShimpleBody) body).getOptions().debug();
Chain<Unit> units = body.getUnits();
/* Determine whether we should continue processing or not. */
List<UnitBox> boxesPointingToThis = remove.getBoxesPointingToThis();
if (boxesPointingToThis.isEmpty())
return;
for (UnitBox pointer : boxesPointingToThis) {
// continue iteration from where we left off.
if (!pointer.isBranchTarget())
break;
}
/* Ok, continuing... */
Set<Unit> preds = new HashSet<Unit>();
Set<PhiExpr> phis = new HashSet<PhiExpr>();
// find fall-through pred
if (!remove.equals(units.getFirst())) {
Unit possiblePred = (Unit) units.getPredOf(remove);
if (possiblePred.fallsThrough())
preds.add(possiblePred);
}
// find the rest of the preds and all Phi's that point to remove
for (Unit unit : units) {
for (UnitBox targetBox : unit.getUnitBoxes()) {
if (remove.equals(targetBox.getUnit())) {
if (targetBox.isBranchTarget())
preds.add(unit);
else {
PhiExpr phiExpr = Shimple.getPhiExpr(unit);
if (phiExpr != null)
phis.add(phiExpr);
}
}
}
}
if (phis.size() == 0) {
if (debug)
logger.warn("Orphaned UnitBoxes to " + remove + "? Shimple.redirectToPreds is giving up.");
return;
}
if (preds.size() == 0) {
if (debug)
logger.warn("Shimple.redirectToPreds couldn't find any predecessors for " + remove + " in " + body.getMethod() + ".");
if (!remove.equals(units.getFirst())) {
Unit pred = (Unit) units.getPredOf(remove);
if (debug)
logger.warn("Falling back to immediate chain predecessor: " + pred + ".");
preds.add(pred);
} else if (!remove.equals(units.getLast())) {
Unit succ = (Unit) units.getSuccOf(remove);
if (debug)
logger.warn("Falling back to immediate chain successor: " + succ + ".");
preds.add(succ);
} else
throw new RuntimeException("Assertion failed.");
}
/* At this point we have found all the preds and relevant Phi's */
/* Each Phi needs an argument for each pred. */
Iterator<PhiExpr> phiIt = phis.iterator();
while (phiIt.hasNext()) {
PhiExpr phiExpr = phiIt.next();
ValueUnitPair argBox = phiExpr.getArgBox(remove);
if (argBox == null)
throw new RuntimeException("Assertion failed.");
// now we've got the value!
Value arg = argBox.getValue();
phiExpr.removeArg(argBox);
// add new arguments to Phi
Iterator<Unit> predsIt = preds.iterator();
while (predsIt.hasNext()) {
Unit pred = predsIt.next();
phiExpr.addArg(arg, pred);
}
}
}