use of soot.jimple.AssignStmt in project soot by Sable.
the class AccessManager method createSetAccessor.
private static void createSetAccessor(SootMethod container, AssignStmt as, FieldRef ref) {
java.util.List parameterTypes = new LinkedList();
java.util.List<SootClass> thrownExceptions = new LinkedList<SootClass>();
Body accessorBody = Jimple.v().newBody();
soot.util.Chain accStmts = accessorBody.getUnits();
LocalGenerator lg = new LocalGenerator(accessorBody);
Body containerBody = container.getActiveBody();
soot.util.Chain containerStmts = containerBody.getUnits();
SootClass target = ref.getField().getDeclaringClass();
SootMethod accessor;
String name = createAccessorName(ref.getField(), true);
accessor = target.getMethodByNameUnsafe(name);
if (accessor == null) {
Local thisLocal = lg.generateLocal(target.getType());
int paramID = 0;
if (ref instanceof InstanceFieldRef) {
accStmts.add(Jimple.v().newIdentityStmt(thisLocal, Jimple.v().newParameterRef(target.getType(), paramID)));
parameterTypes.add(target.getType());
paramID++;
}
parameterTypes.add(ref.getField().getType());
Local l = lg.generateLocal(ref.getField().getType());
accStmts.add(Jimple.v().newIdentityStmt(l, Jimple.v().newParameterRef(ref.getField().getType(), paramID)));
paramID++;
if (ref instanceof InstanceFieldRef) {
accStmts.add(Jimple.v().newAssignStmt(Jimple.v().newInstanceFieldRef(thisLocal, ref.getFieldRef()), l));
} else {
accStmts.add(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(ref.getFieldRef()), l));
}
accStmts.addLast(Jimple.v().newReturnVoidStmt());
Type returnType = VoidType.v();
accessor = Scene.v().makeSootMethod(name, parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC, thrownExceptions);
accessorBody.setMethod(accessor);
accessor.setActiveBody(accessorBody);
target.addMethod(accessor);
}
java.util.List args = new LinkedList();
if (ref instanceof InstanceFieldRef) {
args.add(((InstanceFieldRef) ref).getBase());
}
args.add(as.getRightOp());
InvokeExpr newExpr = Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
Stmt newStmt = Jimple.v().newInvokeStmt(newExpr);
containerStmts.insertAfter(newStmt, as);
containerStmts.remove(as);
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class SiteInliner method inlineSite.
/**
* Inlines the given site. Note that this method does
* not actually check if it's safe (with respect to access modifiers and special invokes)
* for it to be inlined. That functionality is handled by the InlinerSafetyManager.
*/
public static List inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container, Map options) {
boolean enableNullPointerCheckInsertion = PhaseOptions.getBoolean(options, "insert-null-checks");
boolean enableRedundantCastInsertion = PhaseOptions.getBoolean(options, "insert-redundant-casts");
Hierarchy hierarchy = Scene.v().getActiveHierarchy();
JimpleBody containerB = (JimpleBody) container.getActiveBody();
Chain<Unit> containerUnits = containerB.getUnits();
if (!(inlinee.getDeclaringClass().isApplicationClass() || inlinee.getDeclaringClass().isLibraryClass()))
return null;
Body inlineeB = inlinee.getActiveBody();
Chain<Unit> inlineeUnits = inlineeB.getUnits();
InvokeExpr ie = toInline.getInvokeExpr();
Value thisToAdd = null;
if (ie instanceof InstanceInvokeExpr)
thisToAdd = ((InstanceInvokeExpr) ie).getBase();
// Insert casts to please the verifier.
{
boolean targetUsesThis = true;
if (enableRedundantCastInsertion && ie instanceof InstanceInvokeExpr && targetUsesThis) {
// The verifier will complain if targetUsesThis, and:
// the argument passed to the method is not the same type.
// For instance, Bottle.price_static takes a cost.
// Cost is an interface implemented by Bottle.
SootClass localType, parameterType;
localType = ((RefType) ((InstanceInvokeExpr) ie).getBase().getType()).getSootClass();
parameterType = inlinee.getDeclaringClass();
if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
containerB.getLocals().add(castee);
containerB.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), toInline);
thisToAdd = castee;
}
}
}
// (If enabled), add a null pointer check.
{
if (enableNullPointerCheckInsertion && ie instanceof InstanceInvokeExpr) {
boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB);
/* Ah ha. Caught again! */
if (caught) {
/* In this case, we don't use throwPoint;
* instead, put the code right there. */
Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), toInline);
containerB.getUnits().insertBefore(insertee, toInline);
// This sucks (but less than before).
((IfStmt) insertee).setTarget(toInline);
ThrowManager.addThrowAfter(containerB, insertee);
} else {
Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(containerB);
containerB.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), toInline);
}
}
}
// Add synchronizing stuff.
{
if (inlinee.isSynchronized()) {
// Need to get the class object if ie is a static invoke.
if (ie instanceof InstanceInvokeExpr)
SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, (Local) ((InstanceInvokeExpr) ie).getBase());
else {
// synchronization.
if (!container.getDeclaringClass().isInterface()) {
// Whew!
Local l = SynchronizerManager.v().addStmtsToFetchClassBefore(containerB, toInline);
SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, l);
}
}
}
}
Stmt exitPoint = (Stmt) containerUnits.getSuccOf(toInline);
// First, clone all of the inlinee's units & locals.
HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
HashMap<Stmt, Stmt> oldUnitsToNew = new HashMap<Stmt, Stmt>();
{
Stmt cursor = toInline;
for (Iterator<Unit> currIt = inlineeUnits.iterator(); currIt.hasNext(); ) {
final Stmt curr = (Stmt) currIt.next();
Stmt currPrime = (Stmt) curr.clone();
if (currPrime == null)
throw new RuntimeException("getting null from clone!");
currPrime.addAllTagsOf(curr);
containerUnits.insertAfter(currPrime, cursor);
cursor = currPrime;
oldUnitsToNew.put(curr, currPrime);
}
for (Iterator<Local> lIt = inlineeB.getLocals().iterator(); lIt.hasNext(); ) {
final Local l = lIt.next();
Local lPrime = (Local) l.clone();
if (lPrime == null)
throw new RuntimeException("getting null from local clone!");
containerB.getLocals().add(lPrime);
oldLocalsToNew.put(l, lPrime);
}
}
// Backpatch the newly-inserted units using newly-constructed maps.
{
Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
while (it.hasNext()) {
Stmt patchee = (Stmt) it.next();
for (ValueBox box : patchee.getUseAndDefBoxes()) {
if (!(box.getValue() instanceof Local))
continue;
Local lPrime = oldLocalsToNew.get(box.getValue());
if (lPrime != null)
box.setValue(lPrime);
else
throw new RuntimeException("local has no clone!");
}
for (UnitBox box : patchee.getUnitBoxes()) {
Unit uPrime = (oldUnitsToNew.get(box.getUnit()));
if (uPrime != null)
box.setUnit(uPrime);
else
throw new RuntimeException("inlined stmt has no clone!");
}
}
}
// Copy & backpatch the traps; preserve their same order.
{
Trap prevTrap = null;
for (Trap t : inlineeB.getTraps()) {
Stmt newBegin = oldUnitsToNew.get(t.getBeginUnit()), newEnd = oldUnitsToNew.get(t.getEndUnit()), newHandler = oldUnitsToNew.get(t.getHandlerUnit());
if (newBegin == null || newEnd == null || newHandler == null)
throw new RuntimeException("couldn't map trap!");
Trap trap = Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler);
if (prevTrap == null)
containerB.getTraps().addFirst(trap);
else
containerB.getTraps().insertAfter(trap, prevTrap);
prevTrap = trap;
}
}
// Handle identity stmt's and returns.
{
Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
ArrayList<Unit> cuCopy = new ArrayList<Unit>();
while (it.hasNext()) {
cuCopy.add(it.next());
}
for (Unit u : cuCopy) {
Stmt s = (Stmt) u;
if (s instanceof IdentityStmt) {
IdentityRef rhs = (IdentityRef) ((IdentityStmt) s).getRightOp();
if (rhs instanceof CaughtExceptionRef)
continue;
else if (rhs instanceof ThisRef) {
if (!(ie instanceof InstanceInvokeExpr))
throw new RuntimeException("thisref with no receiver!");
containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), thisToAdd));
} else if (rhs instanceof ParameterRef) {
ParameterRef pref = (ParameterRef) rhs;
containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), ie.getArg(pref.getIndex())));
}
} else if (s instanceof ReturnStmt) {
if (toInline instanceof InvokeStmt) {
// munch, munch.
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
continue;
}
if (!(toInline instanceof AssignStmt))
throw new RuntimeException("invoking stmt neither InvokeStmt nor AssignStmt!??!?!");
Value ro = ((ReturnStmt) s).getOp();
Value lhs = ((AssignStmt) toInline).getLeftOp();
AssignStmt as = Jimple.v().newAssignStmt(lhs, ro);
containerUnits.insertBefore(as, s);
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
} else if (s instanceof ReturnVoidStmt)
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
}
}
List<Unit> newStmts = new ArrayList<Unit>();
for (Iterator<Unit> i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext(); ) {
newStmts.add(i.next());
}
// Remove the original statement toInline.
containerUnits.remove(toInline);
// Resolve name collisions.
LocalNameStandardizer.v().transform(containerB, "ji.lns");
return newStmts;
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class IFDSLocalInfoFlow method createFlowFunctionsFactory.
public FlowFunctions<Unit, Local, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Local, SootMethod>() {
@Override
public FlowFunction<Local> getNormalFlowFunction(Unit src, Unit dest) {
if (src instanceof IdentityStmt && interproceduralCFG().getMethodOf(src) == Scene.v().getMainMethod()) {
IdentityStmt is = (IdentityStmt) src;
Local leftLocal = (Local) is.getLeftOp();
Value right = is.getRightOp();
if (right instanceof ParameterRef) {
return new Gen<Local>(leftLocal, zeroValue());
}
}
if (src instanceof AssignStmt) {
AssignStmt assignStmt = (AssignStmt) src;
Value right = assignStmt.getRightOp();
if (assignStmt.getLeftOp() instanceof Local) {
final Local leftLocal = (Local) assignStmt.getLeftOp();
if (right instanceof Local) {
final Local rightLocal = (Local) right;
return new Transfer<Local>(leftLocal, rightLocal);
} else {
return new Kill<Local>(leftLocal);
}
}
}
return Identity.v();
}
@Override
public FlowFunction<Local> getCallFlowFunction(Unit src, final SootMethod dest) {
Stmt s = (Stmt) src;
InvokeExpr ie = s.getInvokeExpr();
final List<Value> callArgs = ie.getArgs();
final List<Local> paramLocals = new ArrayList<Local>();
for (int i = 0; i < dest.getParameterCount(); i++) {
paramLocals.add(dest.getActiveBody().getParameterLocal(i));
}
return new FlowFunction<Local>() {
public Set<Local> computeTargets(Local source) {
// ignore implicit calls to static initializers
if (dest.getName().equals(SootMethod.staticInitializerName) && dest.getParameterCount() == 0)
return Collections.emptySet();
Set<Local> taintsInCaller = new HashSet<Local>();
for (int i = 0; i < callArgs.size(); i++) {
if (callArgs.get(i).equivTo(source)) {
taintsInCaller.add(paramLocals.get(i));
}
}
return taintsInCaller;
}
};
}
@Override
public FlowFunction<Local> getReturnFlowFunction(Unit callSite, SootMethod callee, Unit exitStmt, Unit retSite) {
if (exitStmt instanceof ReturnStmt) {
ReturnStmt returnStmt = (ReturnStmt) exitStmt;
Value op = returnStmt.getOp();
if (op instanceof Local) {
if (callSite instanceof DefinitionStmt) {
DefinitionStmt defnStmt = (DefinitionStmt) callSite;
Value leftOp = defnStmt.getLeftOp();
if (leftOp instanceof Local) {
final Local tgtLocal = (Local) leftOp;
final Local retLocal = (Local) op;
return new FlowFunction<Local>() {
public Set<Local> computeTargets(Local source) {
if (source == retLocal)
return Collections.singleton(tgtLocal);
return Collections.emptySet();
}
};
}
}
}
}
return KillAll.v();
}
@Override
public FlowFunction<Local> getCallToReturnFlowFunction(Unit call, Unit returnSite) {
return Identity.v();
}
};
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class ConstantCastEliminator method internalTransform.
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
// Check for all assignments that perform casts on primitive constants
for (Unit u : b.getUnits()) {
if (u instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) u;
if (assign.getRightOp() instanceof CastExpr) {
CastExpr ce = (CastExpr) assign.getRightOp();
if (ce.getOp() instanceof Constant) {
// a = (float) 42
if (ce.getType() instanceof FloatType && ce.getOp() instanceof IntConstant) {
IntConstant it = (IntConstant) ce.getOp();
assign.setRightOp(FloatConstant.v(it.value));
} else // a = (double) 42
if (ce.getType() instanceof DoubleType && ce.getOp() instanceof IntConstant) {
IntConstant it = (IntConstant) ce.getOp();
assign.setRightOp(DoubleConstant.v(it.value));
}
}
}
}
}
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class CopyPropagator method internalTransform.
/**
* Cascaded copy propagator.
*
* If it encounters situations of the form: A: a = ...; B: ... x = a; C:...
* use (x); where a has only one definition, and x has only one definition
* (B), then it can propagate immediately without checking between B and C
* for redefinitions of a (namely) A because they cannot occur. In this case
* the propagator is global.
*
* Otherwise, if a has multiple definitions then it only checks for
* redefinitions of Propagates constants and copies in extended basic
* blocks.
*
* Does not propagate stack locals when the "only-regular-locals" option is
* true.
*/
protected void internalTransform(Body b, String phaseName, Map<String, String> opts) {
CPOptions options = new CPOptions(opts);
StmtBody stmtBody = (StmtBody) b;
int fastCopyPropagationCount = 0;
int slowCopyPropagationCount = 0;
if (Options.v().verbose())
logger.debug("[" + stmtBody.getMethod().getName() + "] Propagating copies...");
if (Options.v().time())
Timers.v().propagatorTimer.start();
Chain<Unit> units = stmtBody.getUnits();
Map<Local, Integer> localToDefCount = new HashMap<Local, Integer>();
// Count number of definitions for each local.
for (Unit u : units) {
Stmt s = (Stmt) u;
if (s instanceof DefinitionStmt && ((DefinitionStmt) s).getLeftOp() instanceof Local) {
Local l = (Local) ((DefinitionStmt) s).getLeftOp();
if (!localToDefCount.containsKey(l))
localToDefCount.put(l, new Integer(1));
else
localToDefCount.put(l, new Integer(localToDefCount.get(l).intValue() + 1));
}
}
if (throwAnalysis == null)
throwAnalysis = Scene.v().getDefaultThrowAnalysis();
if (forceOmitExceptingUnitEdges == false)
forceOmitExceptingUnitEdges = Options.v().omit_excepting_unit_edges();
// Go through the definitions, building the webs
UnitGraph graph = new ExceptionalUnitGraph(stmtBody, throwAnalysis, forceOmitExceptingUnitEdges);
LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(graph);
// Perform a local propagation pass.
{
Iterator<Unit> stmtIt = (new PseudoTopologicalOrderer<Unit>()).newList(graph, false).iterator();
while (stmtIt.hasNext()) {
Stmt stmt = (Stmt) stmtIt.next();
for (ValueBox useBox : stmt.getUseBoxes()) {
if (useBox.getValue() instanceof Local) {
Local l = (Local) useBox.getValue();
// null due to typing, we always inline that constant.
if (!(l.getType() instanceof NullType)) {
if (options.only_regular_locals() && l.getName().startsWith("$"))
continue;
if (options.only_stack_locals() && !l.getName().startsWith("$"))
continue;
}
List<Unit> defsOfUse = localDefs.getDefsOfAt(l, stmt);
// We can propagate the definition if we either only
// have
// one definition or all definitions are side-effect
// free
// and equal. For starters, we only support constants in
// the case of multiple definitions.
boolean propagateDef = defsOfUse.size() == 1;
if (!propagateDef && defsOfUse.size() > 0) {
boolean agrees = true;
Constant constVal = null;
for (Unit defUnit : defsOfUse) {
boolean defAgrees = false;
if (defUnit instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) defUnit;
if (assign.getRightOp() instanceof Constant) {
if (constVal == null) {
constVal = (Constant) assign.getRightOp();
defAgrees = true;
} else if (constVal.equals(assign.getRightOp()))
defAgrees = true;
}
}
agrees &= defAgrees;
}
propagateDef = agrees;
}
if (propagateDef) {
DefinitionStmt def = (DefinitionStmt) defsOfUse.get(0);
if (def.getRightOp() instanceof Constant) {
if (useBox.canContainValue(def.getRightOp())) {
useBox.setValue(def.getRightOp());
}
} else if (def.getRightOp() instanceof CastExpr) {
CastExpr ce = (CastExpr) def.getRightOp();
if (ce.getCastType() instanceof RefLikeType) {
boolean isConstNull = ce.getOp() instanceof IntConstant && ((IntConstant) ce.getOp()).value == 0;
isConstNull |= ce.getOp() instanceof LongConstant && ((LongConstant) ce.getOp()).value == 0;
if (isConstNull) {
if (useBox.canContainValue(NullConstant.v())) {
useBox.setValue(NullConstant.v());
}
}
}
} else if (def.getRightOp() instanceof Local) {
Local m = (Local) def.getRightOp();
if (l != m) {
Integer defCount = localToDefCount.get(m);
if (defCount == null || defCount == 0)
throw new RuntimeException("Variable " + m + " used without definition!");
if (defCount == 1) {
useBox.setValue(m);
fastCopyPropagationCount++;
continue;
}
List<Unit> path = graph.getExtendedBasicBlockPathBetween(def, stmt);
if (path == null) {
// no path in the extended basic block
continue;
}
Iterator<Unit> pathIt = path.iterator();
// Skip first node
pathIt.next();
// Make sure that m is not redefined along
// path
{
boolean isRedefined = false;
while (pathIt.hasNext()) {
Stmt s = (Stmt) pathIt.next();
if (stmt == s) {
break;
}
if (s instanceof DefinitionStmt) {
if (((DefinitionStmt) s).getLeftOp() == m) {
isRedefined = true;
break;
}
}
}
if (isRedefined)
continue;
}
useBox.setValue(m);
slowCopyPropagationCount++;
}
}
}
}
}
}
}
if (Options.v().verbose())
logger.debug("[" + stmtBody.getMethod().getName() + "] Propagated: " + fastCopyPropagationCount + " fast copies " + slowCopyPropagationCount + " slow copies");
if (Options.v().time())
Timers.v().propagatorTimer.end();
}
Aggregations