use of soot.jimple.Constant in project soot by Sable.
the class IFDSPossibleTypes method createFlowFunctionsFactory.
public FlowFunctions<Unit, Pair<Value, Type>, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Pair<Value, Type>, SootMethod>() {
public FlowFunction<Pair<Value, Type>> getNormalFlowFunction(Unit src, Unit dest) {
if (src instanceof DefinitionStmt) {
DefinitionStmt defnStmt = (DefinitionStmt) src;
if (defnStmt.containsInvokeExpr())
return Identity.v();
final Value right = defnStmt.getRightOp();
final Value left = defnStmt.getLeftOp();
// won't track primitive-typed variables
if (right.getType() instanceof PrimType)
return Identity.v();
if (right instanceof Constant || right instanceof NewExpr) {
return new FlowFunction<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
if (source == zeroValue()) {
Set<Pair<Value, Type>> res = new LinkedHashSet<Pair<Value, Type>>();
res.add(new Pair<Value, Type>(left, right.getType()));
res.add(zeroValue());
return res;
} else if (source.getO1() instanceof Local && source.getO1().equivTo(left)) {
// strong update for local variables
return Collections.emptySet();
} else {
return Collections.singleton(source);
}
}
};
} else if (right instanceof Ref || right instanceof Local) {
return new FlowFunction<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(final Pair<Value, Type> source) {
Value value = source.getO1();
if (source.getO1() instanceof Local && source.getO1().equivTo(left)) {
// strong update for local variables
return Collections.emptySet();
} else if (maybeSameLocation(value, right)) {
return new LinkedHashSet<Pair<Value, Type>>() {
{
add(new Pair<Value, Type>(left, source.getO2()));
add(source);
}
};
} else {
return Collections.singleton(source);
}
}
private boolean maybeSameLocation(Value v1, Value v2) {
if (!(v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) && !(v1 instanceof ArrayRef && v2 instanceof ArrayRef)) {
return v1.equivTo(v2);
}
if (v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) {
InstanceFieldRef ifr1 = (InstanceFieldRef) v1;
InstanceFieldRef ifr2 = (InstanceFieldRef) v2;
if (!ifr1.getField().getName().equals(ifr2.getField().getName()))
return false;
Local base1 = (Local) ifr1.getBase();
Local base2 = (Local) ifr2.getBase();
PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
PointsToSet pts1 = pta.reachingObjects(base1);
PointsToSet pts2 = pta.reachingObjects(base2);
return pts1.hasNonEmptyIntersection(pts2);
} else {
// v1 instanceof ArrayRef && v2 instanceof ArrayRef
ArrayRef ar1 = (ArrayRef) v1;
ArrayRef ar2 = (ArrayRef) v2;
Local base1 = (Local) ar1.getBase();
Local base2 = (Local) ar2.getBase();
PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
PointsToSet pts1 = pta.reachingObjects(base1);
PointsToSet pts2 = pta.reachingObjects(base2);
return pts1.hasNonEmptyIntersection(pts2);
}
}
};
}
}
return Identity.v();
}
public FlowFunction<Pair<Value, Type>> getCallFlowFunction(final Unit src, final SootMethod dest) {
Stmt stmt = (Stmt) src;
InvokeExpr ie = stmt.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<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
if (!dest.getName().equals("<clinit>") && !dest.getSubSignature().equals("void run()")) {
Value value = source.getO1();
int argIndex = callArgs.indexOf(value);
if (argIndex > -1) {
return Collections.singleton(new Pair<Value, Type>(paramLocals.get(argIndex), source.getO2()));
}
}
return Collections.emptySet();
}
};
}
public FlowFunction<Pair<Value, Type>> 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<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
if (source == retLocal)
return Collections.singleton(new Pair<Value, Type>(tgtLocal, source.getO2()));
return Collections.emptySet();
}
};
}
}
}
}
return KillAll.v();
}
public FlowFunction<Pair<Value, Type>> getCallToReturnFlowFunction(Unit call, Unit returnSite) {
return Identity.v();
}
};
}
use of soot.jimple.Constant in project soot by Sable.
the class LocalMayAliasAnalysis method flowThrough.
@Override
protected void flowThrough(Set<Set<Value>> source, Unit unit, Set<Set<Value>> target) {
target.addAll(source);
if (unit instanceof DefinitionStmt) {
DefinitionStmt def = (DefinitionStmt) unit;
Value left = def.getLeftOp();
Value right = def.getRightOp();
if (right instanceof Constant) {
// find the sets containing the left
Set<Value> leftSet = null;
for (Set<Value> s : source) {
if (s.contains(left)) {
leftSet = s;
break;
}
}
if (leftSet == null)
throw new RuntimeException("internal error");
// remove left from this set
target.remove(leftSet);
HashSet<Value> setWithoutLeft = new HashSet<Value>(leftSet);
setWithoutLeft.remove(left);
target.add(setWithoutLeft);
// add left on its own
target.add(Collections.singleton(left));
} else {
// find the sets containing the left and right hand sides
Set<Value> leftSet = null, rightSet = null;
for (Set<Value> s : source) {
if (s.contains(left)) {
leftSet = s;
break;
}
}
for (Set<Value> s : source) {
if (s.contains(right)) {
rightSet = s;
break;
}
}
if (leftSet == null || rightSet == null)
throw new RuntimeException("internal error");
// replace the sets by their union
target.remove(leftSet);
target.remove(rightSet);
HashSet<Value> union = new HashSet<Value>(leftSet);
union.addAll(rightSet);
target.add(union);
}
}
}
use of soot.jimple.Constant 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.Constant 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();
}
use of soot.jimple.Constant in project soot by Sable.
the class UseChecker method caseAssignStmt.
public void caseAssignStmt(AssignStmt stmt) {
Value lhs = stmt.getLeftOp();
Value rhs = stmt.getRightOp();
Type tlhs = null;
if (lhs instanceof Local)
tlhs = this.tg.get((Local) lhs);
else if (lhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) lhs;
Local base = (Local) aref.getBase();
// Try to force Type integrity. The left side must agree on the
// element type of the right side array reference.
ArrayType at = null;
Type tgType = this.tg.get(base);
if (tgType instanceof ArrayType)
at = (ArrayType) tgType;
else {
// is java.lang.Object
if (tgType == Scene.v().getObjectType() && rhs instanceof Local) {
Type rhsType = this.tg.get((Local) rhs);
if (rhsType instanceof PrimType) {
if (defs == null) {
defs = LocalDefs.Factory.newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
}
// Check the original type of the array from the alloc site
for (Unit defU : defs.getDefsOfAt(base, stmt)) {
if (defU instanceof AssignStmt) {
AssignStmt defUas = (AssignStmt) defU;
if (defUas.getRightOp() instanceof NewArrayExpr) {
at = (ArrayType) defUas.getRightOp().getType();
break;
}
}
}
}
}
if (at == null)
at = tgType.makeArrayType();
}
tlhs = ((ArrayType) at).getElementType();
this.handleArrayRef(aref, stmt);
aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setLeftOp(this.uv.visit(lhs, tlhs, stmt));
} else if (lhs instanceof FieldRef) {
tlhs = ((FieldRef) lhs).getFieldRef().type();
if (lhs instanceof InstanceFieldRef)
this.handleInstanceFieldRef((InstanceFieldRef) lhs, stmt);
}
// They may have been changed above
lhs = stmt.getLeftOp();
rhs = stmt.getRightOp();
if (rhs instanceof Local)
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
else if (rhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) rhs;
Local base = (Local) aref.getBase();
// try to force Type integrity
ArrayType at = null;
Type et = null;
if (this.tg.get(base) instanceof ArrayType)
at = (ArrayType) this.tg.get(base);
else {
Type bt = this.tg.get(base);
// For some fixed type T, we assume that we can fix the array to T[].
if (bt instanceof RefType || bt instanceof NullType) {
RefType rt = bt instanceof NullType ? null : (RefType) bt;
if (rt == null || rt.getSootClass().getName().equals("java.lang.Object") || rt.getSootClass().getName().equals("java.io.Serializable") || rt.getSootClass().getName().equals("java.lang.Cloneable")) {
if (defs == null) {
defs = LocalDefs.Factory.newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
}
outer: for (UnitValueBoxPair usePair : uses.getUsesOf(stmt)) {
Stmt useStmt = (Stmt) usePair.getUnit();
// from the callee's signature=
if (useStmt.containsInvokeExpr()) {
for (int i = 0; i < useStmt.getInvokeExpr().getArgCount(); i++) {
if (useStmt.getInvokeExpr().getArg(i) == usePair.getValueBox().getValue()) {
et = useStmt.getInvokeExpr().getMethod().getParameterType(i);
at = et.makeArrayType();
break outer;
}
}
} else // if the other value is a primitive.
if (useStmt instanceof IfStmt) {
IfStmt ifStmt = (IfStmt) useStmt;
if (ifStmt.getCondition() instanceof EqExpr) {
EqExpr expr = (EqExpr) ifStmt.getCondition();
final Value other;
if (expr.getOp1() == usePair.getValueBox().getValue())
other = expr.getOp2();
else
other = expr.getOp1();
Type newEt = getTargetType(other);
if (newEt != null)
et = newEt;
}
} else if (useStmt instanceof AssignStmt) {
// For binary expressions, we can look for type information in the
// other operands
AssignStmt useAssignStmt = (AssignStmt) useStmt;
if (useAssignStmt.getRightOp() instanceof BinopExpr) {
BinopExpr binOp = (BinopExpr) useAssignStmt.getRightOp();
final Value other;
if (binOp.getOp1() == usePair.getValueBox().getValue())
other = binOp.getOp2();
else
other = binOp.getOp1();
Type newEt = getTargetType(other);
if (newEt != null)
et = newEt;
}
} else if (useStmt instanceof ReturnStmt) {
et = jb.getMethod().getReturnType();
}
}
}
}
if (at == null)
at = et.makeArrayType();
}
Type trhs = ((ArrayType) at).getElementType();
this.handleArrayRef(aref, stmt);
aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, trhs, stmt));
} else if (rhs instanceof InstanceFieldRef) {
this.handleInstanceFieldRef((InstanceFieldRef) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof BinopExpr)
this.handleBinopExpr((BinopExpr) rhs, stmt, tlhs);
else if (rhs instanceof InvokeExpr) {
this.handleInvokeExpr((InvokeExpr) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof CastExpr)
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
else if (rhs instanceof InstanceOfExpr) {
InstanceOfExpr ioe = (InstanceOfExpr) rhs;
ioe.setOp(this.uv.visit(ioe.getOp(), RefType.v("java.lang.Object"), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) rhs;
nae.setSize(this.uv.visit(nae.getSize(), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) rhs;
for (int i = 0; i < nmae.getSizeCount(); i++) nmae.setSize(i, this.uv.visit(nmae.getSize(i), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof LengthExpr) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NegExpr) {
((NegExpr) rhs).setOp(this.uv.visit(((NegExpr) rhs).getOp(), tlhs, stmt));
} else if (rhs instanceof Constant)
if (!(rhs instanceof NullConstant))
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
}
Aggregations