package soot.dava.toolkits.base.AST.structuredAnalysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import soot.BooleanType;
import soot.ByteType;
import soot.CharType;
import soot.DoubleType;
import soot.FloatType;
import soot.IntType;
import soot.Local;
import soot.LongType;
import soot.PrimType;
import soot.ShortType;
import soot.SootField;
import soot.Type;
import soot.Value;
import soot.dava.DavaFlowAnalysisException;
import soot.dava.internal.AST.ASTBinaryCondition;
import soot.dava.internal.AST.ASTCondition;
import soot.dava.internal.AST.ASTIfElseNode;
import soot.dava.internal.AST.ASTIfNode;
import soot.dava.internal.AST.ASTMethodNode;
import soot.dava.internal.AST.ASTUnaryCondition;
import soot.dava.internal.AST.ASTUnaryBinaryCondition;
import soot.dava.internal.javaRep.DNotExpr;
import soot.dava.toolkits.base.AST.interProcedural.ConstantFieldValueFinder;
import soot.jimple.BinopExpr;
import soot.jimple.ConditionExpr;
import soot.jimple.DefinitionStmt;
import soot.jimple.FieldRef;
import soot.jimple.Stmt;
public class CP extends StructuredAnalysis {
/*
* Constant Propagation:
*
* Step 1:
* Sets of CPTuple (className, CPVariable, value)
* where: CPVariable contains a local or SootField
*
* Step 2:
* A local or SootField has a constant value at a program point p if on all
* program paths from the start of the method to point p the local or Sootfield
* has only been assigned this constant value.
*
* Step 3:
* Forward Analysis
*
* Step 4:
* Intersection (See intersection method in CPFlowSet)
*
* Step 5:
* See method processStatement
*
* Step 6:
* out(start) = all locals set to bottom(they shouldnt be present in the initialSet all formals set to Top,
* all constant fields set to constant values
*
* newInitialFlow: all locals and formals set to Top, all constant fields set to constant values
* remember new InitialFlow is ONLY used for input to catchBodies
*
* Any local or field which is not in the flow set at any time is necessarily bottom
*
*
* knowing how a condition evaluates can give us useful insight to the values of variables
* Handle this for a == b where both a and b are primtype
* and special case handle it for A where A is a unary boolean condition
*
* See following over-riden methods:
*
* public Object processASTIfElseNode(ASTIfElseNode node,Object input)
* public Object processASTIfNode(ASTIfNode node,Object input)
* public Object processASTSwitchNode(ASTSwitchNode node,Object input)
*/
ArrayList<CPTuple> constantFieldTuples = null; //VariableTuples of constantFields
ArrayList<CPTuple> formals = null; //VariableTuples for formals initially set to T
ArrayList<CPTuple> locals = null; //VariableTuples for locals initially set to default
ArrayList<CPTuple> initialInput = null; //VariableTuples of constantFields, locals set to 0 and formals set to T
ASTMethodNode methodNode = null;
String localClassName = null;
/*
* The start of the analysis takes place whenever this constructor is invoked
*/
public CP(ASTMethodNode analyze, HashMap<String, Object> constantFields,HashMap<String, SootField> classNameFieldNameToSootFieldMapping){
super();
/*
DEBUG = true;
DEBUG_IF = true;
DEBUG_WHILE = true;
DEBUG_STATEMENTS = true;
*/
this.methodNode=analyze;
localClassName = analyze.getDavaBody().getMethod().getDeclaringClass().getName();
//Create a list of VariableValueTuples for all the constantFields
createConstantFieldsList(constantFields, classNameFieldNameToSootFieldMapping);
//Create the complete list of vars to go into constant propagation
createInitialInput();
//input to constant propagation should not be an empty flow set it is the set of all constant fields, locals assigned 0 and formals assigned T
CPFlowSet initialSet = new CPFlowSet();
Iterator<CPTuple> it = initialInput.iterator();
while(it.hasNext())
initialSet.add(it.next());
//System.out.println("Initial set"+initialSet.toString());
CPFlowSet result = (CPFlowSet)process(analyze, initialSet);
//System.out.println("Last result :"+result.toString());
}
/*
* constant fields added with KNOWN CONSTANT VALUE
* formals added with TOP
* locals added with 0
* other fields IGNORED
*
*/
public void createInitialInput(){
initialInput = new ArrayList<CPTuple>();
//adding constant fields
initialInput.addAll(constantFieldTuples);
//String className = analyze.getDavaBody().getMethod().getDeclaringClass().getName();
//adding formals
formals = new ArrayList<CPTuple>();
//System.out.println("Adding following formals: with TOP");
Collection col = methodNode.getDavaBody().get_ParamMap().values();
Iterator it = col.iterator();
while(it.hasNext()){
Object temp = it.next();
if(temp instanceof Local){
Local tempLocal = (Local)temp;
if(! (tempLocal.getType() instanceof PrimType ))
continue;
CPVariable newVar = new CPVariable(tempLocal);
//new tuple set to top since this is a formal and we dont know what value we will get into it
CPTuple newTuple = new CPTuple(localClassName,newVar,true);
initialInput.add(newTuple);
formals.add(newTuple);
//System.out.print("\t"+tempLocal.getName());
}
}
//System.out.println();
//adding locals
List decLocals = methodNode.getDeclaredLocals();
it = decLocals.iterator();
locals = new ArrayList<CPTuple>();
//System.out.println("Adding following locals with default values:");
while(it.hasNext()){
Object temp = it.next();
if(temp instanceof Local){
Local tempLocal = (Local)temp;
Type localType = tempLocal.getType();
if(! (localType instanceof PrimType ))
continue;
CPVariable newVar = new CPVariable(tempLocal);
//store the default value into this object
Object value;
//locals value is set to the default value that it can have depending on its type
if(localType instanceof BooleanType)
value = new Boolean(false);
else if(localType instanceof ByteType)
value = new Integer(0);
else if(localType instanceof CharType)
value = new Integer(0);
else if(localType instanceof DoubleType)
value = new Double(0);
else if(localType instanceof FloatType)
value = new Float(0);
else if(localType instanceof IntType)
value = new Integer(0);
else if(localType instanceof LongType)
value = new Long(0);
else if(localType instanceof ShortType)
value = new Integer(0);
else
throw new DavaFlowAnalysisException("Unknown PrimType");
CPTuple newTuple = new CPTuple(localClassName,newVar,value);
/*
* Commenting the next line since we dont want initial Input to have any locals in it
* all locals are considered bottom initially
*/
//initialInput.add(newTuple);
locals.add(newTuple);
//System.out.print("\t"+tempLocal.getName());
}//was a local
}
//System.out.println();
}
/*
* Uses the results of the ConstantValueFinder to create a list of constantField CPTuple
*/
private void createConstantFieldsList(HashMap<String, Object> constantFields, HashMap<String, SootField> classNameFieldNameToSootFieldMapping){
constantFieldTuples = new ArrayList<CPTuple>();
Iterator<String> it = constantFields.keySet().iterator();
//System.out.println("Adding constant fields to initial set: ");
while(it.hasNext()){
String combined = it.next();
int temp = combined.indexOf(ConstantFieldValueFinder.combiner,0);
if(temp > 0){
String className = combined.substring(0,temp);
//String fieldName = combined.substring(temp+ ConstantFieldValueFinder.combiner.length());
SootField field = classNameFieldNameToSootFieldMapping.get(combined);
//String fieldName = field.getName();
if(! (field.getType() instanceof PrimType)){
//we only care about PrimTypes
continue;
}
//object type is double float long boolean or integer
Object value = constantFields.get(combined);
CPVariable var = new CPVariable(field);
CPTuple newTuples = new CPTuple(className,var,value);
constantFieldTuples.add(newTuples);
//System.out.print("Class: "+className + " Field: "+fieldName+" Value: "+value+" ");
}
else{
throw new DavaFlowAnalysisException("Second argument of VariableValuePair not a variable");
}
}
//System.out.println("");
}
public DavaFlowSet emptyFlowSet(){
return new CPFlowSet();
}
/*
* Setting the mergetype to intersection but since we are going to have constantpropagation flow sets
* the intersection method for this flow set will be invoked which defines the correct semantics of intersection
* for the case of constant propagation
*/
public void setMergeType() {
MERGETYPE = INTERSECTION;
}
/*
* newInitialFlow is invoked for the input set of the catchBodies
*
* formals initialized to top since we dont know what has happened so far in the body
* locals initialized to top since we dont know what has happened so far in the method body
* constant fields present with their constant value since that never changes
*/
public Object newInitialFlow() {
CPFlowSet flowSet = new CPFlowSet();
//formals and locals should be both initialized to top since we dont know what has happened so far in the body
ArrayList<CPTuple> localsAndFormals = new ArrayList<CPTuple>();
localsAndFormals.addAll(formals);
localsAndFormals.addAll(locals);
Iterator<CPTuple> it = localsAndFormals.iterator();
while(it.hasNext()){
CPTuple tempTuple = (CPTuple)it.next().clone();
//just making sure all are set to Top
if(!tempTuple.isTop())
tempTuple.setTop();
flowSet.add(tempTuple);
}
//constant fields should be present with their constant value since that never changes
it = constantFieldTuples.iterator();
while(it.hasNext()){
flowSet.add(it.next());
}
return flowSet;
}
public Object cloneFlowSet(Object flowSet) {
if(flowSet instanceof CPFlowSet){
return ((CPFlowSet)flowSet).clone();
}
else
throw new RuntimeException("cloneFlowSet not implemented for other flowSet types"+flowSet.toString());
}
/*
* Since we are only keeping track of constant fields now there will be no kill
* if we were keeping track of fields then we woul dneed to kill all non constant fields if there was an invokeExpr
*/
public Object processUnaryBinaryCondition(ASTUnaryBinaryCondition cond, Object input) {
if(!(input instanceof CPFlowSet)){
throw new RuntimeException("processCondition is not implemented for other flowSet types"+input.toString());
}
CPFlowSet inSet = (CPFlowSet)input;
return inSet;
}
/*
* Has no effect whatsoever on the analysis
*/
public Object processSynchronizedLocal(Local local, Object input) {
if(!(input instanceof CPFlowSet)){
throw new RuntimeException("processSynchronized is not implemented for other flowSet types"+input.toString());
}
DavaFlowSet inSet = (DavaFlowSet)input;
return inSet;
}
/*
* no effect on the analysis since we are keeping track of non constant fields only
* if we were tracking other fields then
* If the value contained an invoke expr top all non constant fields similar to as done for unarybinary condition
*/
public Object processSwitchKey(Value key, Object input) {
if(!(input instanceof CPFlowSet)){
throw new RuntimeException("processCondition is not implemented for other flowSet types"+input.toString());
}
CPFlowSet inSet = (CPFlowSet)input;
return inSet;
}
/*
* x = expr;
*
* expr is a constant
*
* epr is a local (Note we are not going to worry about fieldRefs)
*
* expr is a Unary op with neg followed by a local or field
*
* expr is actually exp1 op expr2 ..... ( x = x+1, y = i * 3, x = 3 *0
*
* expr contains an invokeExpr
*/
public Object processStatement(Stmt s, Object input) {
if(!(input instanceof CPFlowSet))
throw new RuntimeException("processStatement is not implemented for other flowSet types");
CPFlowSet inSet = (CPFlowSet)input;
if(inSet == NOPATH)
return inSet;
if(! (s instanceof DefinitionStmt) )
return inSet;
DefinitionStmt defStmt = (DefinitionStmt)s;
//x = expr;
//confirm that the left side is a local with a primitive type
Value left = defStmt.getLeftOp();
if( ! (left instanceof Local && ((Local)left).getType() instanceof PrimType) )
return inSet;
//left is a primitive primitive local
CPFlowSet toReturn = (CPFlowSet)cloneFlowSet(inSet);
/*
* KILL ANY PREVIOUS VALUE OF this local as this is an assignment
* Remember the returned value can be null if the element was not found or it was TOP
*/
Object killedValue = killButGetValueForUse((Local)left,toReturn);
Value right = defStmt.getRightOp();
Object value = CPHelper.isAConstantValue(right);
if(value != null){
//EXPR IS A CONSTANT
if(left.getType() instanceof BooleanType ){
Integer tempValue = (Integer)value;
if(tempValue.intValue() == 0)
value = new Boolean(false);
else
value = new Boolean(true);
}
addOrUpdate(toReturn,(Local)left,value);
}
else{
//EXPR IS NOT A CONSTANT
handleMathematical(toReturn,(Local)left,right,killedValue);
}
return toReturn;
}
/*
* The returned value is the current constant associated with left. Integer/Long/Double/Float/Boolean
* The returned value can also be null if the element was not found or it was TOP
*/
public Object killButGetValueForUse(Local left, CPFlowSet toReturn){
Iterator it = toReturn.toList().iterator();
while(it.hasNext()){
CPTuple tempTuple = (CPTuple)it.next();
if( ! (tempTuple.getSootClassName().equals(localClassName)) )
continue;
//className is the same check if the variable is the same or not
if(tempTuple.containsLocal()){ //remmeber the sets contain constant fields also
Local tempLocal = tempTuple.getVariable().getLocal();
if(left.getName().equals(tempLocal.getName())){
//KILL THIS SUCKA!!!
Object killedValue = tempTuple.getValue();
tempTuple.setTop();
return killedValue;
}
}
} //going through all elements of the flow set
//if this element was no where enter it with top
CPVariable newVar = new CPVariable(left);
//create the CPTuple
//System.out.println("trying to kill something which was not present so added with TOP");
CPTuple newTuple = new CPTuple(localClassName,newVar,false);
toReturn.add(newTuple);
return null;
}
/*
* Create a CPTuple for left with the val and update the toReturn set
*/
private void addOrUpdate(CPFlowSet toReturn , Local left, Object val){
CPVariable newVar = new CPVariable(left);
CPTuple newTuple = new CPTuple(localClassName,newVar,val);
toReturn.addIfNotPresent(newTuple);
//System.out.println("DefinitionStmt checked right expr for constants"+toReturn.toString());
}
/*
* x = b where b is in the before set of the statement as a constant then we can simply say x = that constant also
*
* TODO: DONT WANT TO DO IT:::: If right expr is a unary expression see if the stuff inside is a Local
*
* x = exp1 op exp2 (check if both exp1 and exp2 are int constants
*
* killedValuse is either the constant value which left had before this assignment stmt or null if left was Top or not in the set
*
* handle the special case when the inputset could not find a value because its the killed value
* //eg. x = x+1 since we top x first we will never get a match IMPORTANT
*/
private void handleMathematical(CPFlowSet toReturn, Local left, Value right, Object killedValue){
//if right expr is a local or field
Object value = isANotTopConstantInInputSet(toReturn,right);
if(value != null){
//right was a local or field with a value other than top
//dont send value SEND A CLONE OF VALUE.....IMPORTANT!!!!
Object toSend = CPHelper.wrapperClassCloner(value);
if(toSend != null){
addOrUpdate(toReturn ,left,toSend);
}
//return if value was != null as this means that the left was a primitive local assigned some value from the right
return;
}
//if we get here we know that right is not a local or field whose value we could find in the set
if(right instanceof BinopExpr){
Value op1 = ((BinopExpr)right).getOp1();
Value op2 = ((BinopExpr)right).getOp2();
Object op1Val = CPHelper.isAConstantValue(op1);
Object op2Val = CPHelper.isAConstantValue(op2);
if(op1Val ==null)
op1Val = isANotTopConstantInInputSet(toReturn,op1);
if(op2Val == null)
op2Val = isANotTopConstantInInputSet(toReturn,op2);
if(op1 == left){
//System.out.println("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>OP1 is the same as LHS");
op1Val = killedValue;
}
if(op2 == left){
//System.out.println("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>OP2 is the same as LHS");
op2Val = killedValue;
}
if(op1Val != null && op2Val != null){
//System.out.println("found constant values for both operands of binary expression");
if(left.getType() instanceof IntType && op1Val instanceof Integer && op2Val instanceof Integer){
//only caring about operations on two integers and result is an integer
int op1IntValue = ((Integer)op1Val).intValue();
int op2IntValue = ((Integer)op2Val).intValue();
String tempStr = ((BinopExpr)right).getSymbol();
if(tempStr.length()>1){
char symbol = tempStr.charAt(1);
//System.out.println("found symbol "+symbol+" for the operands of binary expression");
int newValue=0;
boolean set =false;
switch(symbol){
case '+':
//System.out.println("Adding");
newValue = op1IntValue + op2IntValue;
set =true;
break;
case '-':
//System.out.println("Subtracting");
newValue = op1IntValue - op2IntValue;
set =true;
break;
case '*':
//System.out.println("Multiplying");
newValue = op1IntValue * op2IntValue;
set =true;
break;
}
if(set){
//we have our new value
Integer newValueObject = new Integer(newValue);
addOrUpdate(toReturn ,left,newValueObject);
return;
}
}
}
}
else{
//System.out.println("atleast one value is not constant so cant simplify expression");
}
}
//System.out.println("DefinitionStmt checked right expr for mathematical stuff"+toReturn.toString());
}
/*
* Check whether it is a local or field which has a constant value (could be top) in the current inSet
*
* The method returns null if its not found or its TOP
* Otherwise it will return the constant value
*/
private Object isANotTopConstantInInputSet(CPFlowSet set, Value toCheck){
if(toCheck instanceof Local || toCheck instanceof FieldRef){
String toCheckClassName = null;
if(toCheck instanceof Local)
toCheckClassName = localClassName;
else
toCheckClassName = ((FieldRef)toCheck).getField().getDeclaringClass().getName();
Iterator it = set.toList().iterator();
while(it.hasNext()){
CPTuple tempTuple = (CPTuple)it.next();
//check that the classNames are the same
if( !( tempTuple.getSootClassName().equals(toCheckClassName))){
//classNames are not the same no point in continuing with checks
continue;
}
boolean tupleFound=false;
if(tempTuple.containsLocal() && toCheck instanceof Local){
//check they are the same Local
Local tempLocal = tempTuple.getVariable().getLocal();
if(tempLocal.getName().equals( ((Local)toCheck).getName())){
//the set does have a constant value for this local
tupleFound=true;
}
}
else if(tempTuple.containsField() && toCheck instanceof FieldRef){
SootField toCheckField= ((FieldRef)toCheck).getField();
SootField tempField = tempTuple.getVariable().getSootField();
if(tempField.getName().equals(toCheckField.getName())){
//the set contains a constant value for this field
tupleFound=true;
}
}
if(tupleFound){
if(tempTuple.isTop())
return null;
else
return tempTuple.getValue();
}
}
}
return null;
}
/*
* over-riding the StructuredFlow Analysis implementation because we want to be able to
* gather information about the truth value in the condition
*/
public Object processASTIfNode(ASTIfNode node,Object input){
if(DEBUG_IF)
System.out.println("Processing if node using over-ridden process if method"+input.toString());;
input = processCondition(node.get_Condition(),input);
if( ! (input instanceof CPFlowSet ) ){
throw new DavaFlowAnalysisException("not a flow set");
}
CPFlowSet inputToBody = ((CPFlowSet)input).clone();
CPTuple tuple = checkForValueHints(node.get_Condition(),inputToBody,false);
if(tuple != null){
//if not null, is a belief going into the if branch simply add it into the input set
//System.out.println(">>>>>Adding tuple because of condition"+tuple.toString());
inputToBody.addIfNotPresentButDontUpdate(tuple);
}
Object output1 = processSingleSubBodyNode(node,inputToBody);
if(DEBUG_IF)
System.out.println("\n\nINPUTS TO MERGE ARE input (original):"+input.toString() +"processingBody output:"+output1.toString()+"\n\n\n");
//merge with input which tells if the cond did not evaluate to true
Object output2 = merge(input,output1);
//handle break
String label = getLabel(node);
Object temp= handleBreak(label,output2,node);
if(DEBUG_IF)
System.out.println("Exiting if node"+temp.toString());;
return temp;
}
public Object processASTIfElseNode(ASTIfElseNode node,Object input){
if(DEBUG_IF)
System.out.println("Processing IF-ELSE node using over-ridden process if method"+input.toString());;
if( ! (input instanceof CPFlowSet ) ){
throw new DavaFlowAnalysisException("not a flow set");
}
//get the subBodies
List<Object> subBodies = node.get_SubBodies();
if(subBodies.size()!=2){
throw new RuntimeException("processASTIfElseNode called with a node without two subBodies");
}
//we know there is only two subBodies
List subBodyOne = (List)subBodies.get(0);
List subBodyTwo = (List)subBodies.get(1);
//process Condition
input = processCondition(node.get_Condition(),input);
//the current input flowset is sent to both branches
Object clonedInput = cloneFlowSet(input);
CPTuple tuple = checkForValueHints(node.get_Condition(),(CPFlowSet)clonedInput,false);
if(tuple != null){
//if not null, is a belief going into the if branch simply add it into the input set
//System.out.println(">>>>>Adding tuple because of condition into if branch"+tuple.toString());
((CPFlowSet)clonedInput).addIfNotPresentButDontUpdate(tuple);
}
Object output1 = process(subBodyOne,clonedInput);
clonedInput = cloneFlowSet(input);
CPTuple tuple1 = checkForValueHints(node.get_Condition(),(CPFlowSet)clonedInput,true);
if(tuple1 != null){
//if not null, is a belief going into the else branch simply add it into the input set
//System.out.println(">>>>>Adding tuple because of condition into else branch"+tuple1.toString());
((CPFlowSet)clonedInput).addIfNotPresentButDontUpdate(tuple1);
}
Object output2 = process(subBodyTwo,clonedInput);
if(DEBUG_IF){
System.out.println("\n\n IF-ELSE INPUTS TO MERGE ARE input (if):"+output1.toString() +" else:"+output2.toString()+"\n\n\n");
}
Object temp=merge(output1,output2);
//notice we handle breaks only once since these are breaks to the same label or same node
String label = getLabel(node);
output1 = handleBreak(label,temp,node);
if(DEBUG_IF){
System.out.println("Exiting ifelse node"+output1.toString());;
}
return output1;
}
/*
* The isElseBranch flag is true if the caller is the else branch of the ifelse statement.
* In that case we might be able to send something for the else branch
*/
public CPTuple checkForValueHints(ASTCondition cond, CPFlowSet input, boolean isElseBranch){
if(cond instanceof ASTUnaryCondition){
//check for lone boolean if(notDone)
ASTUnaryCondition unary = (ASTUnaryCondition)cond;
Value unaryValue = unary.getValue();
boolean NOTTED=false;
//Get the real value if this is a notted expression
if(unaryValue instanceof DNotExpr){
unaryValue =((DNotExpr)unaryValue).getOp();
NOTTED=true;
}
if( ! (unaryValue instanceof Local) ){
//since we only track locals we cant possibly add info to the inset
return null;
}
//the unary value is a local add the value to the inset which woul dbe present in the if branch
CPVariable variable = new CPVariable((Local)unaryValue);
//since NOTTED true means the if branch has variable with value false and vice verse
if(!isElseBranch){
//we are in the if branch hence notted true would mean the variable is actually false here
Boolean boolVal = new Boolean(!NOTTED);
return new CPTuple(localClassName,variable,boolVal);
}
else{
//in the else branch NOTTED true means the variable is true
Boolean boolVal = new Boolean(NOTTED);
return new CPTuple(localClassName,variable,boolVal);
}
}
else if(cond instanceof ASTBinaryCondition){
ASTBinaryCondition binary = (ASTBinaryCondition)cond;
ConditionExpr expr = binary.getConditionExpr();
Boolean equal = null;
String symbol = expr.getSymbol();
if(symbol.indexOf("==") >-1){
//System.out.println("!!!!!!!!!1 FOUND == in binary comparison operaiton");
equal = new Boolean(true);
}
else if(symbol.indexOf("!=") > -1){
equal = new Boolean(false);
//System.out.println("!!!!!!!!!!!!!! FOUND != in binary comparison operaiton");
}
else{
//a symbol we are not interested in
//System.out.println("symbol is"+symbol);
return null;
}
//we have a comparison the truth value of equal tells whether we are doing == or !=
Value a = expr.getOp1();
Value b = expr.getOp2();
//see if its possible to deduce a hint from these values
CPTuple tuple = createCPTupleIfPossible(a,b,input);
//if the tuple is not created
if(tuple == null)
return null;
//we have to make sure is that the == and != are taken into account
if(equal.booleanValue()){
//using equality comparison a == b this then means in the if branch a is in fact equal to b
if(!isElseBranch)
return tuple;
else
return null;
}
else{
if(isElseBranch)
return tuple;
else
return null;
}
}
return null;
}
/*
* Should create the final tuple to add
*
* a == b
*
* case 1 a is constant b is constant dont give a damm
* case 2 a is constant b is a local useful
* case 3 a is a local b is a constant useful
* case 4 a is a local or sootfield b is a local or sootfield useful if one of them is in the inset
*
*/
public CPTuple createCPTupleIfPossible(Value a,Value b,CPFlowSet input){
Object aVal = CPHelper.isAConstantValue(a);
Object bVal = CPHelper.isAConstantValue(b);
if(aVal != null && bVal != null){
//both are constants dont want to do anything..case 1
return null;
}
CPVariable cpVar= null;
Object constantToUse = null;
if(aVal == null && bVal == null){
//both are not constants but one of their values could be known in the inset ... case 4
//System.out.println("a:"+a+" is not a constant b:"+b+" is not");
//check the input set to see if either a or b have known beliefs.
//its useful if one and only one of the two has a known belief
Object av1 = isANotTopConstantInInputSet(input,a);
Object av2 = isANotTopConstantInInputSet(input,b);
if(av1 == null && av2 == null){
//either top or not present hence useless
return null;
}
else if (av1 == null && av2 != null){
//no value of a found but value of b was found <classname, a,b>
//System.out.println("From INSET: a:"+a+" is not a constant b "+b+" is" );
if( ! ( a instanceof Local && ((Local)a).getType() instanceof PrimType ) ){
//we only hanlde primitive locals
return null;
}
cpVar = new CPVariable((Local)a);
constantToUse = av2;
}
else if(av1 != null && av2 == null){
//no value of b found but value of a was found <classname, b,a>
//System.out.println("From INSET: a:"+a+" is a constant b "+b+" is not" );
if( ! ( b instanceof Local && ((Local)b).getType() instanceof PrimType ) ){
//we only hanlde primitive locals
return null;
}
cpVar = new CPVariable((Local)b);
constantToUse = av1;
}
}
else if(aVal != null && bVal == null){
// CASE 2: a is a constant and b is not so we have a chance of entering a tuple <className,b,a> maybe
//System.out.println("a:"+a+" is a constant b:"+b+" is not");
if( ! ( b instanceof Local && ((Local)b).getType() instanceof PrimType ) ){
//we only hanlde primitive locals
return null;
}
//able to create cpVar
cpVar = new CPVariable((Local)b);
constantToUse=aVal;
}
else if(aVal == null && bVal != null){
//CASE 3: a is not a constant but b is a constant so we have a chance of entering a tuple <className,a,b>
//System.out.println("a:"+a+" is not a constant b:"+b+" is ");
if( ! ( a instanceof Local && ((Local)a).getType() instanceof PrimType ) ){
//we only hanlde primitive locals
return null;
}
//able to create cpVar
cpVar = new CPVariable((Local)a);
constantToUse=bVal;
}
//if cpVar is not null and constantToUse is not null thats good
if(cpVar != null && constantToUse != null){
//create a CPTuple which contains the belief for cpVar with constantToUse we will for sure have going into the if branch
//we know cpVar is always a local since we create it only for locals
//need to see if constant is supposed to be a boolean (isAConstantValue returns an Integer for a boolean)
if( cpVar.getLocal().getType() instanceof BooleanType){
if( ! (constantToUse instanceof Integer ) ){
//booleans are represented by Integeres in the isConstantValue method what happened here???
return null;
}
Integer tempValue = (Integer)constantToUse;
if(tempValue.intValue() == 0)
constantToUse = new Boolean(false);
else
constantToUse = new Boolean(true);
}
//ready to create the CPTuple
return new CPTuple(localClassName,cpVar,constantToUse);
}
return null;
}
/*
* TODO some other time
*
public Object processASTSwitchNode(ASTSwitchNode node,Object input){
}*/
}