/* Soot - a J*va Optimization Framework
* Copyright (C) 2003 Navindra Umanee <navindra@cs.mcgill.ca>
*
* This library 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 library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package soot.shimple.toolkits.scalar;
import soot.*;
import soot.util.*;
import soot.jimple.*;
import soot.shimple.*;
import soot.jimple.toolkits.scalar.*;
import java.util.*;
/**
* 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<Value> 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 <code>op</code> if it is easy to
* find the constant value; else returns <code>null</code>.
**/
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.
*
* <p> 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<Value> 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<Local, Constant> 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.");
}
}
}