soot.shimple.toolkits.scalar.SEvaluator Maven / Gradle / Ivy
package soot.shimple.toolkits.scalar;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2003 Navindra Umanee
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.Iterator;
import java.util.Map;
import soot.Local;
import soot.Type;
import soot.UnitBoxOwner;
import soot.UnknownType;
import soot.Value;
import soot.ValueBox;
import soot.jimple.Constant;
import soot.jimple.Expr;
import soot.jimple.toolkits.scalar.Evaluator;
import soot.shimple.PhiExpr;
import soot.util.Switch;
/**
* Extension of soot.jimple.toolkits.scalar.Evaluator to handle Phi expressions.
*
* @author Navindra Umanee.
* @see soot.jimple.toolkits.scalar.Evaluator
* @see SConstantPropagatorAndFolder
**/
public class SEvaluator {
/**
* Returns true if given value is determined to be constant valued, false otherwise
**/
public static boolean isValueConstantValued(Value op) {
if (op instanceof PhiExpr) {
Iterator argsIt = ((PhiExpr) op).getValues().iterator();
Constant firstConstant = null;
while (argsIt.hasNext()) {
Value arg = argsIt.next();
if (!(arg instanceof Constant)) {
return false;
}
if (firstConstant == null) {
firstConstant = (Constant) arg;
} else if (!firstConstant.equals(arg)) {
return false;
}
}
return true;
}
return Evaluator.isValueConstantValued(op);
}
/**
* Returns the constant value of op
if it is easy to find the constant value; else returns null
.
**/
public static Value getConstantValueOf(Value op) {
if (!(op instanceof PhiExpr)) {
return Evaluator.getConstantValueOf(op);
}
if (!(isValueConstantValued(op))) {
return null;
}
return ((PhiExpr) op).getValue(0);
}
/**
* If a normal expression contains Bottom, always return Bottom. Otherwise, if a normal expression contains Top, returns
* Top. Else determine the constant value of the expression if possible, if not return Bottom.
*
*
* If a Phi expression contains Bottom, always return Bottom. Otherwise, if all the constant arguments are the same
* (ignoring Top and locals) return that constant or Top if no concrete constant is present, else return Bottom.
*
* @see SEvaluator.TopConstant
* @see SEvaluator.BottomConstant
**/
public static Constant getFuzzyConstantValueOf(Value v) {
if (v instanceof Constant) {
return (Constant) v;
}
if (v instanceof Local) {
return BottomConstant.v();
}
if (!(v instanceof Expr)) {
return BottomConstant.v();
}
Expr expr = (Expr) v;
Constant constant = null;
if (expr instanceof PhiExpr) {
PhiExpr phi = (PhiExpr) expr;
Iterator argsIt = phi.getValues().iterator();
while (argsIt.hasNext()) {
Value arg = argsIt.next();
if (!(arg instanceof Constant)) {
continue;
}
if (arg instanceof TopConstant) {
continue;
}
if (constant == null) {
constant = (Constant) arg;
} else if (!constant.equals(arg)) {
constant = BottomConstant.v();
break;
}
}
if (constant == null) {
constant = TopConstant.v();
}
} else {
Iterator valueBoxesIt = expr.getUseBoxes().iterator();
while (valueBoxesIt.hasNext()) {
Value value = ((ValueBox) valueBoxesIt.next()).getValue();
if (value instanceof BottomConstant) {
constant = BottomConstant.v();
break;
}
if (value instanceof TopConstant) {
constant = TopConstant.v();
}
}
if (constant == null) {
constant = (Constant) getConstantValueOf(expr);
}
if (constant == null) {
constant = BottomConstant.v();
}
}
return constant;
}
/**
* Get the constant value of the expression given the assumptions in the localToConstant map (may contain Top and Bottom).
* Does not change expression.
*
* @see SEvaluator.TopConstant
* @see SEvaluator.BottomConstant
**/
public static Constant getFuzzyConstantValueOf(Value v, Map localToConstant) {
if (v instanceof Constant) {
return (Constant) v;
}
if (v instanceof Local) {
return localToConstant.get(v);
}
if (!(v instanceof Expr)) {
return BottomConstant.v();
}
/* clone expr and update the clone with our assumptions */
Expr expr = (Expr) v.clone();
Iterator useBoxIt = expr.getUseBoxes().iterator();
while (useBoxIt.hasNext()) {
ValueBox useBox = (ValueBox) useBoxIt.next();
Value use = useBox.getValue();
if (use instanceof Local) {
Constant constant = localToConstant.get(use);
if (useBox.canContainValue(constant)) {
useBox.setValue(constant);
}
}
}
// oops -- clear spurious pointers to the unit chain!
if (expr instanceof UnitBoxOwner) {
((UnitBoxOwner) expr).clearUnitBoxes();
}
/* evaluate the expression */
return (getFuzzyConstantValueOf(expr));
}
/**
* Head of a new hierarchy of constants -- Top and Bottom.
**/
public static abstract class MetaConstant extends Constant {
}
/**
* Top i.e. assumed to be a constant, but of unknown value.
**/
public static class TopConstant extends MetaConstant {
private static final TopConstant constant = new TopConstant();
private TopConstant() {
}
public static Constant v() {
return constant;
}
public Type getType() {
return UnknownType.v();
}
public void apply(Switch sw) {
throw new RuntimeException("Not implemented.");
}
}
/**
* Bottom i.e. known not to be a constant.
**/
public static class BottomConstant extends MetaConstant {
private static final BottomConstant constant = new BottomConstant();
private BottomConstant() {
}
public static Constant v() {
return constant;
}
public Type getType() {
return UnknownType.v();
}
public void apply(Switch sw) {
throw new RuntimeException("Not implemented.");
}
}
}