/* Soot - a J*va Optimization Framework
* Copyright (C) 2002 Florian Loitsch
*
* 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.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.jimple.toolkits.scalar.pre;
import soot.jimple.*;
import soot.*;
/**
* Allows easy filtering/wrapping of Soot objects. Operations that are done
* very often are grouped here.
*/
public class SootFilter {
/**
* wraps a value into a EquivalentValue.
* returns <code>null</code> if <code>val</code> is null.
*
* @param val the Value to wrap.
* @return the EquivalentValue containing val.
*/
public static EquivalentValue equiVal(Value val) {
if (val == null) return null;
return new EquivalentValue(val);
}
/**
* filters out the RHS of an assignmentStmt.
*
* @param unit a Unit from which to extract the RHS.
* @return the RHS-Value of <code>unit</code> or <code>null</code> if
* <code>unit</code> wasn't an assignment-stmt.
*/
public static Value rhs(Unit unit) {
if (unit instanceof AssignStmt)
return ((AssignStmt)unit).getRightOp();
else
return null;
}
/**
* only lets binary expression through.
*
* @param val the Value to test for.
* @return <code>val</code> if it is a binary expression. otherwise
* <code>null</code>.
*/
public static Value binop(Value val) {
if (val == null) return null;
if (val instanceof BinopExpr) return val;
return null;
}
/**
* only lets binary RHS through.
*
* @param unit the Unit to test for.
* @return the rhs of the current unit, if <code>unit</code> is an
* AssigStmt and its RHS is a binary expression. otherwise
* <code>null</code>.
*/
public static Value binopRhs(Unit unit) {
return binop(rhs(unit));
}
/**
* only lets concrete references through. A concrete reference is either an
* array-ref or a field-ref.<br>
* returns <code>null</code> if <code>val</code> already was null.
*
* @param val the Value to test for.
* @return the <code>val</code> if it was a concrete reference. otherwise
* <code>null</code>.
*/
public static Value concreteRef(Value val) {
if (val == null) return null;
if (val instanceof ConcreteRef) return val;
return null;
}
/**
* filters out Exception-throwing Values. This method is perhaps
* conservative.<br>
* returns <code>null</code> if <code>val</code> is null.
*
* @param val the Value to test for.
* @return <code>val</code> if val doesn't throw any exception, or
* <code>null</code> otherwise.
*/
public static Value noExceptionThrowing(Value val) {
if (val == null) return null;
if (!throwsException(val))
return val;
else
return null;
}
/**
* filters out RHS that don't throw any exception.
*
* @param unit the Unit to test.
* @return the rhs, if <code>unit</code> is an assignment-stmt and can't
* throw any exception.
*/
public static Value noExceptionThrowingRhs(Unit unit) {
return noExceptionThrowing(rhs(unit));
}
/**
* filters out RHS that aren't invokes.
*
* @param unit the Unit to look at.
* @return the RHS of <code>unit</code> if it is an assignment-stmt, and its
* RHS is not an invoke.
*/
public static Value noInvokeRhs(Unit unit) {
return noInvoke(rhs(unit));
}
/**
* filters out Invokes.<br>
* returns <code>null</code> if <code>val</code> is null.
*
* @param val the Value to inspect
* @return <code>val</code>, if val is not an invoke, <code>null</code>
* otherwise.
*/
public static Value noInvoke(Value val) {
if (val == null || isInvoke(val))
return null;
else
return val;
}
/**
* returns true, if <code>val</code> is an invoke.
*
* @param val the Value to inspect.
* @return true if <code>val</code> is an invoke.
*/
public static boolean isInvoke(Value val) {
val = getEquivalentValueRoot(val);
if (val instanceof InvokeExpr)
return true;
return false;
}
/**
* filters out Locals.<br>
* returns <code>null</code> if <code>val</code> is null.
*
* @param val the Value to look at.
* @return <code>val</code>, if it is a Local, <code>null</code> otherwise.
*/
public static Value local(Value val) {
if (val != null && isLocal(val))
return val;
else
return null;
}
/**
* only lets non-Locals through.<br>
* returns <code>null</code> if <code>val</code> is null.
*
* @param val the Value to look at.
* @return <code>val</code>, if it is not a Local, <code>null</code> otherwise.
*/
public static Value noLocal(Value val) {
if (val != null && !isLocal(val))
return val;
else
return null;
}
/**
* returns true, if <code>val</code> is a Local.
*/
public static boolean isLocal(Value val) {
return (getEquivalentValueRoot(val) instanceof Local);
}
/**
* returns the Value of an EquivalentValue. If there are several
* EquivalentValues stacked one into another, gets the deepest Value.<br>
* returns <code>null</code> if <code>val</code> is null.
*
* @param val the Value to inspect.
* @return val, if val is not an EquivalentValue, or the deepest Value
* otherwise.
*/
public static Value getEquivalentValueRoot(Value val) {
if (val == null) return null;
/* extract the Value, if val is an EquivalentValue. One of the reasons, why
* testing for "instanceof" is sometimes not a good idea.*/
while (val instanceof EquivalentValue)
val = ((EquivalentValue)val).getValue();
return val;
}
/**
* a (probably) conservative way of telling, if a Value throws an exception
* or not.
*/
public static boolean throwsException(Value val) {
val = getEquivalentValueRoot(val);
/* i really hope i did not forget any... */
if (val instanceof BinopExpr ||
val instanceof UnopExpr ||
val instanceof Local ||
val instanceof Constant) {
if (val instanceof DivExpr ||
val instanceof RemExpr ||
val instanceof LengthExpr)
return true;
return false;
}
return true;
}
}