/* Soot - a J*va Optimization Framework
* Copyright (C) 2004 Jennifer Lhotak
*
* 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.javaToJimple;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import polyglot.ast.Block;
import polyglot.ast.FieldDecl;
import polyglot.ast.Try;
import polyglot.util.IdentityKey;
import soot.Local;
import soot.SootClass;
import soot.SootField;
import soot.Trap;
import soot.Value;
import soot.jimple.IntConstant;
import soot.jimple.Jimple;
import soot.jimple.Stmt;
public class JimpleBodyBuilder extends AbstractJimpleBodyBuilder {
public JimpleBodyBuilder(){
//ext(null);
//base(this);
}
protected List<List<Stmt>> beforeReturn; // list used to exclude return stmts from synch try blocks
protected List<List<Stmt>> afterReturn; // list used to exclude return stmts from synch try blocks
protected ArrayList<Trap> exceptionTable; // list of exceptions
protected Stack<Stmt> endControlNoop = new Stack<Stmt>(); // for break
protected Stack<Stmt> condControlNoop = new Stack<Stmt>(); // continue
protected Stack<Value> monitorStack; // for synchronized blocks
protected Stack<Try> tryStack; // for try stmts in case of returns
protected Stack<Try> catchStack; // for catch stmts in case of returns
protected Stack<Stmt> trueNoop = new Stack<Stmt>();
protected Stack<Stmt> falseNoop = new Stack<Stmt>();
protected HashMap<String, Stmt> labelBreakMap; // for break label --> nop to jump to
protected HashMap<String, Stmt> labelContinueMap; // for continue label --> nop to jump to
protected HashMap<polyglot.ast.Stmt, Stmt> labelMap;
protected HashMap<IdentityKey, Local> localsMap = new HashMap<IdentityKey, Local>(); // localInst --> soot local
protected HashMap getThisMap = new HashMap(); // type --> local to ret
protected Local specialThisLocal; // === body.getThisLocal();
protected Local outerClassParamLocal; // outer class this
protected int paramRefCount = 0; // counter for param ref stmts
protected LocalGenerator lg; // for generated locals not in orig src
/**
* Jimple Body Creation
*/
public soot.jimple.JimpleBody createJimpleBody(polyglot.ast.Block block, List formals, soot.SootMethod sootMethod){
createBody(sootMethod);
lg = new LocalGenerator(body);
// create this formal except for static methods
if (!soot.Modifier.isStatic(sootMethod.getModifiers())) {
soot.RefType type = sootMethod.getDeclaringClass().getType();
specialThisLocal = soot.jimple.Jimple.v().newLocal("this", type);
body.getLocals().add(specialThisLocal);
soot.jimple.ThisRef thisRef = soot.jimple.Jimple.v().newThisRef(type);
soot.jimple.Stmt thisStmt = soot.jimple.Jimple.v().newIdentityStmt(specialThisLocal, thisRef);
body.getUnits().add(thisStmt);
// this is causing problems - no this in java code -> no tags
//Util.addLineTag(thisStmt, block);
}
int formalsCounter = 0;
//create outer class this param ref for inner classes except for static inner classes - this is not needed
int outerIndex = sootMethod.getDeclaringClass().getName().lastIndexOf("$");
if ((outerIndex != -1) && (sootMethod.getName().equals("<init>")) && sootMethod.getDeclaringClass().declaresFieldByName("this$0")){
// we know its an inner non static class can get outer class
// from field ref of the this$0 field
soot.SootClass outerClass = ((soot.RefType)sootMethod.getDeclaringClass().getFieldByName("this$0").getType()).getSootClass();
soot.Local outerLocal = lg.generateLocal(outerClass.getType());
soot.jimple.ParameterRef paramRef = soot.jimple.Jimple.v().newParameterRef(outerClass.getType(), formalsCounter);
paramRefCount++;
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newIdentityStmt(outerLocal, paramRef);
stmt.addTag(new soot.tagkit.EnclosingTag());
body.getUnits().add(stmt);
((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).setOuterClassThisInit(outerLocal);
outerClassParamLocal = outerLocal;
formalsCounter++;
}
// handle formals
if (formals != null) {
ArrayList<String> formalNames = new ArrayList<String>();
Iterator formalsIt = formals.iterator();
while (formalsIt.hasNext()) {
polyglot.ast.Formal formal = (polyglot.ast.Formal)formalsIt.next();
createFormal(formal, formalsCounter);
formalNames.add(formal.name());
formalsCounter++;
}
body.getMethod().addTag(new soot.tagkit.ParamNamesTag(formalNames));
}
// handle final local params
ArrayList<SootField> finalsList = ((PolyglotMethodSource)body.getMethod().getSource()).getFinalsList();
if (finalsList != null){
Iterator<SootField> finalsIt = finalsList.iterator();
while (finalsIt.hasNext()){
soot.SootField sf = finalsIt.next();
soot.jimple.ParameterRef paramRef = soot.jimple.Jimple.v().newParameterRef(sf.getType(), formalsCounter);
paramRefCount++;
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newIdentityStmt(lg.generateLocal(sf.getType()), paramRef);
body.getUnits().add(stmt);
formalsCounter++;
}
}
createBlock(block);
// if method is <clinit> handle static field inits
if (sootMethod.getName().equals("<clinit>")){
handleAssert(sootMethod);
handleStaticFieldInits(sootMethod);
handleStaticInitializerBlocks(sootMethod);
}
// determine if body has a return stmt
boolean hasReturn = false;
if (block != null) {
Iterator it = block.statements().iterator();
while (it.hasNext()){
Object next = it.next();
if (next instanceof polyglot.ast.Return){
hasReturn = true;
}
}
}
soot.Type retType = body.getMethod().getReturnType();
// only do this if noexplicit return
if ((!hasReturn) && (retType instanceof soot.VoidType)) {
soot.jimple.Stmt retStmt = soot.jimple.Jimple.v().newReturnVoidStmt();
body.getUnits().add(retStmt);
}
// add exceptions from exceptionTable
if (exceptionTable != null) {
Iterator<Trap> trapsIt = exceptionTable.iterator();
while (trapsIt.hasNext()){
body.getTraps().add(trapsIt.next());
}
}
return body;
}
private void handleAssert(soot.SootMethod sootMethod){
if (!((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).hasAssert()) return;
((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).addAssertInits(body);
}
/**
* adds any needed field inits
*/
private void handleFieldInits(soot.SootMethod sootMethod) {
ArrayList<FieldDecl> fieldInits = ((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).getFieldInits();
if (fieldInits != null) {
handleFieldInits(fieldInits);
}
}
protected void handleFieldInits(ArrayList<FieldDecl> fieldInits){
Iterator<FieldDecl> fieldInitsIt = fieldInits.iterator();
while (fieldInitsIt.hasNext()) {
polyglot.ast.FieldDecl field = fieldInitsIt.next();
String fieldName = field.name();
polyglot.ast.Expr initExpr = field.init();
soot.SootClass currentClass = body.getMethod().getDeclaringClass();
soot.SootFieldRef sootField = soot.Scene.v().makeFieldRef(currentClass, fieldName, Util.getSootType(field.type().type()), field.flags().isStatic());
soot.Local base = specialThisLocal;
soot.jimple.FieldRef fieldRef = soot.jimple.Jimple.v().newInstanceFieldRef(base, sootField);
soot.Value sootExpr;
if (initExpr instanceof polyglot.ast.ArrayInit) {
sootExpr = getArrayInitLocal((polyglot.ast.ArrayInit)initExpr, field.type().type());
}
else {
//System.out.println("field init expr: "+initExpr);
sootExpr = base().createAggressiveExpr(initExpr, false, false);
//System.out.println("soot expr: "+sootExpr);
}
if (sootExpr instanceof soot.jimple.ConditionExpr) {
sootExpr = handleCondBinExpr((soot.jimple.ConditionExpr)sootExpr);
}
soot.jimple.AssignStmt assign;
if (sootExpr instanceof soot.Local){
assign = soot.jimple.Jimple.v().newAssignStmt(fieldRef, (soot.Local)sootExpr);
}
else if (sootExpr instanceof soot.jimple.Constant){
assign = soot.jimple.Jimple.v().newAssignStmt(fieldRef, (soot.jimple.Constant)sootExpr);
}
else {
throw new RuntimeException("fields must assign to local or constant only");
}
body.getUnits().add(assign);
Util.addLnPosTags(assign, initExpr.position());
Util.addLnPosTags(assign.getRightOpBox(), initExpr.position());
}
}
/**
* adds this field for the outer class
*/
private void handleOuterClassThisInit(soot.SootMethod sootMethod) {
// static inner classes are different
if (body.getMethod().getDeclaringClass().declaresFieldByName("this$0")){
soot.jimple.FieldRef fieldRef = soot.jimple.Jimple.v().newInstanceFieldRef(specialThisLocal, body.getMethod().getDeclaringClass().getFieldByName("this$0").makeRef());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(fieldRef, outerClassParamLocal);
body.getUnits().add(stmt);
}
}
/**
* adds any needed static field inits
*/
private void handleStaticFieldInits(soot.SootMethod sootMethod) {
ArrayList<FieldDecl> staticFieldInits = ((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).getStaticFieldInits();
if (staticFieldInits != null) {
Iterator<FieldDecl> staticFieldInitsIt = staticFieldInits.iterator();
while (staticFieldInitsIt.hasNext()) {
polyglot.ast.FieldDecl field = staticFieldInitsIt.next();
String fieldName = field.name();
polyglot.ast.Expr initExpr = field.init();
soot.SootClass currentClass = body.getMethod().getDeclaringClass();
soot.SootFieldRef sootField = soot.Scene.v().makeFieldRef(currentClass, fieldName, Util.getSootType(field.type().type()), field.flags().isStatic());
soot.jimple.FieldRef fieldRef = soot.jimple.Jimple.v().newStaticFieldRef(sootField);
//System.out.println("initExpr: "+initExpr);
soot.Value sootExpr;
if (initExpr instanceof polyglot.ast.ArrayInit) {
sootExpr = getArrayInitLocal((polyglot.ast.ArrayInit)initExpr, field.type().type());
}
else {
//System.out.println("field init expr: "+initExpr);
sootExpr = base().createAggressiveExpr(initExpr, false, false);
//System.out.println("soot expr: "+sootExpr);
if (sootExpr instanceof soot.jimple.ConditionExpr) {
sootExpr = handleCondBinExpr((soot.jimple.ConditionExpr)sootExpr);
}
}
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(fieldRef, sootExpr);
body.getUnits().add(assign);
Util.addLnPosTags(assign, initExpr.position());
}
}
}
/**
* init blocks get created within init methods in Jimple
*/
private void handleInitializerBlocks(soot.SootMethod sootMethod) {
ArrayList<Block> initializerBlocks = ((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).getInitializerBlocks();
if (initializerBlocks != null) {
handleStaticBlocks(initializerBlocks);
}
}
protected void handleStaticBlocks(ArrayList<Block> initializerBlocks){
Iterator<Block> initBlocksIt = initializerBlocks.iterator();
while (initBlocksIt.hasNext()) {
createBlock(initBlocksIt.next());
}
}
/**
* static init blocks get created in clinit methods in Jimple
*/
private void handleStaticInitializerBlocks(soot.SootMethod sootMethod) {
ArrayList<Block> staticInitializerBlocks = ((soot.javaToJimple.PolyglotMethodSource)sootMethod.getSource()).getStaticInitializerBlocks();
if (staticInitializerBlocks != null) {
Iterator<Block> staticInitBlocksIt = staticInitializerBlocks.iterator();
while (staticInitBlocksIt.hasNext()) {
createBlock(staticInitBlocksIt.next());
}
}
}
/**
* create body and make it be active
*/
private void createBody(soot.SootMethod sootMethod) {
body = soot.jimple.Jimple.v().newBody(sootMethod);
sootMethod.setActiveBody(body);
}
/**
* Block creation
*/
private void createBlock(polyglot.ast.Block block){
if (block == null) return;
// handle stmts
Iterator it = block.statements().iterator();
while (it.hasNext()){
Object next = it.next();
if (next instanceof polyglot.ast.Stmt){
createStmt((polyglot.ast.Stmt)next);
}
else {
throw new RuntimeException("Unexpected - Unhandled Node");
}
}
}
/**
* Catch Formal creation - method parameters
*/
private soot.Local createCatchFormal(polyglot.ast.Formal formal){
soot.Type sootType = Util.getSootType(formal.type().type());
soot.Local formalLocal = createLocal(formal.localInstance());
soot.jimple.CaughtExceptionRef exceptRef = soot.jimple.Jimple.v().newCaughtExceptionRef();
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newIdentityStmt(formalLocal, exceptRef);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, formal.position());
Util.addLnPosTags(((soot.jimple.IdentityStmt) stmt).getRightOpBox(), formal.position());
ArrayList<String> names = new ArrayList<String>();
names.add(formal.name());
stmt.addTag(new soot.tagkit.ParamNamesTag(names));
return formalLocal;
}
/**
* Formal creation - method parameters
*/
private void createFormal(polyglot.ast.Formal formal, int counter){
soot.Type sootType = Util.getSootType(formal.type().type());
soot.Local formalLocal = createLocal(formal.localInstance());
soot.jimple.ParameterRef paramRef = soot.jimple.Jimple.v().newParameterRef(sootType, counter);
paramRefCount++;
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newIdentityStmt(formalLocal, paramRef);
body.getUnits().add(stmt);
Util.addLnPosTags(((soot.jimple.IdentityStmt) stmt).getRightOpBox(), formal.position());
Util.addLnPosTags(stmt, formal.position());
}
/**
* Literal Creation
*/
private soot.Value createLiteral(polyglot.ast.Lit lit) {
if (lit instanceof polyglot.ast.IntLit) {
polyglot.ast.IntLit intLit = (polyglot.ast.IntLit)lit;
long litValue = intLit.value();
if (intLit.kind() == polyglot.ast.IntLit.INT) {
return soot.jimple.IntConstant.v((int)litValue);
}
else {
//System.out.println(litValue);
return soot.jimple.LongConstant.v(litValue);
}
}
else if (lit instanceof polyglot.ast.StringLit) {
String litValue = ((polyglot.ast.StringLit)lit).value();
return soot.jimple.StringConstant.v(litValue);
}
else if (lit instanceof polyglot.ast.NullLit) {
return soot.jimple.NullConstant.v();
}
else if (lit instanceof polyglot.ast.FloatLit) {
polyglot.ast.FloatLit floatLit = (polyglot.ast.FloatLit)lit;
double litValue = floatLit.value();
if (floatLit.kind() == polyglot.ast.FloatLit.DOUBLE) {
return soot.jimple.DoubleConstant.v(floatLit.value());
}
else {
return soot.jimple.FloatConstant.v((float)(floatLit.value()));
}
}
else if (lit instanceof polyglot.ast.CharLit) {
char litValue = ((polyglot.ast.CharLit)lit).value();
return soot.jimple.IntConstant.v(litValue);
}
else if (lit instanceof polyglot.ast.BooleanLit) {
boolean litValue = ((polyglot.ast.BooleanLit)lit).value();
if (litValue) return soot.jimple.IntConstant.v(1);
else return soot.jimple.IntConstant.v(0);
}
else if (lit instanceof polyglot.ast.ClassLit){
return getSpecialClassLitLocal((polyglot.ast.ClassLit)lit);
}
else {
throw new RuntimeException("Unknown Literal - Unhandled: "+lit.getClass());
}
}
/**
* Local Creation
*/
// this should be used for polyglot locals and formals
private soot.Local createLocal(polyglot.types.LocalInstance localInst) {
soot.Type sootType = Util.getSootType(localInst.type());
String name = localInst.name();
soot.Local sootLocal = createLocal(name, sootType);
localsMap.put(new polyglot.util.IdentityKey(localInst), sootLocal);
return sootLocal;
}
// this should be used for generated locals only
private soot.Local createLocal(String name, soot.Type sootType) {
soot.Local sootLocal = soot.jimple.Jimple.v().newLocal(name, sootType);
body.getLocals().add(sootLocal);
return sootLocal;
}
/**
* Local Retreival
*/
private soot.Local getLocal(polyglot.ast.Local local) {
return getLocal(local.localInstance());
}
/**
* Local Retreival
*/
private soot.Local getLocal(polyglot.types.LocalInstance li) {
if (localsMap.containsKey(new polyglot.util.IdentityKey(li))){
soot.Local sootLocal = localsMap.get(new polyglot.util.IdentityKey(li));
return sootLocal;
}
else if (body.getMethod().getDeclaringClass().declaresField("val$"+li.name(), Util.getSootType(li.type()))){
soot.Local fieldLocal = generateLocal(li.type());
soot.SootFieldRef field = soot.Scene.v().makeFieldRef(body.getMethod().getDeclaringClass(), "val$"+li.name(), Util.getSootType(li.type()), false);
soot.jimple.FieldRef fieldRef = soot.jimple.Jimple.v().newInstanceFieldRef(specialThisLocal, field);
soot.jimple.AssignStmt assign = soot.jimple.Jimple.v().newAssignStmt(fieldLocal, fieldRef);
body.getUnits().add(assign);
return fieldLocal;
}
/*else {
throw new RuntimeException("Trying unsuccessfully to get local: "+li.name());
}*/
else {
//else create access meth in outer for val$fieldname
// get the this$0 field to find the type of an outer class - has
// to have one because local/anon inner can't declare static
// memebers so for deepnesting not in static context for these
// cases
soot.SootClass currentClass = body.getMethod().getDeclaringClass();
boolean fieldFound = false;
while (!fieldFound){
if (!currentClass.declaresFieldByName("this$0")){
throw new RuntimeException("Trying to get field val$"+li.name()+" from some outer class but can't access the outer class of: "+currentClass.getName()+"!"+" current class contains fields: "+currentClass.getFields());
}
soot.SootClass outerClass = ((soot.RefType)currentClass.getFieldByName("this$0").getType()).getSootClass();
// look for field of type li.type and name val$li.name in outer
// class
if (outerClass.declaresField("val$"+li.name(), Util.getSootType(li.type()))){
fieldFound = true;
}
currentClass = outerClass;
// repeat until found in some outer class
}
// create and add accessor to that outer class (indic as current)
soot.SootMethod methToInvoke = makeLiFieldAccessMethod(currentClass, li);
// invoke and return
// generate a local that corresponds to the invoke of that meth
ArrayList methParams = new ArrayList();
methParams.add(getThis(currentClass.getType()));
soot.Local res = Util.getPrivateAccessFieldInvoke(methToInvoke.makeRef(), methParams, body, lg);
return res;
}
}
private soot.SootMethod makeLiFieldAccessMethod(soot.SootClass classToInvoke, polyglot.types.LocalInstance li){
String name = "access$"+soot.javaToJimple.InitialResolver.v().getNextPrivateAccessCounter()+"00";
ArrayList paramTypes = new ArrayList();
paramTypes.add(classToInvoke.getType());
soot.SootMethod meth = new soot.SootMethod(name, paramTypes, Util.getSootType(li.type()), soot.Modifier.STATIC);
classToInvoke.addMethod(meth);
PrivateFieldAccMethodSource src = new PrivateFieldAccMethodSource(
Util.getSootType(li.type()),
"val$"+li.name(),
false,
classToInvoke
);
meth.setActiveBody(src.getBody(meth, null));
meth.addTag(new soot.tagkit.SyntheticTag());
return meth;
}
/**
* Stmt creation
*/
protected void createStmt(polyglot.ast.Stmt stmt) {
//System.out.println("stmt: "+stmt.getClass());
if (stmt instanceof polyglot.ast.Eval) {
base().createAggressiveExpr(((polyglot.ast.Eval)stmt).expr(), false, false);
}
else if (stmt instanceof polyglot.ast.If) {
createIf2((polyglot.ast.If)stmt);
}
else if (stmt instanceof polyglot.ast.LocalDecl) {
createLocalDecl((polyglot.ast.LocalDecl)stmt);
}
else if (stmt instanceof polyglot.ast.Block) {
createBlock((polyglot.ast.Block)stmt);
}
else if (stmt instanceof polyglot.ast.While) {
createWhile2((polyglot.ast.While)stmt);
}
else if (stmt instanceof polyglot.ast.Do) {
createDo2((polyglot.ast.Do)stmt);
}
else if (stmt instanceof polyglot.ast.For) {
createForLoop2((polyglot.ast.For)stmt);
}
else if (stmt instanceof polyglot.ast.Switch) {
createSwitch((polyglot.ast.Switch)stmt);
}
else if (stmt instanceof polyglot.ast.Return) {
createReturn((polyglot.ast.Return)stmt);
}
else if (stmt instanceof polyglot.ast.Branch) {
createBranch((polyglot.ast.Branch)stmt);
}
else if (stmt instanceof polyglot.ast.ConstructorCall) {
createConstructorCall((polyglot.ast.ConstructorCall)stmt);
}
else if (stmt instanceof polyglot.ast.Empty) {
// do nothing empty stmt
}
else if (stmt instanceof polyglot.ast.Throw) {
createThrow((polyglot.ast.Throw)stmt);
}
else if (stmt instanceof polyglot.ast.Try) {
createTry((polyglot.ast.Try)stmt);
}
else if (stmt instanceof polyglot.ast.Labeled) {
createLabeled((polyglot.ast.Labeled)stmt);
}
else if (stmt instanceof polyglot.ast.Synchronized) {
createSynchronized((polyglot.ast.Synchronized)stmt);
}
else if (stmt instanceof polyglot.ast.Assert) {
createAssert((polyglot.ast.Assert)stmt);
}
else if (stmt instanceof polyglot.ast.LocalClassDecl) {
createLocalClassDecl((polyglot.ast.LocalClassDecl)stmt);
}
else {
throw new RuntimeException("Unhandled Stmt: "+stmt.getClass());
}
}
private boolean needSootIf(soot.Value sootCond){
if (sootCond instanceof soot.jimple.IntConstant){
if (((soot.jimple.IntConstant)sootCond).value == 1){
return false;
}
}
return true;
}
/**
* If Stmts Creation - only add line-number tags to if (the other
* stmts needing tags are created elsewhere
*/
/*private void createIf(polyglot.ast.If ifExpr){
// create true/false noops to handle cond and/or
trueNoop.push(soot.jimple.Jimple.v().newNopStmt());
falseNoop.push(soot.jimple.Jimple.v().newNopStmt());
// handle cond
polyglot.ast.Expr condition = ifExpr.cond();
soot.Value sootCond = base().createExpr(condition);
// pop true false noops right away
soot.jimple.Stmt tNoop = (soot.jimple.Stmt)trueNoop.pop();
soot.jimple.Stmt fNoop = (soot.jimple.Stmt)falseNoop.pop();
boolean needIf = needSootIf(sootCond);
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
sootCond = soot.jimple.Jimple.v().newEqExpr(sootCond, soot.jimple.IntConstant.v(0));
}
else {
sootCond = reverseCondition((soot.jimple.ConditionExpr)sootCond);
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
}
// add if
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
if (needIf) {
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, noop1);
body.getUnits().add(ifStmt);
// add line and pos tags
Util.addLnPosTags(ifStmt.getConditionBox(), condition.position());
Util.addLnPosTags(ifStmt, condition.position());
}
// add true nop
body.getUnits().add(tNoop);
// add consequence
polyglot.ast.Stmt consequence = ifExpr.consequent();
createStmt(consequence);
soot.jimple.Stmt noop2 = null;
if (ifExpr.alternative() != null){
noop2 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
}
body.getUnits().add(noop1);
// add false nop
body.getUnits().add(fNoop);
// handle alternative
polyglot.ast.Stmt alternative = ifExpr.alternative();
if (alternative != null){
createStmt(alternative);
body.getUnits().add(noop2);
}
}*/
/**
* If Stmts Creation - only add line-number tags to if (the other
* stmts needing tags are created elsewhere
*/
private void createIf2(polyglot.ast.If ifExpr){
soot.jimple.NopStmt endTgt = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.NopStmt brchTgt = soot.jimple.Jimple.v().newNopStmt();
// handle cond
polyglot.ast.Expr condition = ifExpr.cond();
createBranchingExpr(condition, brchTgt, false);
// add consequence
polyglot.ast.Stmt consequence = ifExpr.consequent();
createStmt(consequence);
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(endTgt);
body.getUnits().add(goto1);
body.getUnits().add(brchTgt);
// handle alternative
polyglot.ast.Stmt alternative = ifExpr.alternative();
if (alternative != null){
createStmt(alternative);
}
body.getUnits().add(endTgt);
}
private void createBranchingExpr(polyglot.ast.Expr expr, soot.jimple.Stmt tgt, boolean boto){
if (expr instanceof polyglot.ast.Binary && ((polyglot.ast.Binary)expr).operator() == polyglot.ast.Binary.COND_AND){
polyglot.ast.Binary cond_and = (polyglot.ast.Binary)expr;
if (boto){
soot.jimple.Stmt t1 = soot.jimple.Jimple.v().newNopStmt();
createBranchingExpr(cond_and.left(), t1, false);
createBranchingExpr(cond_and.right(), tgt, true);
body.getUnits().add(t1);
}
else {
createBranchingExpr(cond_and.left(), tgt, false);
createBranchingExpr(cond_and.right(), tgt, false);
}
}
else if (expr instanceof polyglot.ast.Binary && ((polyglot.ast.Binary)expr).operator() == polyglot.ast.Binary.COND_OR){
polyglot.ast.Binary cond_or = (polyglot.ast.Binary)expr;
if (boto){
createBranchingExpr(cond_or.left(), tgt, true);
createBranchingExpr(cond_or.right(), tgt, true);
}
else {
soot.jimple.Stmt t1 = soot.jimple.Jimple.v().newNopStmt();
createBranchingExpr(cond_or.left(), t1, true);
createBranchingExpr(cond_or.right(), tgt, false);
body.getUnits().add(t1);
}
}
else if (expr instanceof polyglot.ast.Unary && ((polyglot.ast.Unary)expr).operator() == polyglot.ast.Unary.NOT){
polyglot.ast.Unary not = (polyglot.ast.Unary)expr;
createBranchingExpr(not.expr(), tgt, !boto);
}
else {
soot.Value sootCond = base().createAggressiveExpr(expr, false, false);
boolean needIf = needSootIf(sootCond);
if (needIf) {
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
if (!boto){
sootCond = soot.jimple.Jimple.v().newEqExpr(sootCond, soot.jimple.IntConstant.v(0));
}
else {
sootCond = soot.jimple.Jimple.v().newNeExpr(sootCond, soot.jimple.IntConstant.v(0));
}
}
else {
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
if (!boto){
sootCond = reverseCondition((soot.jimple.ConditionExpr)sootCond);
}
}
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, tgt);
body.getUnits().add(ifStmt);
// add line and pos tags
Util.addLnPosTags(ifStmt.getConditionBox(), expr.position());
Util.addLnPosTags(ifStmt, expr.position());
}
//for an "if(true) goto tgt" we have to branch always; for an "if(true) goto tgt" we just
//do nothing at all
//(if boto is false then we have to reverse the meaning)
else if(sootCond instanceof IntConstant && (((IntConstant)sootCond).value == 1)==boto){
soot.jimple.GotoStmt gotoStmt = soot.jimple.Jimple.v().newGotoStmt(tgt);
body.getUnits().add(gotoStmt);
// add line and pos tags
Util.addLnPosTags(gotoStmt, expr.position());
}
}
}
/**
* While Stmts Creation
*/
/*private void createWhile(polyglot.ast.While whileStmt){
// create true/false noops to handle cond and/or
trueNoop.push(soot.jimple.Jimple.v().newNopStmt());
falseNoop.push(soot.jimple.Jimple.v().newNopStmt());
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
// these are for break and continue
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
condControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
body.getUnits().add(noop2);
// handle cond
soot.jimple.Stmt continueStmt = (soot.jimple.Stmt)condControlNoop.pop();
body.getUnits().add(continueStmt);
condControlNoop.push(continueStmt);
polyglot.ast.Expr condition = whileStmt.cond();
soot.Value sootCond = base().createExpr(condition);
soot.jimple.Stmt tNoop = (soot.jimple.Stmt)trueNoop.pop();
soot.jimple.Stmt fNoop = (soot.jimple.Stmt)falseNoop.pop();
boolean needIf = needSootIf(sootCond);
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
sootCond = soot.jimple.Jimple.v().newEqExpr(sootCond, soot.jimple.IntConstant.v(0));
}
else {
sootCond = reverseCondition((soot.jimple.ConditionExpr)sootCond);
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
}
if (needIf){
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, noop1);
body.getUnits().add(ifStmt);
Util.addLnPosTags(ifStmt.getConditionBox(), condition.position());
Util.addLnPosTags(ifStmt, condition.position());
}
body.getUnits().add(tNoop);
createStmt(whileStmt.body());
soot.jimple.GotoStmt gotoLoop = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(gotoLoop);
body.getUnits().add((soot.jimple.Stmt)(endControlNoop.pop()));
body.getUnits().add(noop1);
body.getUnits().add(fNoop);
condControlNoop.pop();
}*/
/**
* While Stmts Creation
*/
private void createWhile2(polyglot.ast.While whileStmt){
soot.jimple.Stmt brchTgt = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt beginTgt = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(beginTgt);
// these are for break and continue
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
condControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
// handle cond
soot.jimple.Stmt continueStmt = condControlNoop.pop();
body.getUnits().add(continueStmt);
condControlNoop.push(continueStmt);
polyglot.ast.Expr condition = whileStmt.cond();
createBranchingExpr(condition, brchTgt, false);
createStmt(whileStmt.body());
soot.jimple.GotoStmt gotoLoop = soot.jimple.Jimple.v().newGotoStmt(beginTgt);
body.getUnits().add(gotoLoop);
body.getUnits().add((endControlNoop.pop()));
body.getUnits().add(brchTgt);
condControlNoop.pop();
}
/**
* DoWhile Stmts Creation
*/
/*private void createDo(polyglot.ast.Do doStmt){
// create true/false noops to handle cond and/or
soot.jimple.Stmt tNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt fNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop1);
// add true noop - for cond and/or
body.getUnits().add(tNoop);
// these are for break and continue
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
condControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
// handle body
createStmt(doStmt.body());
// handle cond
soot.jimple.Stmt continueStmt = (soot.jimple.Stmt)condControlNoop.pop();
body.getUnits().add(continueStmt);
condControlNoop.push(continueStmt);
// handle label continue
//if ((labelContinueMap != null) && (labelContinueMap.containsKey(lastLabel))){
if (labelMap != null && labelMap.containsKey(doStmt)){
body.getUnits().add((soot.jimple.Stmt)labelMap.get(doStmt));
}
/*if ((labelContinueMap != null) && (labelStack != null) && (!labelStack.isEmpty()) && (labelContinueMap.containsKey(((LabelKey)labelStack.peek()).label()))){
body.getUnits().add((soot.jimple.Stmt)labelContinueMap.get(((LabelKey)labelStack.peek()).label()));
}*/
/* trueNoop.push(tNoop);
falseNoop.push(fNoop);
polyglot.ast.Expr condition = doStmt.cond();
soot.Value sootCond = base().createExpr(condition);
trueNoop.pop();
boolean needIf = needSootIf(sootCond);
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
sootCond = soot.jimple.Jimple.v().newNeExpr(sootCond, soot.jimple.IntConstant.v(0));
}
else {
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
}
if (needIf){
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, noop1);
body.getUnits().add(ifStmt);
Util.addPosTag(ifStmt.getConditionBox(), condition.position());
Util.addLnPosTags(ifStmt, condition.position());
}
else {
soot.jimple.GotoStmt gotoIf = soot.jimple.Jimple.v().newGotoStmt(noop1);
body.getUnits().add(gotoIf);
}
body.getUnits().add((soot.jimple.Stmt)(endControlNoop.pop()));
condControlNoop.pop();
body.getUnits().add(falseNoop.pop());
}*/
/**
* DoWhile Stmts Creation
*/
private void createDo2(polyglot.ast.Do doStmt){
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop1);
// these are for break and continue
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
condControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
// handle body
createStmt(doStmt.body());
// handle cond
soot.jimple.Stmt continueStmt = condControlNoop.pop();
body.getUnits().add(continueStmt);
condControlNoop.push(continueStmt);
if (labelMap != null && labelMap.containsKey(doStmt)){
body.getUnits().add(labelMap.get(doStmt));
}
polyglot.ast.Expr condition = doStmt.cond();
createBranchingExpr(condition, noop1, true);
body.getUnits().add((endControlNoop.pop()));
condControlNoop.pop();
}
/**
* For Loop Stmts Creation
*/
/*private void createForLoop(polyglot.ast.For forStmt){
// create true/false noops to handle cond and/or
soot.jimple.Stmt tNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt fNoop = soot.jimple.Jimple.v().newNopStmt();
// these ()are for break and continue
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
condControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
// handle for inits
Iterator initsIt = forStmt.inits().iterator();
while (initsIt.hasNext()){
createStmt((polyglot.ast.Stmt)initsIt.next());
}
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop2);
// handle cond
polyglot.ast.Expr condition = forStmt.cond();
if (condition != null) {
trueNoop.push(tNoop);
falseNoop.push(fNoop);
soot.Value sootCond = base().createExpr(condition);
trueNoop.pop();
falseNoop.pop();
boolean needIf = needSootIf(sootCond);
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
sootCond = soot.jimple.Jimple.v().newEqExpr(sootCond, soot.jimple.IntConstant.v(0));
}
else {
sootCond = reverseCondition((soot.jimple.ConditionExpr)sootCond);
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
}
if (needIf){
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, noop1);
// add cond
body.getUnits().add(ifStmt);
// add line and pos tags
Util.addLnPosTags(ifStmt.getConditionBox(), condition.position());
Util.addLnPosTags(ifStmt, condition.position());
}
//else {
// soot.jimple.GotoStmt gotoIf = soot.jimple.Jimple.v().newGotoStmt(noop1);
// body.getUnits().add(gotoIf);
//}
}
//else {
// soot.jimple.Stmt goto2 = soot.jimple.Jimple.v().newGotoStmt(noop1);
// body.getUnits().add(goto2);
//}
// handle body
//soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
//soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
//body.getUnits().add(goto1);
//body.getUnits().add(noop1);
body.getUnits().add(tNoop);
createStmt(forStmt.body());
// handle continue
body.getUnits().add((soot.jimple.Stmt)(condControlNoop.pop()));
// handle label continue
//if ((labelContinueMap != null) && (labelContinueMap.containsKey(lastLabel))){
if (labelMap != null && labelMap.containsKey(forStmt)){
body.getUnits().add((soot.jimple.Stmt)labelMap.get(forStmt));
}
/*if ((labelContinueMap != null) && (labelStack != null) && (!labelStack.isEmpty()) && (labelContinueMap.containsKey(((LabelKey)labelStack.peek()).label()))){
body.getUnits().add((soot.jimple.Stmt)labelContinueMap.get(((LabelKey)labelStack.peek()).label()));
//System.out.println("lastLabel: "+lastLabel);
//if (!body.getUnits().contains((soot.jimple.Stmt)labelContinueMap.get(lastLabel))){
// body.getUnits().add((soot.jimple.Stmt)labelContinueMap.get(lastLabel));
//}
}*/
// handle iters
/* Iterator itersIt = forStmt.iters().iterator();
//System.out.println("for iters: "+forStmt.iters());
while (itersIt.hasNext()){
createStmt((polyglot.ast.Stmt)itersIt.next());
}
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
//body.getUnits().add(noop2);
// handle cond
/*polyglot.ast.Expr condition = forStmt.cond();
if (condition != null) {
soot.Value sootCond = base().createExpr(condition);
boolean needIf = needSootIf(sootCond);
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
sootCond = soot.jimple.Jimple.v().newNeExpr(sootCond, soot.jimple.IntConstant.v(0));
}
else {
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
}
if (needIf){
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, noop1);
// add cond
body.getUnits().add(ifStmt);
// add line and pos tags
Util.addLnPosTags(ifStmt.getConditionBox(), condition.position());
Util.addLnPosTags(ifStmt, condition.position());
}
else {
soot.jimple.GotoStmt gotoIf = soot.jimple.Jimple.v().newGotoStmt(noop1);
body.getUnits().add(gotoIf);
}
}
else {
soot.jimple.Stmt goto2 = soot.jimple.Jimple.v().newGotoStmt(noop1);
body.getUnits().add(goto2);
}*/
/* body.getUnits().add(noop1);
body.getUnits().add((soot.jimple.Stmt)(endControlNoop.pop()));
body.getUnits().add(fNoop);
}*/
/**
* For Loop Stmts Creation
*/
private void createForLoop2(polyglot.ast.For forStmt){
// these ()are for break and continue
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
condControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
// handle for inits
Iterator initsIt = forStmt.inits().iterator();
while (initsIt.hasNext()){
createStmt((polyglot.ast.Stmt)initsIt.next());
}
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop2);
// handle cond
polyglot.ast.Expr condition = forStmt.cond();
if (condition != null) {
createBranchingExpr(condition, noop1, false);
}
createStmt(forStmt.body());
// handle continue
body.getUnits().add((condControlNoop.pop()));
if (labelMap != null && labelMap.containsKey(forStmt)){
body.getUnits().add(labelMap.get(forStmt));
}
// handle iters
Iterator itersIt = forStmt.iters().iterator();
while (itersIt.hasNext()){
createStmt((polyglot.ast.Stmt)itersIt.next());
}
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
body.getUnits().add(noop1);
body.getUnits().add((endControlNoop.pop()));
}
/**
* Local Decl Creation
*/
private void createLocalDecl(polyglot.ast.LocalDecl localDecl) {
//System.out.println("local decl: "+localDecl);
String name = localDecl.name();
polyglot.types.LocalInstance localInst = localDecl.localInstance();
soot.Value lhs = createLocal(localInst);
polyglot.ast.Expr expr = localDecl.init();
if (expr != null) {
//System.out.println("expr: "+expr+" get type: "+expr.getClass());
soot.Value rhs;
if (expr instanceof polyglot.ast.ArrayInit){
//System.out.println("creating array from localdecl: "+localInst.type());
rhs = getArrayInitLocal((polyglot.ast.ArrayInit)expr, localInst.type());
}
else {
//System.out.println("create local decl: "+expr+" is a: "+expr.getClass());
rhs = base().createAggressiveExpr(expr, false, false);
//System.out.println("rhs is: "+rhs+" is a: "+rhs.getClass());
}
if (rhs instanceof soot.jimple.ConditionExpr) {
rhs = handleCondBinExpr((soot.jimple.ConditionExpr)rhs);
}
//System.out.println("rhs: "+rhs);
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(lhs, rhs);
body.getUnits().add(stmt);
//Util.addLineTag(stmt, localDecl);
Util.addLnPosTags(stmt, localDecl.position());
// this is a special case for position tags
if ( localDecl.position() != null){
Util.addLnPosTags(stmt.getLeftOpBox(), localDecl.position().line(), localDecl.position().endLine(), localDecl.position().endColumn()-name.length(), localDecl.position().endColumn());
if (expr != null){
Util.addLnPosTags(stmt, localDecl.position().line(), expr.position().endLine(), localDecl.position().column(), expr.position().endColumn());
}
else {
Util.addLnPosTags(stmt, localDecl.position().line(), localDecl.position().endLine(), localDecl.position().column(), localDecl.position().endColumn());
}
}
else {
}
if (expr != null){
Util.addLnPosTags(stmt.getRightOpBox(), expr.position());
}
}
}
/**
* Switch Stmts Creation
*/
private void createSwitch(polyglot.ast.Switch switchStmt) {
polyglot.ast.Expr value = switchStmt.expr();
soot.Value sootValue = base().createAggressiveExpr(value, false, false);
if (switchStmt.elements().size() == 0) return;
soot.jimple.Stmt defaultTarget = null;
polyglot.ast.Case [] caseArray = new polyglot.ast.Case[switchStmt.elements().size()];
soot.jimple.Stmt [] targetsArray = new soot.jimple.Stmt[switchStmt.elements().size()];
ArrayList<Stmt> targets = new ArrayList<Stmt>();
HashMap<Object, Stmt> targetsMap = new HashMap<Object, Stmt>();
int counter = 0;
Iterator it = switchStmt.elements().iterator();
while (it.hasNext()) {
Object next = it.next();
if (next instanceof polyglot.ast.Case) {
soot.jimple.Stmt noop = soot.jimple.Jimple.v().newNopStmt();
if (!((polyglot.ast.Case)next).isDefault()){
targets.add(noop);
caseArray[counter] = (polyglot.ast.Case)next;
targetsArray[counter] = noop;
counter++;
targetsMap.put(next, noop);
}
else {
defaultTarget = noop;
}
}
}
// sort targets map
int lowIndex = 0;
int highIndex = 0;
for (int i = 0; i < counter; i++) {
for (int j = i+1; j < counter; j++) {
if (caseArray[j].value() < caseArray[i].value()) {
polyglot.ast.Case tempCase = caseArray[i];
soot.jimple.Stmt tempTarget = targetsArray[i];
caseArray[i] = caseArray[j];
targetsArray[i] = targetsArray[j];
caseArray[j] = tempCase;
targetsArray[j] = tempTarget;
}
}
}
ArrayList sortedTargets = new ArrayList();
for (int i = 0; i < counter; i++) {
sortedTargets.add(targetsArray[i]);
}
// deal with default
boolean hasDefaultTarget = true;
if (defaultTarget == null) {
soot.jimple.Stmt noop = soot.jimple.Jimple.v().newNopStmt();
defaultTarget = noop;
hasDefaultTarget = false;
}
// lookup or tableswitch
soot.jimple.Stmt sootSwitchStmt;
if (isLookupSwitch(switchStmt)) {
ArrayList values = new ArrayList();
for (int i = 0; i < counter; i++) {
if (!caseArray[i].isDefault()) {
values.add(soot.jimple.IntConstant.v((int)caseArray[i].value()));
}
}
soot.jimple.LookupSwitchStmt lookupStmt = soot.jimple.Jimple.v().newLookupSwitchStmt(sootValue, values, sortedTargets, defaultTarget);
Util.addLnPosTags(lookupStmt.getKeyBox(), value.position());
sootSwitchStmt = lookupStmt;
}
else {
long lowVal = 0;
long highVal = 0;
boolean unknown = true;
it = switchStmt.elements().iterator();
while (it.hasNext()){
Object next = it.next();
if (next instanceof polyglot.ast.Case) {
if (!((polyglot.ast.Case)next).isDefault()){
long temp = ((polyglot.ast.Case)next).value();
if (unknown){
highVal = temp;
lowVal = temp;
unknown = false;
}
if (temp > highVal) {
highVal = temp;
}
if (temp < lowVal) {
lowVal = temp;
}
}
}
}
soot.jimple.TableSwitchStmt tableStmt = soot.jimple.Jimple.v().newTableSwitchStmt(sootValue, (int)lowVal, (int)highVal, sortedTargets, defaultTarget);
Util.addLnPosTags(tableStmt.getKeyBox(), value.position());
sootSwitchStmt = tableStmt;
}
body.getUnits().add(sootSwitchStmt);
Util.addLnPosTags(sootSwitchStmt, switchStmt.position());
endControlNoop.push(soot.jimple.Jimple.v().newNopStmt());
it = switchStmt.elements().iterator();
Iterator<Stmt> targetsIt = targets.iterator();
while (it.hasNext()){
Object next = it.next();
if (next instanceof polyglot.ast.Case) {
if (!((polyglot.ast.Case)next).isDefault()){
body.getUnits().add(targetsMap.get(next));
}
else {
body.getUnits().add(defaultTarget);
}
}
else {
polyglot.ast.SwitchBlock blockStmt = (polyglot.ast.SwitchBlock)next;
createBlock(blockStmt);
}
}
if (!hasDefaultTarget) {
body.getUnits().add(defaultTarget);
}
body.getUnits().add((endControlNoop.pop()));
}
/**
* Determine if switch should be lookup or table - this doesn't
* always get the same result as javac
* lookup: non-table
* table: sequential (no gaps)
*/
private boolean isLookupSwitch(polyglot.ast.Switch switchStmt){
int lowest = 0;
int highest = 0;
int counter = 0;
Iterator it = switchStmt.elements().iterator();
while (it.hasNext()){
Object next = it.next();
if (next instanceof polyglot.ast.Case) {
polyglot.ast.Case caseStmt = (polyglot.ast.Case)next;
if (caseStmt.isDefault()) continue;
int caseValue = (int)caseStmt.value();
if (caseValue <= lowest || counter == 0 ) {
lowest = caseValue;
}
if (caseValue >= highest || counter == 0) {
highest = caseValue;
}
counter++;
}
}
if ((counter-1) == (highest - lowest)) return false;
return true;
}
/**
* Branch Stmts Creation
*/
private void createBranch(polyglot.ast.Branch branchStmt){
//handle finally blocks before branch if inside try block
if (tryStack != null && !tryStack.isEmpty()){
polyglot.ast.Try currentTry = tryStack.pop();
if (currentTry.finallyBlock() != null){
createBlock(currentTry.finallyBlock());
tryStack.push(currentTry);
}
else {
tryStack.push(currentTry);
}
}
//handle finally blocks before branch if inside catch block
if (catchStack != null && !catchStack.isEmpty()){
polyglot.ast.Try currentTry = catchStack.pop();
if (currentTry.finallyBlock() != null){
createBlock(currentTry.finallyBlock());
catchStack.push(currentTry);
}
else {
catchStack.push(currentTry);
}
}
body.getUnits().add(soot.jimple.Jimple.v().newNopStmt());
if (branchStmt.kind() == polyglot.ast.Branch.BREAK){
if (branchStmt.label() == null) {
soot.jimple.Stmt gotoEndNoop = endControlNoop.pop();
// handle monitor exits before break if necessary
if (monitorStack != null){
Stack<Local> putBack = new Stack<Local>();
while (!monitorStack.isEmpty()){
soot.Local exitVal = (soot.Local)monitorStack.pop();
putBack.push(exitVal);
soot.jimple.ExitMonitorStmt emStmt = soot.jimple.Jimple.v().newExitMonitorStmt(exitVal);
body.getUnits().add(emStmt);
}
while(!putBack.isEmpty()){
monitorStack.push(putBack.pop());
}
}
soot.jimple.Stmt gotoEnd = soot.jimple.Jimple.v().newGotoStmt(gotoEndNoop);
endControlNoop.push(gotoEndNoop);
body.getUnits().add(gotoEnd);
Util.addLnPosTags(gotoEnd, branchStmt.position());
}
else {
soot.jimple.Stmt gotoLabel = soot.jimple.Jimple.v().newGotoStmt(labelBreakMap.get(branchStmt.label()));
body.getUnits().add(gotoLabel);
Util.addLnPosTags(gotoLabel, branchStmt.position());
}
}
else if (branchStmt.kind() == polyglot.ast.Branch.CONTINUE){
if (branchStmt.label() == null) {
soot.jimple.Stmt gotoCondNoop = condControlNoop.pop();
// handle monitor exits before continue if necessary
if (monitorStack != null){
Stack<Local> putBack = new Stack<Local>();
while (!monitorStack.isEmpty()){
soot.Local exitVal = (soot.Local)monitorStack.pop();
putBack.push(exitVal);
soot.jimple.ExitMonitorStmt emStmt = soot.jimple.Jimple.v().newExitMonitorStmt(exitVal);
body.getUnits().add(emStmt);
}
while(!putBack.isEmpty()){
monitorStack.push(putBack.pop());
}
}
soot.jimple.Stmt gotoCond = soot.jimple.Jimple.v().newGotoStmt(gotoCondNoop);
condControlNoop.push(gotoCondNoop);
body.getUnits().add(gotoCond);
Util.addLnPosTags(gotoCond, branchStmt.position());
}
else {
soot.jimple.Stmt gotoLabel = soot.jimple.Jimple.v().newGotoStmt(labelContinueMap.get(branchStmt.label()));
body.getUnits().add(gotoLabel);
Util.addLnPosTags(gotoLabel, branchStmt.position());
}
}
}
/**
* Labeled Stmt Creation
*/
private void createLabeled(polyglot.ast.Labeled labeledStmt){
String label = labeledStmt.label();
//lastLabel = label;
polyglot.ast.Stmt stmt = labeledStmt.statement();
soot.jimple.Stmt noop = soot.jimple.Jimple.v().newNopStmt();
//System.out.println("labeled stmt type: "+stmt.getClass());
if (!(stmt instanceof polyglot.ast.For) && !(stmt instanceof polyglot.ast.Do)){
body.getUnits().add(noop);
}
/*else {
if (labelStack == null){
labelStack = new Stack();
}
labelStack.push(new LabelKey(label, noop));
}*/
if (labelMap == null){
labelMap = new HashMap<polyglot.ast.Stmt, Stmt>();
}
labelMap.put(stmt, noop);
if (labelBreakMap == null) {
labelBreakMap = new HashMap<String, Stmt>();
}
if (labelContinueMap == null) {
labelContinueMap = new HashMap<String, Stmt>();
}
labelContinueMap.put(label, noop);
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
labelBreakMap.put(label, noop2);
createStmt(stmt);
/*if (labelStack != null && !labelStack.isEmpty() && (stmt instanceof polyglot.ast.For || stmt instanceof polyglot.ast.Do)){
labelStack.pop();
}*/
body.getUnits().add(noop2);
// the idea here is to make a map of labels to the first
// jimple stmt of the stmt (a noop) to be created - so
// there is something to look up for breaks and continues
// with labels
}
/*class LabelKey{
public LabelKey(String label, soot.jimple.Stmt noop){
this.label = label;
this.noop = noop;
}
private String label;
public String label(){
return label;
}
private soot.jimple.Stmt noop;
public soot.jimple.Stmt noop(){
return noop;
}
}*/
/**
* Assert Stmt Creation
*/
private void createAssert(polyglot.ast.Assert assertStmt) {
// check if assertions are disabled
soot.Local testLocal = lg.generateLocal(soot.BooleanType.v());
soot.SootFieldRef assertField = soot.Scene.v().makeFieldRef(body.getMethod().getDeclaringClass(), "$assertionsDisabled", soot.BooleanType.v(), true);
soot.jimple.FieldRef assertFieldRef = soot.jimple.Jimple.v().newStaticFieldRef(assertField);
soot.jimple.AssignStmt fieldAssign = soot.jimple.Jimple.v().newAssignStmt(testLocal, assertFieldRef);
body.getUnits().add(fieldAssign);
soot.jimple.NopStmt nop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.ConditionExpr cond1 = soot.jimple.Jimple.v().newNeExpr(testLocal, soot.jimple.IntConstant.v(0));
soot.jimple.IfStmt testIf = soot.jimple.Jimple.v().newIfStmt(cond1, nop1);
body.getUnits().add(testIf);
// actual cond test
if ((assertStmt.cond() instanceof polyglot.ast.BooleanLit) && (!((polyglot.ast.BooleanLit)assertStmt.cond()).value())){
// don't makeif
}
else {
soot.Value sootCond = base().createAggressiveExpr(assertStmt.cond(), false, false);
boolean needIf = needSootIf(sootCond);
if (!(sootCond instanceof soot.jimple.ConditionExpr)) {
sootCond = soot.jimple.Jimple.v().newEqExpr(sootCond, soot.jimple.IntConstant.v(1));
}
else {
sootCond = handleDFLCond((soot.jimple.ConditionExpr)sootCond);
}
if (needIf){
// add if
soot.jimple.IfStmt ifStmt = soot.jimple.Jimple.v().newIfStmt(sootCond, nop1);
body.getUnits().add(ifStmt);
Util.addLnPosTags(ifStmt.getConditionBox(), assertStmt.cond().position());
Util.addLnPosTags(ifStmt, assertStmt.position());
}
}
// assertion failure code
soot.Local failureLocal = lg.generateLocal(soot.RefType.v("java.lang.AssertionError"));
soot.jimple.NewExpr newExpr = soot.jimple.Jimple.v().newNewExpr(soot.RefType.v("java.lang.AssertionError"));
soot.jimple.AssignStmt newAssign = soot.jimple.Jimple.v().newAssignStmt(failureLocal, newExpr);
body.getUnits().add(newAssign);
soot.SootMethodRef methToInvoke;
ArrayList paramTypes = new ArrayList();
ArrayList params = new ArrayList();
if (assertStmt.errorMessage() != null){
soot.Value errorExpr = base().createAggressiveExpr(assertStmt.errorMessage(), false, false);
if (errorExpr instanceof soot.jimple.ConditionExpr) {
errorExpr = handleCondBinExpr((soot.jimple.ConditionExpr)errorExpr);
}
soot.Type errorType = errorExpr.getType();
if (assertStmt.errorMessage().type().isChar()){
errorType = soot.CharType.v();
}
if (errorType instanceof soot.IntType) {
paramTypes.add(soot.IntType.v());
}
else if (errorType instanceof soot.LongType){
paramTypes.add(soot.LongType.v());
}
else if (errorType instanceof soot.FloatType){
paramTypes.add(soot.FloatType.v());
}
else if (errorType instanceof soot.DoubleType){
paramTypes.add(soot.DoubleType.v());
}
else if (errorType instanceof soot.CharType){
paramTypes.add(soot.CharType.v());
}
else if (errorType instanceof soot.BooleanType){
paramTypes.add(soot.BooleanType.v());
}
else if (errorType instanceof soot.ShortType){
paramTypes.add(soot.IntType.v());
}
else if (errorType instanceof soot.ByteType){
paramTypes.add(soot.IntType.v());
}
else {
paramTypes.add(soot.Scene.v().getSootClass("java.lang.Object").getType());
}
params.add(errorExpr);
}
methToInvoke = soot.Scene.v().makeMethodRef( soot.Scene.v().getSootClass("java.lang.AssertionError"), "<init>", paramTypes, soot.VoidType.v(), false);
soot.jimple.SpecialInvokeExpr invokeExpr = soot.jimple.Jimple.v().newSpecialInvokeExpr(failureLocal, methToInvoke, params);
soot.jimple.InvokeStmt invokeStmt = soot.jimple.Jimple.v().newInvokeStmt(invokeExpr);
body.getUnits().add(invokeStmt);
if (assertStmt.errorMessage() != null){
Util.addLnPosTags(invokeExpr.getArgBox(0), assertStmt.errorMessage().position());
}
soot.jimple.ThrowStmt throwStmt = soot.jimple.Jimple.v().newThrowStmt(failureLocal);
body.getUnits().add(throwStmt);
// end
body.getUnits().add(nop1);
}
/**
* Synchronized Stmt Creation
*/
private void createSynchronized(polyglot.ast.Synchronized synchStmt) {
soot.Value sootExpr = base().createAggressiveExpr(synchStmt.expr(), false, false);
soot.jimple.EnterMonitorStmt enterMon = soot.jimple.Jimple.v().newEnterMonitorStmt(sootExpr);
body.getUnits().add(enterMon);
if (beforeReturn == null)
{
beforeReturn = new ArrayList<List<Stmt>>();
}
if (afterReturn == null)
{
afterReturn = new ArrayList<List<Stmt>>();
}
beforeReturn.add(new ArrayList<Stmt>());
afterReturn.add(new ArrayList<Stmt>());
if (monitorStack == null){
monitorStack = new Stack<Value>();
}
monitorStack.push(sootExpr);
Util.addLnPosTags(enterMon.getOpBox(), synchStmt.expr().position());
Util.addLnPosTags(enterMon, synchStmt.expr().position());
soot.jimple.Stmt startNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(startNoop);
createBlock(synchStmt.body());
soot.jimple.ExitMonitorStmt exitMon = soot.jimple.Jimple.v().newExitMonitorStmt(sootExpr);
body.getUnits().add(exitMon);
monitorStack.pop();
Util.addLnPosTags(exitMon.getOpBox(), synchStmt.expr().position());
Util.addLnPosTags(exitMon, synchStmt.expr().position());
soot.jimple.Stmt endSynchNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt gotoEnd = soot.jimple.Jimple.v().newGotoStmt(endSynchNoop);
soot.jimple.Stmt endNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(endNoop);
body.getUnits().add(gotoEnd);
soot.jimple.Stmt catchAllBeforeNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchAllBeforeNoop);
// catch all
soot.Local formalLocal = lg.generateLocal(soot.RefType.v("java.lang.Throwable"));
soot.jimple.CaughtExceptionRef exceptRef = soot.jimple.Jimple.v().newCaughtExceptionRef();
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newIdentityStmt(formalLocal, exceptRef);
body.getUnits().add(stmt);
// catch
soot.jimple.Stmt catchBeforeNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchBeforeNoop);
soot.Local local = lg.generateLocal(soot.RefType.v("java.lang.Throwable"));
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(local, formalLocal);
body.getUnits().add(assign);
soot.jimple.ExitMonitorStmt catchExitMon = soot.jimple.Jimple.v().newExitMonitorStmt(sootExpr);
body.getUnits().add(catchExitMon);
Util.addLnPosTags(catchExitMon.getOpBox(), synchStmt.expr().position());
soot.jimple.Stmt catchAfterNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchAfterNoop);
// throw
soot.jimple.Stmt throwStmt = soot.jimple.Jimple.v().newThrowStmt(local);
body.getUnits().add(throwStmt);
body.getUnits().add(endSynchNoop);
/* add to the exceptionList all the ranges dictated by the returns found
* (the problem is that return statements are not within the traps
* because just before the return all locks have already been released)
*/
List<Stmt> before = beforeReturn.get(beforeReturn.size()-1); //last element
List<Stmt> after = afterReturn.get(afterReturn.size()-1); //last element
if (before.size() > 0)
{
addToExceptionList(startNoop, before.get(0), catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
for (int i = 1; i < before.size(); i++)
{
addToExceptionList(after.get(i-1), before.get(i), catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
}
addToExceptionList(after.get(after.size()-1), endNoop, catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
}
else
{
addToExceptionList(startNoop, endNoop, catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
}
beforeReturn.remove(before);
afterReturn.remove(after);
addToExceptionList(catchBeforeNoop, catchAfterNoop, catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
}
/**
* Return Stmts Creation
*/
private void createReturn(polyglot.ast.Return retStmt) {
polyglot.ast.Expr expr = retStmt.expr();
soot.Value sootLocal = null;
if (expr != null){
sootLocal = base().createAggressiveExpr(expr, false, false);
}
// handle monitor exits before return if necessary
if (monitorStack != null){
Stack<Local> putBack = new Stack<Local>();
while (!monitorStack.isEmpty()){
soot.Local exitVal = (soot.Local)monitorStack.pop();
putBack.push(exitVal);
soot.jimple.ExitMonitorStmt emStmt = soot.jimple.Jimple.v().newExitMonitorStmt(exitVal);
body.getUnits().add(emStmt);
}
while(!putBack.isEmpty()){
monitorStack.push(putBack.pop());
}
//put label after exitmonitor(s) to mark where to stop the synch try block
soot.jimple.Stmt stopNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(stopNoop);
if (beforeReturn != null) // add to the list(s) of returns to be handled in the createSynch method
{
for (List<Stmt> v: beforeReturn)
{
v.add(stopNoop);
}
}
}
//handle finally blocks before return if inside try block
if (tryStack != null && !tryStack.isEmpty()){
polyglot.ast.Try currentTry = tryStack.pop();
if (currentTry.finallyBlock() != null){
createBlock(currentTry.finallyBlock());
tryStack.push(currentTry);
// if return stmt contains a return don't create the other return
//ReturnStmtChecker rsc = new ReturnStmtChecker();
//currentTry.finallyBlock().visit(rsc);
//if (rsc.hasRet()){
// return;
//}
}
else {
tryStack.push(currentTry);
}
}
//handle finally blocks before return if inside catch block
if (catchStack != null && !catchStack.isEmpty()){
polyglot.ast.Try currentTry = catchStack.pop();
if (currentTry.finallyBlock() != null){
createBlock(currentTry.finallyBlock());
catchStack.push(currentTry);
// if return stmt contains a return don't create the other return
// extra return remove with some Soot phase
//ReturnStmtChecker rsc = new ReturnStmtChecker();
//currentTry.finallyBlock().visit(rsc);
//if (rsc.hasRet()){
// return;
//}
}
else {
catchStack.push(currentTry);
}
}
// return
if (expr == null) {
soot.jimple.Stmt retStmtVoid = soot.jimple.Jimple.v().newReturnVoidStmt();
body.getUnits().add(retStmtVoid);
Util.addLnPosTags(retStmtVoid, retStmt.position());
}
else {
//soot.Value sootLocal = createExpr(expr);
if (sootLocal instanceof soot.jimple.ConditionExpr) {
sootLocal = handleCondBinExpr((soot.jimple.ConditionExpr)sootLocal);
}
soot.jimple.ReturnStmt retStmtLocal = soot.jimple.Jimple.v().newReturnStmt(sootLocal);
body.getUnits().add(retStmtLocal);
Util.addLnPosTags(retStmtLocal.getOpBox(), expr.position());
Util.addLnPosTags(retStmtLocal, retStmt.position());
}
//after the return is handled, put another label to show the new start point of the synch try block
soot.jimple.Stmt startNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(startNoop);
if (afterReturn != null) // add to the list(s) of returns to be handled in the createSynch method
{
for (List<Stmt> v: afterReturn)
{
v.add(startNoop);
}
}
}
/**
* Throw Stmt Creation
*/
private void createThrow(polyglot.ast.Throw throwStmt){
soot.Value toThrow = base().createAggressiveExpr(throwStmt.expr(), false, false);
soot.jimple.ThrowStmt throwSt = soot.jimple.Jimple.v().newThrowStmt(toThrow);
body.getUnits().add(throwSt);
Util.addLnPosTags(throwSt, throwStmt.position());
Util.addLnPosTags(throwSt.getOpBox(), throwStmt.expr().position());
}
/**
* Try Stmt Creation
*/
private void createTry(polyglot.ast.Try tryStmt) {
polyglot.ast.Block finallyBlock = tryStmt.finallyBlock();
if (finallyBlock == null) {
createTryCatch(tryStmt);
}
else {
createTryCatchFinally(tryStmt);
}
}
/**
* handles try/catch (try/catch/finally is separate for simplicity)
*/
private void createTryCatch(polyglot.ast.Try tryStmt){
// try
polyglot.ast.Block tryBlock = tryStmt.tryBlock();
// this nop is for the fromStmt of try
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop1);
if (tryStack == null){
tryStack = new Stack<Try>();
}
tryStack.push(tryStmt);
createBlock(tryBlock);
tryStack.pop();
// this nop is for the toStmt of try
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop2);
// create end nop for after entire try/catch
soot.jimple.Stmt endNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt tryEndGoto = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(tryEndGoto);
Iterator it = tryStmt.catchBlocks().iterator();
while (it.hasNext()) {
soot.jimple.Stmt noop3 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop3);
// create catch stmts
polyglot.ast.Catch catchBlock = (polyglot.ast.Catch)it.next();
// create catch ref
createCatchFormal(catchBlock.formal());
if (catchStack == null){
catchStack = new Stack<Try>();
}
catchStack.push(tryStmt);
createBlock(catchBlock.body());
catchStack.pop();
soot.jimple.Stmt catchEndGoto = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(catchEndGoto);
soot.Type sootType = Util.getSootType(catchBlock.catchType());
addToExceptionList(noop1, noop2, noop3, soot.Scene.v().getSootClass(sootType.toString()));
}
body.getUnits().add(endNoop);
}
/**
* handles try/catch/finally (try/catch is separate for simplicity)
*/
private void createTryCatchFinally(polyglot.ast.Try tryStmt){
HashMap<Stmt, Stmt> gotoMap = new HashMap<Stmt, Stmt>();
// try
polyglot.ast.Block tryBlock = tryStmt.tryBlock();
// this nop is for the fromStmt of try
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop1);
if (tryStack == null){
tryStack = new Stack<Try>();
}
tryStack.push(tryStmt);
createBlock(tryBlock);
tryStack.pop();
// this nop is for the toStmt of try
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop2);
// create end nop for after entire try/catch
soot.jimple.Stmt endNoop = soot.jimple.Jimple.v().newNopStmt();
// to finally
soot.jimple.Stmt tryGotoFinallyNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(tryGotoFinallyNoop);
soot.jimple.Stmt tryFinallyNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt tryGotoFinally = soot.jimple.Jimple.v().newGotoStmt(tryFinallyNoop);
body.getUnits().add(tryGotoFinally);
// goto end stmts
soot.jimple.Stmt beforeEndGotoNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(beforeEndGotoNoop);
soot.jimple.Stmt tryEndGoto = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(tryEndGoto);
gotoMap.put(tryFinallyNoop, beforeEndGotoNoop);
// catch section
soot.jimple.Stmt catchAllBeforeNoop = soot.jimple.Jimple.v().newNopStmt();
Iterator it = tryStmt.catchBlocks().iterator();
while (it.hasNext()) {
soot.jimple.Stmt noop3 = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(noop3);
// create catch stmts
polyglot.ast.Catch catchBlock = (polyglot.ast.Catch)it.next();
// create catch ref
soot.jimple.Stmt catchRefNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchRefNoop);
createCatchFormal(catchBlock.formal());
soot.jimple.Stmt catchStmtsNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchStmtsNoop);
if (catchStack == null){
catchStack = new Stack<Try>();
}
catchStack.push(tryStmt);
createBlock(catchBlock.body());
catchStack.pop();
// to finally
soot.jimple.Stmt catchGotoFinallyNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchGotoFinallyNoop);
soot.jimple.Stmt catchFinallyNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt catchGotoFinally = soot.jimple.Jimple.v().newGotoStmt(catchFinallyNoop);
body.getUnits().add(catchGotoFinally);
// goto end stmts
soot.jimple.Stmt beforeCatchEndGotoNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(beforeCatchEndGotoNoop);
soot.jimple.Stmt catchEndGoto = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(catchEndGoto);
gotoMap.put(catchFinallyNoop, beforeCatchEndGotoNoop);
soot.Type sootType = Util.getSootType(catchBlock.catchType());
addToExceptionList(noop1, noop2, noop3, soot.Scene.v().getSootClass(sootType.toString()));
addToExceptionList(catchStmtsNoop, beforeCatchEndGotoNoop, catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
}
// catch all ref
soot.Local formalLocal = lg.generateLocal(soot.RefType.v("java.lang.Throwable"));
body.getUnits().add(catchAllBeforeNoop);
soot.jimple.CaughtExceptionRef exceptRef = soot.jimple.Jimple.v().newCaughtExceptionRef();
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newIdentityStmt(formalLocal, exceptRef);
body.getUnits().add(stmt);
// catch all assign
soot.jimple.Stmt beforeCatchAllAssignNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(beforeCatchAllAssignNoop);
soot.Local catchAllAssignLocal = lg.generateLocal(soot.RefType.v("java.lang.Throwable"));
soot.jimple.Stmt catchAllAssign = soot.jimple.Jimple.v().newAssignStmt(catchAllAssignLocal, formalLocal);
body.getUnits().add(catchAllAssign);
// catch all finally
soot.jimple.Stmt catchAllFinallyNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt catchAllGotoFinally = soot.jimple.Jimple.v().newGotoStmt(catchAllFinallyNoop);
body.getUnits().add(catchAllGotoFinally);
// catch all throw
soot.jimple.Stmt catchAllBeforeThrowNoop = soot.jimple.Jimple.v().newNopStmt();
body.getUnits().add(catchAllBeforeThrowNoop);
soot.jimple.Stmt throwStmt = soot.jimple.Jimple.v().newThrowStmt(catchAllAssignLocal);
throwStmt.addTag(new soot.tagkit.ThrowCreatedByCompilerTag());
body.getUnits().add(throwStmt);
gotoMap.put(catchAllFinallyNoop, catchAllBeforeThrowNoop);
// catch all goto end
soot.jimple.Stmt catchAllGotoEnd = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(catchAllGotoEnd);
addToExceptionList(beforeCatchAllAssignNoop, catchAllBeforeThrowNoop ,catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
// create finally's
Iterator<Stmt> finallyIt = gotoMap.keySet().iterator();
while (finallyIt.hasNext()) {
soot.jimple.Stmt noopStmt = finallyIt.next();
body.getUnits().add(noopStmt);
createBlock(tryStmt.finallyBlock());
soot.jimple.Stmt backToStmt = gotoMap.get(noopStmt);
soot.jimple.Stmt backToGoto = soot.jimple.Jimple.v().newGotoStmt(backToStmt);
body.getUnits().add(backToGoto);
}
body.getUnits().add(endNoop);
addToExceptionList(noop1, beforeEndGotoNoop, catchAllBeforeNoop, soot.Scene.v().getSootClass("java.lang.Throwable"));
}
/**
* add exceptions to a list that gets added at end of method
*/
private void addToExceptionList(soot.jimple.Stmt from, soot.jimple.Stmt to, soot.jimple.Stmt with, soot.SootClass exceptionClass) {
if (exceptionTable == null) {
exceptionTable = new ArrayList<Trap>();
}
soot.Trap trap = soot.jimple.Jimple.v().newTrap(exceptionClass, from, to, with);
exceptionTable.add(trap);
}
public soot.jimple.Constant createConstant(polyglot.ast.Expr expr){
Object constantVal = expr.constantValue();
//System.out.println("expr: "+expr);
return getConstant(constantVal, expr.type());
}
/**
* Expression Creation
*/
/*protected soot.Value createExpr(polyglot.ast.Expr expr){
//System.out.println("create expr: "+expr+" type: "+expr.getClass());
// maybe right here check if expr has constant val and return that
// instead
if (expr.isConstant() && expr.constantValue() != null && expr.type() != null && !(expr instanceof polyglot.ast.Binary && expr.type().toString().equals("java.lang.String")) ){
return createConstant(expr);
}
if (expr instanceof polyglot.ast.Assign) {
return getAssignLocal((polyglot.ast.Assign)expr);
}
else if (expr instanceof polyglot.ast.Lit) {
return createLiteral((polyglot.ast.Lit)expr);
}
else if (expr instanceof polyglot.ast.Local) {
return getLocal((polyglot.ast.Local)expr);
}
else if (expr instanceof polyglot.ast.Binary) {
return getBinaryLocal((polyglot.ast.Binary)expr);
}
else if (expr instanceof polyglot.ast.Unary) {
return getUnaryLocal((polyglot.ast.Unary)expr);
}
else if (expr instanceof polyglot.ast.Cast) {
return getCastLocal((polyglot.ast.Cast)expr);
}
//else if (expr instanceof polyglot.ast.ArrayInit) {
// array init are special and get created elsewhere
//}
else if (expr instanceof polyglot.ast.ArrayAccess) {
return getArrayRefLocal((polyglot.ast.ArrayAccess)expr);
}
else if (expr instanceof polyglot.ast.NewArray) {
return getNewArrayLocal((polyglot.ast.NewArray)expr);
}
else if (expr instanceof polyglot.ast.Call) {
return getCallLocal((polyglot.ast.Call)expr);
}
else if (expr instanceof polyglot.ast.New) {
return getNewLocal((polyglot.ast.New)expr);
}
else if (expr instanceof polyglot.ast.Special) {
return getSpecialLocal((polyglot.ast.Special)expr);
}
else if (expr instanceof polyglot.ast.Instanceof) {
return getInstanceOfLocal((polyglot.ast.Instanceof)expr);
}
else if (expr instanceof polyglot.ast.Conditional) {
return getConditionalLocal((polyglot.ast.Conditional)expr);
}
else if (expr instanceof polyglot.ast.Field) {
return getFieldLocal((polyglot.ast.Field)expr);
}
else {
throw new RuntimeException("Unhandled Expression: "+expr);
}
}*/
/**
* Aggressive Expression Creation
* make reduceAggressively true to not reduce all the way to a local
*/
protected soot.Value createAggressiveExpr(polyglot.ast.Expr expr, boolean reduceAggressively, boolean reverseCondIfNec){
//System.out.println("create expr: "+expr+" type: "+expr.getClass());
// maybe right here check if expr has constant val and return that
// instead
if (expr.isConstant() && expr.constantValue() != null && expr.type() != null && !(expr instanceof polyglot.ast.Binary && expr.type().toString().equals("java.lang.String")) ){
return createConstant(expr);
}
if (expr instanceof polyglot.ast.Assign) {
return getAssignLocal((polyglot.ast.Assign)expr);
}
else if (expr instanceof polyglot.ast.Lit) {
return createLiteral((polyglot.ast.Lit)expr);
}
else if (expr instanceof polyglot.ast.Local) {
return getLocal((polyglot.ast.Local)expr);
}
else if (expr instanceof polyglot.ast.Binary) {
return getBinaryLocal2((polyglot.ast.Binary)expr, reduceAggressively);
}
else if (expr instanceof polyglot.ast.Unary) {
return getUnaryLocal((polyglot.ast.Unary)expr);
}
else if (expr instanceof polyglot.ast.Cast) {
return getCastLocal((polyglot.ast.Cast)expr);
}
//else if (expr instanceof polyglot.ast.ArrayInit) {
// array init are special and get created elsewhere
//}
else if (expr instanceof polyglot.ast.ArrayAccess) {
return getArrayRefLocal((polyglot.ast.ArrayAccess)expr);
}
else if (expr instanceof polyglot.ast.NewArray) {
return getNewArrayLocal((polyglot.ast.NewArray)expr);
}
else if (expr instanceof polyglot.ast.Call) {
return getCallLocal((polyglot.ast.Call)expr);
}
else if (expr instanceof polyglot.ast.New) {
return getNewLocal((polyglot.ast.New)expr);
}
else if (expr instanceof polyglot.ast.Special) {
return getSpecialLocal((polyglot.ast.Special)expr);
}
else if (expr instanceof polyglot.ast.Instanceof) {
return getInstanceOfLocal((polyglot.ast.Instanceof)expr);
}
else if (expr instanceof polyglot.ast.Conditional) {
return getConditionalLocal((polyglot.ast.Conditional)expr);
}
else if (expr instanceof polyglot.ast.Field) {
return getFieldLocal((polyglot.ast.Field)expr);
}
else {
throw new RuntimeException("Unhandled Expression: "+expr);
}
}
protected soot.Local handlePrivateFieldUnarySet(polyglot.ast.Unary unary){
polyglot.ast.Field fLeft = (polyglot.ast.Field)unary.expr();
soot.Value base = base().getBaseLocal(fLeft.target());
soot.Value fieldGetLocal = getPrivateAccessFieldLocal(fLeft, base);
soot.Local tmp = generateLocal(fLeft.type());
soot.jimple.AssignStmt stmt1 = soot.jimple.Jimple.v().newAssignStmt(tmp, fieldGetLocal);
body.getUnits().add(stmt1);
Util.addLnPosTags(stmt1, unary.position());
soot.Value incVal = base().getConstant(Util.getSootType(fLeft.type()), 1);
soot.jimple.BinopExpr binExpr;
if (unary.operator() == polyglot.ast.Unary.PRE_INC || unary.operator() == polyglot.ast.Unary.POST_INC){
binExpr = soot.jimple.Jimple.v().newAddExpr(tmp, incVal);
}
else {
binExpr = soot.jimple.Jimple.v().newSubExpr(tmp, incVal);
}
soot.Local tmp2 = generateLocal(fLeft.type());
soot.jimple.AssignStmt assign = soot.jimple.Jimple.v().newAssignStmt(tmp2, binExpr);
body.getUnits().add(assign);
if (unary.operator() == polyglot.ast.Unary.PRE_INC || unary.operator() == polyglot.ast.Unary.PRE_DEC){
return base().handlePrivateFieldSet(fLeft, tmp2, base);
}
else {
base().handlePrivateFieldSet(fLeft, tmp2, base);
return tmp;
}
}
protected soot.Local handlePrivateFieldAssignSet(polyglot.ast.Assign assign){
polyglot.ast.Field fLeft = (polyglot.ast.Field)assign.left();
//soot.Value right = createExpr(assign.right());
// if assign is not = but +=, -=, *=, /=, >>=, >>>-, <<=, %=,
// |= &= or ^= then compute it all into a local first
//if (assign.operator() != polyglot.ast.Assign.ASSIGN){
// in this cas can cast to local (never a string const here
// as it has to be a lhs
soot.Value right;
soot.Value fieldBase = base().getBaseLocal(fLeft.target());
if (assign.operator() == polyglot.ast.Assign.ASSIGN){
right = base().getSimpleAssignRightLocal(assign);
}
else if ((assign.operator() == polyglot.ast.Assign.ADD_ASSIGN) && assign.type().toString().equals("java.lang.String")){
right = getStringConcatAssignRightLocal(assign);
}
else {
// here the lhs is a private field and needs to use get call
soot.Local leftLocal = getPrivateAccessFieldLocal(fLeft, fieldBase);
//soot.Local leftLocal = (soot.Local)base().createExpr(fLeft);
right = base().getAssignRightLocal(assign, leftLocal);
}
return handlePrivateFieldSet(fLeft, right, fieldBase);
}
protected soot.Local handlePrivateFieldSet(polyglot.ast.Expr expr, soot.Value right, soot.Value base){
// in normal j2j its always a field (and checked before call)
// only has an expr for param for extensibility
polyglot.ast.Field fLeft = (polyglot.ast.Field)expr;
soot.SootClass containClass = ((soot.RefType)Util.getSootType(fLeft.target().type())).getSootClass();
soot.SootMethod methToUse = addSetAccessMeth(containClass, fLeft, right);
ArrayList params = new ArrayList();
if (!fLeft.flags().isStatic()){
// this is the this ref if needed
//params.add(getThis(Util.getSootType(fLeft.target().type())));
params.add(base);
}
params.add(right);
soot.jimple.InvokeExpr invoke = soot.jimple.Jimple.v().newStaticInvokeExpr(methToUse.makeRef(), params);
soot.Local retLocal = lg.generateLocal(right.getType());
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, invoke);
body.getUnits().add(assignStmt);
return retLocal;
}
private soot.SootMethod addSetAccessMeth(soot.SootClass conClass, polyglot.ast.Field field, soot.Value param){
if ((InitialResolver.v().getPrivateFieldSetAccessMap() != null) && (InitialResolver.v().getPrivateFieldSetAccessMap().containsKey(new polyglot.util.IdentityKey(field.fieldInstance())))){
return InitialResolver.v().getPrivateFieldSetAccessMap().get(new polyglot.util.IdentityKey(field.fieldInstance()));
}
String name = "access$"+soot.javaToJimple.InitialResolver.v().getNextPrivateAccessCounter()+"00";
ArrayList paramTypes = new ArrayList();
if (!field.flags().isStatic()){
// add this param type
paramTypes.add(conClass.getType());
//paramTypes.add(Util.getSootType(field.target().type()));
}
soot.Type retType;
paramTypes.add(Util.getSootType(field.type()));
retType = Util.getSootType(field.type());
/*if (param.getType() instanceof soot.NullType){
paramTypes.add(soot.RefType.v("java.lang.Object"));
retType = soot.RefType.v("java.lang.Object");
}
else {
paramTypes.add(param.getType());
retType = param.getType();
}*/
soot.SootMethod meth = new soot.SootMethod(name, paramTypes, retType, soot.Modifier.STATIC);
PrivateFieldSetMethodSource pfsms = new PrivateFieldSetMethodSource(
Util.getSootType(field.type()),
field.name(),
field.flags().isStatic()
);
conClass.addMethod(meth);
meth.setActiveBody(pfsms.getBody(meth, null));
InitialResolver.v().addToPrivateFieldSetAccessMap(field, meth);
meth.addTag(new soot.tagkit.SyntheticTag());
return meth;
}
private soot.SootMethod addGetFieldAccessMeth(soot.SootClass conClass, polyglot.ast.Field field){
if ((InitialResolver.v().getPrivateFieldGetAccessMap() != null) && (InitialResolver.v().getPrivateFieldGetAccessMap().containsKey(new polyglot.util.IdentityKey(field.fieldInstance())))){
return InitialResolver.v().getPrivateFieldGetAccessMap().get(new polyglot.util.IdentityKey(field.fieldInstance()));
}
String name = "access$"+soot.javaToJimple.InitialResolver.v().getNextPrivateAccessCounter()+"00";
ArrayList paramTypes = new ArrayList();
if (!field.flags().isStatic()){
// add this param type
paramTypes.add(conClass.getType());//(soot.Local)getBaseLocal(field.target()));
//paramTypes.add(Util.getSootType(field.target().type()));
}
soot.SootMethod meth = new soot.SootMethod(name, paramTypes, Util.getSootType(field.type()), soot.Modifier.STATIC);
PrivateFieldAccMethodSource pfams = new PrivateFieldAccMethodSource(
Util.getSootType(field.type()),
field.name(),
field.flags().isStatic(),
conClass
);
conClass.addMethod(meth);
meth.setActiveBody(pfams.getBody(meth, null));
InitialResolver.v().addToPrivateFieldGetAccessMap(field, meth);
meth.addTag(new soot.tagkit.SyntheticTag());
return meth;
}
private soot.SootMethod addGetMethodAccessMeth(soot.SootClass conClass, polyglot.ast.Call call){
if ((InitialResolver.v().getPrivateMethodGetAccessMap() != null) && (InitialResolver.v().getPrivateMethodGetAccessMap().containsKey(new polyglot.util.IdentityKey(call.methodInstance())))){
return InitialResolver.v().getPrivateMethodGetAccessMap().get(new polyglot.util.IdentityKey(call.methodInstance()));
}
String name = "access$"+soot.javaToJimple.InitialResolver.v().getNextPrivateAccessCounter()+"00";
ArrayList paramTypes = new ArrayList();
if (!call.methodInstance().flags().isStatic()){
// add this param type
//paramTypes.add(Util.getSootType(call.methodInstance().container()));
paramTypes.add(conClass.getType());
}
ArrayList sootParamsTypes = getSootParamsTypes(call);
paramTypes.addAll(sootParamsTypes);
soot.SootMethod meth = new soot.SootMethod(name, paramTypes, Util.getSootType(call.methodInstance().returnType()), soot.Modifier.STATIC);
PrivateMethodAccMethodSource pmams = new PrivateMethodAccMethodSource(
call.methodInstance()
);
conClass.addMethod(meth);
meth.setActiveBody(pmams.getBody(meth, null));
InitialResolver.v().addToPrivateMethodGetAccessMap(call, meth);
meth.addTag(new soot.tagkit.SyntheticTag());
return meth;
}
protected soot.Value getAssignRightLocal(polyglot.ast.Assign assign, soot.Local leftLocal){
if (assign.operator() == polyglot.ast.Assign.ASSIGN){
return base().getSimpleAssignRightLocal(assign);
}
else if (assign.operator() == polyglot.ast.Assign.ADD_ASSIGN && assign.type().toString().equals("java.lang.String")){
return getStringConcatAssignRightLocal(assign);
}
else {
return getComplexAssignRightLocal(assign, leftLocal);
}
}
protected soot.Value getSimpleAssignRightLocal(polyglot.ast.Assign assign){
boolean repush = false;
soot.jimple.Stmt tNoop = null;
soot.jimple.Stmt fNoop = null;
if (!trueNoop.empty() && !falseNoop.empty()){
tNoop = trueNoop.pop();
fNoop = falseNoop.pop();
repush = true;
}
soot.Value right = base().createAggressiveExpr(assign.right(), false, false);
if (repush){
trueNoop.push(tNoop);
falseNoop.push(fNoop);
}
if (right instanceof soot.jimple.ConditionExpr) {
right = handleCondBinExpr((soot.jimple.ConditionExpr)right);
}
return right;
}
private soot.Local getStringConcatAssignRightLocal(polyglot.ast.Assign assign){
soot.Local sb = (soot.Local)createStringBuffer(assign);
sb = generateAppends(assign.left(), sb);
sb = generateAppends(assign.right(), sb);
soot.Local rLocal = createToString(sb, assign);
return rLocal;
}
private soot.Local getComplexAssignRightLocal(polyglot.ast.Assign assign, soot.Local leftLocal){
soot.Value right = base().createAggressiveExpr(assign.right(), false, false);
if (right instanceof soot.jimple.ConditionExpr) {
right = handleCondBinExpr((soot.jimple.ConditionExpr)right);
}
soot.jimple.BinopExpr binop = null;
if (assign.operator() == polyglot.ast.Assign.ADD_ASSIGN) {
binop = soot.jimple.Jimple.v().newAddExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.SUB_ASSIGN){
binop = soot.jimple.Jimple.v().newSubExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.MUL_ASSIGN) {
binop = soot.jimple.Jimple.v().newMulExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.DIV_ASSIGN) {
binop = soot.jimple.Jimple.v().newDivExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.MOD_ASSIGN) {
binop = soot.jimple.Jimple.v().newRemExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.SHL_ASSIGN) {
binop = soot.jimple.Jimple.v().newShlExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.SHR_ASSIGN) {
binop = soot.jimple.Jimple.v().newShrExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.USHR_ASSIGN) {
binop = soot.jimple.Jimple.v().newUshrExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.BIT_AND_ASSIGN) {
binop = soot.jimple.Jimple.v().newAndExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.BIT_OR_ASSIGN) {
binop = soot.jimple.Jimple.v().newOrExpr(leftLocal, right);
}
else if (assign.operator() == polyglot.ast.Assign.BIT_XOR_ASSIGN) {
binop = soot.jimple.Jimple.v().newXorExpr(leftLocal, right);
}
soot.Local retLocal = lg.generateLocal(leftLocal.getType());
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, binop);
body.getUnits().add(assignStmt);
Util.addLnPosTags(binop.getOp1Box(), assign.left().position());
Util.addLnPosTags(binop.getOp2Box(), assign.right().position());
return retLocal;
}
private soot.Value getSimpleAssignLocal(polyglot.ast.Assign assign){
soot.jimple.AssignStmt stmt;
soot.Value left = base().createLHS(assign.left());
soot.Value right = base().getSimpleAssignRightLocal(assign);
stmt = soot.jimple.Jimple.v().newAssignStmt(left, right);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, assign.position());
Util.addLnPosTags(stmt.getRightOpBox(), assign.right().position());
Util.addLnPosTags(stmt.getLeftOpBox(), assign.left().position());
if (left instanceof soot.Local){
return left;
}
else {
return right;
}
}
private soot.Value getStrConAssignLocal(polyglot.ast.Assign assign){
soot.jimple.AssignStmt stmt;
soot.Value left = base().createLHS(assign.left());
soot.Value right = getStringConcatAssignRightLocal(assign);
stmt = soot.jimple.Jimple.v().newAssignStmt(left, right);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, assign.position());
Util.addLnPosTags(stmt.getRightOpBox(), assign.right().position());
Util.addLnPosTags(stmt.getLeftOpBox(), assign.left().position());
if (left instanceof soot.Local){
return left;
}
else {
return right;
}
}
/**
* Assign Expression Creation
*/
protected soot.Value getAssignLocal(polyglot.ast.Assign assign) {
// handle private access field assigns
//HashMap accessMap = ((PolyglotMethodSource)body.getMethod().getSource()).getPrivateAccessMap();
// if assigning to a field and the field is private and its not in
// this class (then it had better be in some outer class and will
// be handled as such)
if (base().needsAccessor(assign.left())){
//if ((assign.left() instanceof polyglot.ast.Field) && (needsPrivateAccessor((polyglot.ast.Field)assign.left()) || needsProtectedAccessor((polyglot.ast.Field)assign.left()))){
//((polyglot.ast.Field)assign.left()).fieldInstance().flags().isPrivate() && !Util.getSootType(((polyglot.ast.Field)assign.left()).fieldInstance().container()).equals(body.getMethod().getDeclaringClass().getType())){
return base().handlePrivateFieldAssignSet(assign);
}
if (assign.operator() == polyglot.ast.Assign.ASSIGN){
return getSimpleAssignLocal(assign);
}
if ((assign.operator() == polyglot.ast.Assign.ADD_ASSIGN) && assign.type().toString().equals("java.lang.String")){
return getStrConAssignLocal(assign);
}
soot.jimple.AssignStmt stmt;
soot.Value left = base().createLHS(assign.left());
soot.Value left2 = (soot.Value)left.clone();
soot.Local leftLocal;
if (left instanceof soot.Local){
leftLocal = (soot.Local)left;
}
else {
leftLocal = lg.generateLocal(left.getType());
soot.jimple.AssignStmt stmt1 = soot.jimple.Jimple.v().newAssignStmt(leftLocal, left);
body.getUnits().add(stmt1);
Util.addLnPosTags(stmt1, assign.position());
}
soot.Value right = base().getAssignRightLocal(assign, leftLocal);
soot.jimple.AssignStmt stmt2 = soot.jimple.Jimple.v().newAssignStmt(leftLocal, right);
body.getUnits().add(stmt2);
Util.addLnPosTags(stmt2, assign.position());
Util.addLnPosTags(stmt2.getRightOpBox(), assign.right().position());
Util.addLnPosTags(stmt2.getLeftOpBox(), assign.left().position());
if (!(left instanceof soot.Local)) {
soot.jimple.AssignStmt stmt3 = soot.jimple.Jimple.v().newAssignStmt(left2, leftLocal);
body.getUnits().add(stmt3);
Util.addLnPosTags(stmt3, assign.position());
Util.addLnPosTags(stmt3.getRightOpBox(), assign.right().position());
Util.addLnPosTags(stmt3.getLeftOpBox(), assign.left().position());
}
return leftLocal;
}
/**
* Field Expression Creation - LHS
*/
private soot.Value getFieldLocalLeft(polyglot.ast.Field field){
polyglot.ast.Receiver receiver = field.target();
if ((field.name().equals("length")) && (receiver.type() instanceof polyglot.types.ArrayType)){
return getSpecialArrayLengthLocal(field);
}
else {
return getFieldRef(field);
}
}
/**
* Field Expression Creation
*/
private soot.Value getFieldLocal(polyglot.ast.Field field){
polyglot.ast.Receiver receiver = field.target();
soot.javaToJimple.PolyglotMethodSource ms = (soot.javaToJimple.PolyglotMethodSource)body.getMethod().getSource();
if ((field.name().equals("length")) && (receiver.type() instanceof polyglot.types.ArrayType)){
return getSpecialArrayLengthLocal(field);
}
else if (field.name().equals("class")){
throw new RuntimeException("Should go through ClassLit");
}
else if (base().needsAccessor(field)){
//else if (needsPrivateAccessor(field) || needsProtectedAccessor(field)){
//((field.fieldInstance().flags().isPrivate() && !Util.getSootType(field.fieldInstance().container()).equals(body.getMethod().getDeclaringClass().getType())) ||()){
soot.Value base = base().getBaseLocal(field.target());
return getPrivateAccessFieldLocal(field, base);
}
if ((field.target() instanceof polyglot.ast.Special) && (((polyglot.ast.Special)field.target()).kind() == polyglot.ast.Special.SUPER) && (((polyglot.ast.Special)field.target()).qualifier() != null)){
return getSpecialSuperQualifierLocal(field);
}
else if (shouldReturnConstant(field)){
return getReturnConstant(field);
// in this case don't return fieldRef but a string constant
}
else {
soot.jimple.FieldRef fieldRef = getFieldRef(field);
soot.Local baseLocal = generateLocal(field.type());
soot.jimple.AssignStmt fieldAssignStmt = soot.jimple.Jimple.v().newAssignStmt(baseLocal, fieldRef);
body.getUnits().add(fieldAssignStmt);
Util.addLnPosTags(fieldAssignStmt, field.position());
Util.addLnPosTags(fieldAssignStmt.getRightOpBox(), field.position());
return baseLocal;
}
}
protected boolean needsAccessor(polyglot.ast.Expr expr){
if (!(expr instanceof polyglot.ast.Field) && !(expr instanceof polyglot.ast.Call)) return false;
else {
if (expr instanceof polyglot.ast.Field){
return needsAccessor(((polyglot.ast.Field)expr).fieldInstance());
}
else {
return needsAccessor(((polyglot.ast.Call)expr).methodInstance());
}
}
}
/**
* needs accessors:
* when field or meth is private and in some other class
* when field or meth is protected and in
*/
protected boolean needsAccessor(polyglot.types.MemberInstance inst){
if (inst.flags().isPrivate()){
if (!Util.getSootType(inst.container()).equals(body.getMethod().getDeclaringClass().getType())){
return true;
}
}
else if (inst.flags().isProtected()){
if (Util.getSootType(inst.container()).equals(body.getMethod().getDeclaringClass().getType())){
return false;
}
soot.SootClass currentClass = body.getMethod().getDeclaringClass();
if (currentClass.getSuperclass().getType().equals(Util.getSootType(inst.container()))){
return false;
}
while (currentClass.hasOuterClass()){
currentClass = currentClass.getOuterClass();
if (Util.getSootType(inst.container()).equals(currentClass.getType())){
return false;
}
else if (Util.getSootType(inst.container()).equals(currentClass.getSuperclass().getType())){
return true;
}
}
return false;
}
return false;
}
/**
* needs a private access method if field is private and in
* some other class
*/
/*protected boolean needsPrivateAccessor(polyglot.ast.Field field){
if (field.fieldInstance().flags().isPrivate()){
if (!Util.getSootType(field.fieldInstance().container()).equals(body.getMethod().getDeclaringClass().getType())){
return true;
}
}
return false;
}*/
/**
* needs a protected access method if field is protected and in
* a super class of the outer class of the innerclass trying to access
* the field (ie not in self or in outer of self)
*/
/*protected boolean needsProtectedAccessor(polyglot.ast.Field field){
//return false;
if (field.fieldInstance().flags().isProtected()){
if (Util.getSootType(field.fieldInstance().container()).equals(body.getMethod().getDeclaringClass().getType())){
return false;
}
soot.SootClass currentClass = body.getMethod().getDeclaringClass();
while (currentClass.hasOuterClass()){
currentClass = currentClass.getOuterClass();
if (Util.getSootType(field.fieldInstance().container()).equals(currentClass.getType())){
return false;
}
else if (Util.getSootType(field.fieldInstance().container()).equals(currentClass.getSuperclass().getType())){
return true;
}
}
return false;
}
return false;
/*
if (field.fieldInstance().flags().isProtected()){
if (!Util.getSootType(field.fieldInstance().container()).equals(body.getMethod().getDeclaringClass().getType())){
soot.SootClass checkClass = body.getMethod().getDeclaringClass();
while (checkClass.hasOuterClass()){
checkClass = checkClass.getOuterClass();
if (Util.getSootType(field.fieldInstance().container()).equals(checkClass.getType())){
return false;
}
}
return true;
}
}
return false;*/
//}
private soot.jimple.Constant getReturnConstant(polyglot.ast.Field field){
return getConstant(field.constantValue(), field.type());
}
private soot.jimple.Constant getConstant(Object constVal, polyglot.types.Type type){
//System.out.println("getConstant: "+constVal);
if (constVal instanceof String){
return soot.jimple.StringConstant.v((String)constVal);
}
else if (constVal instanceof Boolean){
boolean val = ((Boolean)constVal).booleanValue();
return soot.jimple.IntConstant.v(val ? 1 : 0);
}
else if (type.isChar()){
char val;
if (constVal instanceof Integer){
val = (char)((Integer)constVal).intValue();
}
else {
val = ((Character)constVal).charValue();
}
//System.out.println("val: "+val);
return soot.jimple.IntConstant.v(val);
}
else {
Number num = (Number)constVal;
//System.out.println("num: "+num);
num = createConstantCast(type, num);
//System.out.println("num: "+num);
if (num instanceof Long) {
//System.out.println(((Long)num).longValue());
return soot.jimple.LongConstant.v(((Long)num).longValue());
}
else if (num instanceof Double) {
return soot.jimple.DoubleConstant.v(((Double)num).doubleValue());
}
else if (num instanceof Float) {
return soot.jimple.FloatConstant.v(((Float)num).floatValue());
}
else if (num instanceof Byte) {
return soot.jimple.IntConstant.v(((Byte)num).byteValue());
}
else if (num instanceof Short) {
return soot.jimple.IntConstant.v(((Short)num).shortValue());
}
else {
return soot.jimple.IntConstant.v(((Integer)num).intValue());
}
}
}
private Number createConstantCast(polyglot.types.Type fieldType, Number constant) {
if (constant instanceof Integer){
if (fieldType.isDouble()){
return new Double((double)((Integer)constant).intValue());
}
else if (fieldType.isFloat()){
return new Float((float)((Integer)constant).intValue());
}
else if (fieldType.isLong()){
return new Long((long)((Integer)constant).intValue());
}
}
return constant;
}
private boolean shouldReturnConstant(polyglot.ast.Field field){
if (field.isConstant() && field.constantValue() != null) {
return true;
}
return false;
}
/**
* creates a field ref
*/
protected soot.jimple.FieldRef getFieldRef(polyglot.ast.Field field) {
soot.SootClass receiverClass = ((soot.RefType)Util.getSootType(field.target().type())).getSootClass();
soot.SootFieldRef receiverField = soot.Scene.v().makeFieldRef(receiverClass, field.name(), Util.getSootType(field.type()), field.flags().isStatic());
soot.jimple.FieldRef fieldRef;
if (field.fieldInstance().flags().isStatic()) {
fieldRef = soot.jimple.Jimple.v().newStaticFieldRef(receiverField);
}
else {
soot.Local base;
base = (soot.Local)base().getBaseLocal(field.target());
fieldRef = soot.jimple.Jimple.v().newInstanceFieldRef(base, receiverField);
}
if (field.target() instanceof polyglot.ast.Local && fieldRef instanceof soot.jimple.InstanceFieldRef){
Util.addLnPosTags(((soot.jimple.InstanceFieldRef)fieldRef).getBaseBox(), field.target().position());
}
return fieldRef;
}
/**
* For Inner Classes - to access private fields of their outer class
*/
private soot.Local getPrivateAccessFieldLocal(polyglot.ast.Field field, soot.Value base) {
// need to add access method
// if private add to the containing class
// but if its protected then add to outer class - not containing
// class because in this case the containing class is the super class
soot.SootMethod toInvoke;
soot.SootClass invokeClass;
if (field.fieldInstance().flags().isPrivate()){
toInvoke = addGetFieldAccessMeth(((soot.RefType)Util.getSootType(field.fieldInstance().container())).getSootClass(), field);
invokeClass = ((soot.RefType)Util.getSootType(field.fieldInstance().container())).getSootClass();
}
else {
if (InitialResolver.v().hierarchy() == null){
InitialResolver.v().hierarchy(new soot.FastHierarchy());
}
soot.SootClass containingClass = ((soot.RefType)Util.getSootType(field.fieldInstance().container())).getSootClass();
soot.SootClass addToClass;
if (body.getMethod().getDeclaringClass().hasOuterClass()){
addToClass = body.getMethod().getDeclaringClass().getOuterClass();
while (!InitialResolver.v().hierarchy().canStoreType(containingClass.getType(), addToClass.getType())){
if (addToClass.hasOuterClass()){
addToClass = addToClass.getOuterClass();
}
else {
break;
}
}
}
else{
addToClass = containingClass;
}
invokeClass = addToClass;
toInvoke = addGetFieldAccessMeth(addToClass, field);
}
ArrayList params = new ArrayList();
if (!field.fieldInstance().flags().isStatic()) {
params.add(base);
/*if (field.target() instanceof polyglot.ast.Expr){
params.add((soot.Local)base().getBaseLocal(field.target()));
}
else if (body.getMethod().getDeclaringClass().declaresFieldByName("this$0")){
params.add(getThis(invokeClass.getType()));
}
else {
soot.Local local = (soot.Local)base().getBaseLocal(field.target());
params.add(local);
}*/
//(soot.Local)getBaseLocal(field.target()));
/*if (Util.getSootType(field.target().type()).equals(invokeClass.getType())){
*/
//params.add(getThis(invokeClass.getType()));//(soot.Local)getBaseLocal(field.target()));
//}
/*else {*/
//soot.Local local = (soot.Local)getBaseLocal(field.target());
//params.add(getThis(invokeClass.getType()));//(soot.Local)getBaseLocal(field.target()));
//soot.Local local = (soot.Local)getBaseLocal(field.target());
//params.add(local);
//}
}
return Util.getPrivateAccessFieldInvoke(toInvoke.makeRef(), params, body, lg);
}
/**
* To get the local for the special .class literal
*/
private soot.Local getSpecialClassLitLocal(polyglot.ast.ClassLit lit) {
if (lit.typeNode().type().isPrimitive()){
polyglot.types.PrimitiveType primType = (polyglot.types.PrimitiveType)lit.typeNode().type();
soot.Local retLocal = lg.generateLocal(soot.RefType.v("java.lang.Class"));
soot.SootFieldRef primField = null;
if (primType.isBoolean()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Boolean"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isByte()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Byte"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isChar()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Character"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isDouble()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Double"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isFloat()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Float"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isInt()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Integer"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isLong()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Long"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isShort()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Short"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
else if (primType.isVoid()){
primField = soot.Scene.v().makeFieldRef(soot.Scene.v().getSootClass("java.lang.Void"), "TYPE", soot.RefType.v("java.lang.Class"), true);
}
soot.jimple.StaticFieldRef fieldRef = soot.jimple.Jimple.v().newStaticFieldRef(primField);
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, fieldRef);
body.getUnits().add(assignStmt);
return retLocal;
}
else {
// this class
soot.SootClass thisClass = body.getMethod().getDeclaringClass();
String fieldName = Util.getFieldNameForClassLit(lit.typeNode().type());
soot.Type fieldType = soot.RefType.v("java.lang.Class");
soot.Local fieldLocal = lg.generateLocal(soot.RefType.v("java.lang.Class"));
soot.SootFieldRef sootField = null;
if (thisClass.isInterface()){
HashMap<SootClass, SootClass> specialAnonMap = InitialResolver.v().specialAnonMap();
if ((specialAnonMap != null) && (specialAnonMap.containsKey(thisClass))){
soot.SootClass specialClass = specialAnonMap.get(thisClass);
sootField = soot.Scene.v().makeFieldRef(specialClass, fieldName, fieldType, true);
}
else {
throw new RuntimeException("Class is interface so it must have an anon class to handle class lits but its anon class cannot be found.");
}
}
else {
sootField = soot.Scene.v().makeFieldRef(thisClass, fieldName, fieldType, true);
}
soot.jimple.StaticFieldRef fieldRef = soot.jimple.Jimple.v().newStaticFieldRef(sootField);
soot.jimple.Stmt fieldAssign = soot.jimple.Jimple.v().newAssignStmt(fieldLocal, fieldRef);
body.getUnits().add(fieldAssign);
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Expr neExpr = soot.jimple.Jimple.v().newNeExpr(fieldLocal, soot.jimple.NullConstant.v());
soot.jimple.Stmt ifStmt = soot.jimple.Jimple.v().newIfStmt(neExpr, noop1);
body.getUnits().add(ifStmt);
ArrayList paramTypes = new ArrayList();
paramTypes.add(soot.RefType.v("java.lang.String"));
soot.SootMethodRef invokeMeth = null;
if (thisClass.isInterface()){
HashMap<SootClass, SootClass> specialAnonMap = InitialResolver.v().specialAnonMap();
if ((specialAnonMap != null) && (specialAnonMap.containsKey(thisClass))){
soot.SootClass specialClass = specialAnonMap.get(thisClass);
invokeMeth = soot.Scene.v().makeMethodRef(specialClass, "class$", paramTypes, soot.RefType.v("java.lang.Class"), true);
}
else {
throw new RuntimeException("Class is interface so it must have an anon class to handle class lits but its anon class cannot be found.");
}
}
else {
invokeMeth = soot.Scene.v().makeMethodRef(thisClass, "class$", paramTypes, soot.RefType.v("java.lang.Class"), true);
}
ArrayList params = new ArrayList();
params.add(soot.jimple.StringConstant.v(Util.getParamNameForClassLit(lit.typeNode().type())));
soot.jimple.Expr classInvoke = soot.jimple.Jimple.v().newStaticInvokeExpr(invokeMeth, params);
soot.Local methLocal = lg.generateLocal(soot.RefType.v("java.lang.Class"));
soot.jimple.Stmt invokeAssign = soot.jimple.Jimple.v().newAssignStmt(methLocal, classInvoke);
body.getUnits().add(invokeAssign);
soot.jimple.Stmt assignField = soot.jimple.Jimple.v().newAssignStmt(fieldRef, methLocal);
body.getUnits().add(assignField);
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
body.getUnits().add(noop1);
fieldAssign = soot.jimple.Jimple.v().newAssignStmt(methLocal, fieldRef);
body.getUnits().add(fieldAssign);
body.getUnits().add(noop2);
return methLocal;
}
}
/**
* Array Length local for example a.length w/o brackets gets length
* of array
*/
private soot.Local getSpecialArrayLengthLocal(polyglot.ast.Field field) {
soot.Local localField;
polyglot.ast.Receiver receiver = field.target();
if (receiver instanceof polyglot.ast.Local) {
localField = getLocal((polyglot.ast.Local)receiver);
}
else if (receiver instanceof polyglot.ast.Expr){
localField = (soot.Local)base().createAggressiveExpr((polyglot.ast.Expr)receiver, false, false);
}
else {
localField = generateLocal(receiver.type());
}
soot.jimple.LengthExpr lengthExpr = soot.jimple.Jimple.v().newLengthExpr(localField);
soot.Local retLocal = lg.generateLocal(soot.IntType.v());
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(retLocal, lengthExpr);
body.getUnits().add(assign);
Util.addLnPosTags(assign, field.position());
Util.addLnPosTags(lengthExpr.getOpBox(), field.target().position());
return retLocal;
}
/**
* Binary Expression Creation
*/
private soot.Value getBinaryLocal2(polyglot.ast.Binary binary, boolean reduceAggressively) {
//System.out.println("binary: "+binary+" class: "+binary.getClass());
soot.Value rhs;
if (binary.operator() == polyglot.ast.Binary.COND_AND) {
return createCondAnd(binary);
}
if (binary.operator() == polyglot.ast.Binary.COND_OR) {
return createCondOr(binary);
}
if (binary.type().toString().equals("java.lang.String")){
//System.out.println("binary: "+binary);
if (areAllStringLits(binary)){
String result = createStringConstant(binary);
//System.out.println("created string constant: "+result);
return soot.jimple.StringConstant.v(result);
}
else {
soot.Local sb = (soot.Local)createStringBuffer(binary);
sb = generateAppends(binary.left(), sb);
sb = generateAppends(binary.right(), sb);
return createToString(sb, binary);
}
}
//System.out.println("bin exp left: "+binary.left());
//System.out.println("bin exp right: "+binary.right());
soot.Value lVal = base().createAggressiveExpr(binary.left(), true, false);
soot.Value rVal = base().createAggressiveExpr(binary.right(), true, false);
if (isComparisonBinary(binary.operator())) {
//System.out.println("bin exp: "+binary);
rhs = getBinaryComparisonExpr(lVal, rVal, binary.operator());
}
else {
rhs = getBinaryExpr(lVal, rVal, binary.operator());
}
if (rhs instanceof soot.jimple.BinopExpr) {
Util.addLnPosTags(((soot.jimple.BinopExpr)rhs).getOp1Box(), binary.left().position());
Util.addLnPosTags(((soot.jimple.BinopExpr)rhs).getOp2Box(), binary.right().position());
}
if (rhs instanceof soot.jimple.ConditionExpr && !reduceAggressively) {
return rhs;
}
else if (rhs instanceof soot.jimple.ConditionExpr){
rhs = handleCondBinExpr((soot.jimple.ConditionExpr)rhs, true);
}
soot.Local lhs = generateLocal(binary.type());
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(lhs, rhs);
body.getUnits().add(assignStmt);
//System.out.println("binary pos: "+binary.position());
Util.addLnPosTags(assignStmt.getRightOpBox(), binary.position());
Util.addLnPosTags(assignStmt, binary.position());
return lhs;
}
private boolean areAllStringLits(polyglot.ast.Node node){
// System.out.println("node in is string lit: "+node+" kind: "+node.getClass());
if (node instanceof polyglot.ast.StringLit) return true;
else if ( node instanceof polyglot.ast.Field) {
if (shouldReturnConstant((polyglot.ast.Field)node)) return true;
else return false;
}
else if (node instanceof polyglot.ast.Binary){
if (areAllStringLitsBinary((polyglot.ast.Binary)node)) return true;
return false;
}
else if (node instanceof polyglot.ast.Unary){
polyglot.ast.Unary unary = (polyglot.ast.Unary)node;
if (unary.isConstant()){
return true;
}
return false;
}
else if (node instanceof polyglot.ast.Cast){
polyglot.ast.Cast cast = (polyglot.ast.Cast)node;
if (cast.isConstant()){
return true;
}
return false;
}
else if (node instanceof polyglot.ast.Lit){
polyglot.ast.Lit lit = (polyglot.ast.Lit)node;
//System.out.println("lit: "+lit+" is constant: "+(lit.isConstant()?true:false));
if (lit.isConstant()){
return true;
}
return false;
}
return false;
}
private boolean areAllStringLitsBinary(polyglot.ast.Binary binary){
if (areAllStringLits(binary.left()) && areAllStringLits(binary.right())) return true;
else return false;
}
private String createStringConstant(polyglot.ast.Node node){
//System.out.println("creatinf string constant: "+createConstant((polyglot.ast.Expr)node));
String s = null;
if (node instanceof polyglot.ast.StringLit){
s = ((polyglot.ast.StringLit)node).value();
}
else if (node instanceof polyglot.ast.Cast){
polyglot.ast.Cast cast = (polyglot.ast.Cast)node;
if (cast.type().isChar()){
s = "" + (char)((Character)cast.constantValue()).charValue();
}
else {
s = "" + cast.constantValue();
}
}
else if (node instanceof polyglot.ast.Unary){
polyglot.ast.Unary unary = (polyglot.ast.Unary)node;
s = "" + unary.constantValue();
}
else if (node instanceof polyglot.ast.CharLit){
s = "" + ((polyglot.ast.CharLit)node).value();
}
else if (node instanceof polyglot.ast.BooleanLit){
s = "" + ((polyglot.ast.BooleanLit)node).value();
}
else if (node instanceof polyglot.ast.IntLit){
s = "" + ((polyglot.ast.IntLit)node).value();
}
else if (node instanceof polyglot.ast.FloatLit){
s = "" + ((polyglot.ast.FloatLit)node).value();
}
else if (node instanceof polyglot.ast.NullLit){
s = "null";
}
else if (node instanceof polyglot.ast.Field){
polyglot.ast.Field field = (polyglot.ast.Field)node;
if (field.fieldInstance().constantValue() instanceof String){
s = (String)field.constantValue();
}
else if (field.fieldInstance().constantValue() instanceof Boolean){
boolean val = ((Boolean)field.constantValue()).booleanValue();
int temp = val ? 1 : 0;
s = "" + temp;
}
else if (field.type().isChar()){
char val = (char)((Integer)field.constantValue()).intValue();
s = "" + val;
}
else {
Number num = (Number)field.fieldInstance().constantValue();
num = createConstantCast(field.type(), num);
if (num instanceof Long) {
s = "" + ((Long)num).longValue();
}
else if (num instanceof Double) {
s = "" + ((Double)num).doubleValue();
}
else if (num instanceof Float) {
s = "" + ((Float)num).floatValue();
}
else if (num instanceof Byte) {
s = "" + ((Byte)num).byteValue();
}
else if (num instanceof Short) {
s = "" + ((Short)num).shortValue();
}
else {
s = "" + ((Integer)num).intValue();
}
}
}
else if (node instanceof polyglot.ast.Binary){
s = createStringConstantBinary((polyglot.ast.Binary)node);
}
else {
throw new RuntimeException("No other string constant folding done");
}
return s;
}
private String createStringConstantBinary(polyglot.ast.Binary binary){
//System.out.println("create string binary: type"+binary.type());
String s = null;
if (Util.getSootType(binary.type()).toString().equals("java.lang.String")){
// here if type is a string return string constant
s = createStringConstant(binary.left()) + createStringConstant(binary.right());
}
else {
// else eval and return string of the eval result
s = binary.constantValue().toString();
}
return s;
}
private boolean isComparisonBinary(polyglot.ast.Binary.Operator op) {
if ((op == polyglot.ast.Binary.EQ) || (op == polyglot.ast.Binary.NE) ||
(op == polyglot.ast.Binary.GE) || (op == polyglot.ast.Binary.GT) ||
(op == polyglot.ast.Binary.LE) || (op == polyglot.ast.Binary.LT)) {
return true;
}
else {
return false;
}
}
/**
* Creates a binary expression that is not a comparison
*/
private soot.Value getBinaryExpr(soot.Value lVal, soot.Value rVal, polyglot.ast.Binary.Operator operator){
soot.Value rValue = null;
if (lVal instanceof soot.jimple.ConditionExpr) {
lVal = handleCondBinExpr((soot.jimple.ConditionExpr)lVal);
}
if (rVal instanceof soot.jimple.ConditionExpr) {
rVal = handleCondBinExpr((soot.jimple.ConditionExpr)rVal);
}
if (operator == polyglot.ast.Binary.ADD){
rValue = soot.jimple.Jimple.v().newAddExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.SUB){
rValue = soot.jimple.Jimple.v().newSubExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.MUL){
rValue = soot.jimple.Jimple.v().newMulExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.DIV){
rValue = soot.jimple.Jimple.v().newDivExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.SHR){
if (rVal.getType().equals(soot.LongType.v())){
soot.Local intVal = lg.generateLocal(soot.IntType.v());
soot.jimple.CastExpr castExpr = soot.jimple.Jimple.v().newCastExpr(rVal, soot.IntType.v());
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(intVal, castExpr);
body.getUnits().add(assignStmt);
rValue = soot.jimple.Jimple.v().newShrExpr(lVal, intVal);
}
else {
rValue = soot.jimple.Jimple.v().newShrExpr(lVal, rVal);
}
}
else if (operator == polyglot.ast.Binary.USHR){
if (rVal.getType().equals(soot.LongType.v())){
soot.Local intVal = lg.generateLocal(soot.IntType.v());
soot.jimple.CastExpr castExpr = soot.jimple.Jimple.v().newCastExpr(rVal, soot.IntType.v());
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(intVal, castExpr);
body.getUnits().add(assignStmt);
rValue = soot.jimple.Jimple.v().newUshrExpr(lVal, intVal);
}
else {
rValue = soot.jimple.Jimple.v().newUshrExpr(lVal, rVal);
}
}
else if (operator == polyglot.ast.Binary.SHL){
if (rVal.getType().equals(soot.LongType.v())){
soot.Local intVal = lg.generateLocal(soot.IntType.v());
soot.jimple.CastExpr castExpr = soot.jimple.Jimple.v().newCastExpr(rVal, soot.IntType.v());
soot.jimple.AssignStmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(intVal, castExpr);
body.getUnits().add(assignStmt);
rValue = soot.jimple.Jimple.v().newShlExpr(lVal, intVal);
}
else {
rValue = soot.jimple.Jimple.v().newShlExpr(lVal, rVal);
}
}
else if (operator == polyglot.ast.Binary.BIT_AND){
rValue = soot.jimple.Jimple.v().newAndExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.BIT_OR){
rValue = soot.jimple.Jimple.v().newOrExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.BIT_XOR){
rValue = soot.jimple.Jimple.v().newXorExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.MOD){
rValue = soot.jimple.Jimple.v().newRemExpr(lVal, rVal);
}
else {
throw new RuntimeException("Binary not yet handled!");
}
return rValue;
}
/**
* Creates a binary expr that is a comparison
*/
private soot.Value getBinaryComparisonExpr(soot.Value lVal, soot.Value rVal, polyglot.ast.Binary.Operator operator) {
soot.Value rValue;
if (operator == polyglot.ast.Binary.EQ){
//System.out.println("processing: "+body.getMethod().getDeclaringClass());
//System.out.println("lval: "+lVal+" rval: "+rVal);
rValue = soot.jimple.Jimple.v().newEqExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.GE){
rValue = soot.jimple.Jimple.v().newGeExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.GT){
rValue = soot.jimple.Jimple.v().newGtExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.LE){
rValue = soot.jimple.Jimple.v().newLeExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.LT){
rValue = soot.jimple.Jimple.v().newLtExpr(lVal, rVal);
}
else if (operator == polyglot.ast.Binary.NE){
rValue = soot.jimple.Jimple.v().newNeExpr(lVal, rVal);
}
else {
throw new RuntimeException("Unknown Comparison Expr");
}
return rValue;
}
/**
* in bytecode and Jimple the conditions in conditional binary
* expressions are often reversed
*/
private soot.Value reverseCondition(soot.jimple.ConditionExpr cond) {
soot.jimple.ConditionExpr newExpr;
if (cond instanceof soot.jimple.EqExpr) {
newExpr = soot.jimple.Jimple.v().newNeExpr(cond.getOp1(), cond.getOp2());
}
else if (cond instanceof soot.jimple.NeExpr) {
newExpr = soot.jimple.Jimple.v().newEqExpr(cond.getOp1(), cond.getOp2());
}
else if (cond instanceof soot.jimple.GtExpr) {
newExpr = soot.jimple.Jimple.v().newLeExpr(cond.getOp1(), cond.getOp2());
}
else if (cond instanceof soot.jimple.GeExpr) {
newExpr = soot.jimple.Jimple.v().newLtExpr(cond.getOp1(), cond.getOp2());
}
else if (cond instanceof soot.jimple.LtExpr) {
newExpr = soot.jimple.Jimple.v().newGeExpr(cond.getOp1(), cond.getOp2());
}
else if (cond instanceof soot.jimple.LeExpr) {
newExpr = soot.jimple.Jimple.v().newGtExpr(cond.getOp1(), cond.getOp2());
}
else {
throw new RuntimeException("Unknown Condition Expr");
}
newExpr.getOp1Box().addAllTagsOf(cond.getOp1Box());
newExpr.getOp2Box().addAllTagsOf(cond.getOp2Box());
return newExpr;
}
/**
* Special conditions for doubles and floats and longs
*/
private soot.Value handleDFLCond(soot.jimple.ConditionExpr cond){
soot.Local result = lg.generateLocal(soot.ByteType.v());
soot.jimple.Expr cmExpr = null;
if (isDouble(cond.getOp1()) || isDouble(cond.getOp2()) || isFloat(cond.getOp1()) || isFloat(cond.getOp2())) {
// use cmpg and cmpl
if ((cond instanceof soot.jimple.GeExpr) || (cond instanceof soot.jimple.GtExpr)) {
// use cmpg
cmExpr = soot.jimple.Jimple.v().newCmpgExpr(cond.getOp1(), cond.getOp2());
}
else {
// use cmpl
cmExpr = soot.jimple.Jimple.v().newCmplExpr(cond.getOp1(), cond.getOp2());
}
}
else if (isLong(cond.getOp1()) || isLong(cond.getOp2())) {
// use cmp
cmExpr = soot.jimple.Jimple.v().newCmpExpr(cond.getOp1(), cond.getOp2());
}
else {
return cond;
}
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(result, cmExpr);
body.getUnits().add(assign);
if (cond instanceof soot.jimple.EqExpr){
cond = soot.jimple.Jimple.v().newEqExpr(result, soot.jimple.IntConstant.v(0));
}
else if (cond instanceof soot.jimple.GeExpr){
cond = soot.jimple.Jimple.v().newGeExpr(result, soot.jimple.IntConstant.v(0));
}
else if (cond instanceof soot.jimple.GtExpr){
cond = soot.jimple.Jimple.v().newGtExpr(result, soot.jimple.IntConstant.v(0));
}
else if (cond instanceof soot.jimple.LeExpr){
cond = soot.jimple.Jimple.v().newLeExpr(result, soot.jimple.IntConstant.v(0));
}
else if (cond instanceof soot.jimple.LtExpr){
cond = soot.jimple.Jimple.v().newLtExpr(result, soot.jimple.IntConstant.v(0));
}
else if (cond instanceof soot.jimple.NeExpr){
cond = soot.jimple.Jimple.v().newNeExpr(result, soot.jimple.IntConstant.v(0));
}
else {
throw new RuntimeException("Unknown Comparison Expr");
}
return cond;
}
private boolean isDouble(soot.Value val) {
if (val.getType() instanceof soot.DoubleType) return true;
return false;
}
private boolean isFloat(soot.Value val) {
if (val.getType() instanceof soot.FloatType) return true;
return false;
}
private boolean isLong(soot.Value val) {
if (val.getType() instanceof soot.LongType) return true;
return false;
}
/**
* Creates a conitional AND expr
*/
private soot.Value createCondAnd(polyglot.ast.Binary binary) {
soot.Local retLocal = lg.generateLocal(soot.BooleanType.v());
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.Value lVal = base().createAggressiveExpr(binary.left(), false, false);
boolean leftNeedIf = needSootIf(lVal);
if (!(lVal instanceof soot.jimple.ConditionExpr)) {
lVal = soot.jimple.Jimple.v().newEqExpr(lVal, soot.jimple.IntConstant.v(0));
}
else {
lVal = reverseCondition((soot.jimple.ConditionExpr)lVal);
lVal = handleDFLCond((soot.jimple.ConditionExpr)lVal);
}
if (leftNeedIf){
soot.jimple.IfStmt ifLeft;
/*if (!falseNoop.empty()){
soot.jimple.Stmt fNoop = (soot.jimple.Stmt)falseNoop.peek();
ifLeft = soot.jimple.Jimple.v().newIfStmt(lVal, fNoop);
}
else {*/
ifLeft = soot.jimple.Jimple.v().newIfStmt(lVal, noop1);
//}
body.getUnits().add(ifLeft);
Util.addLnPosTags(ifLeft.getConditionBox(), binary.left().position());
Util.addLnPosTags(ifLeft, binary.left().position());
}
soot.jimple.Stmt endNoop = soot.jimple.Jimple.v().newNopStmt();
soot.Value rVal = base().createAggressiveExpr(binary.right(), false, false);
boolean rightNeedIf = needSootIf(rVal);
if (!(rVal instanceof soot.jimple.ConditionExpr)) {
rVal = soot.jimple.Jimple.v().newEqExpr(rVal, soot.jimple.IntConstant.v(0));
}
else {
rVal = reverseCondition((soot.jimple.ConditionExpr)rVal);
rVal = handleDFLCond((soot.jimple.ConditionExpr)rVal);
}
if (rightNeedIf){
soot.jimple.IfStmt ifRight;
/*if (!falseNoop.empty()){
soot.jimple.Stmt fNoop = (soot.jimple.Stmt)falseNoop.peek();
ifRight = soot.jimple.Jimple.v().newIfStmt(rVal, fNoop);
}
else {*/
ifRight = soot.jimple.Jimple.v().newIfStmt(rVal, noop1);
//}
body.getUnits().add(ifRight);
Util.addLnPosTags(ifRight.getConditionBox(), binary.right().position());
Util.addLnPosTags(ifRight, binary.right().position());
}
// return if cond will be used in if
/*if (!falseNoop.empty()){
return soot.jimple.IntConstant.v(1);
}*/
soot.jimple.Stmt assign1 = soot.jimple.Jimple.v().newAssignStmt(retLocal, soot.jimple.IntConstant.v(1));
body.getUnits().add(assign1);
soot.jimple.Stmt gotoEnd1 = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(gotoEnd1);
body.getUnits().add(noop1);
soot.jimple.Stmt assign2 = soot.jimple.Jimple.v().newAssignStmt(retLocal, soot.jimple.IntConstant.v(0));
body.getUnits().add(assign2);
body.getUnits().add(endNoop);
Util.addLnPosTags(assign1, binary.position());
Util.addLnPosTags(assign2, binary.position());
return retLocal;
}
int inLeftOr = 0;
/**
* Creates a conditional OR expr
*/
private soot.Value createCondOr(polyglot.ast.Binary binary) {
//System.out.println("cond or binary: "+binary);
soot.Local retLocal = lg.generateLocal(soot.BooleanType.v());
//end
soot.jimple.Stmt endNoop = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
//inLeftOr++;
soot.Value lVal = base().createAggressiveExpr(binary.left(), false, false);
//inLeftOr--;
//System.out.println("leftval : "+lVal);
boolean leftNeedIf = needSootIf(lVal);
if (!(lVal instanceof soot.jimple.ConditionExpr)) {
lVal = soot.jimple.Jimple.v().newNeExpr(lVal, soot.jimple.IntConstant.v(0));
}
else {
// no reversing of condition needed for first expr in conditional
// or expression
lVal = handleDFLCond((soot.jimple.ConditionExpr)lVal);
}
if (leftNeedIf){
soot.jimple.IfStmt ifLeft;
/*if (!trueNoop.empty()){
ifLeft = soot.jimple.Jimple.v().newIfStmt(lVal, (soot.jimple.Stmt)trueNoop.peek());
}
else {*/
ifLeft = soot.jimple.Jimple.v().newIfStmt(lVal, noop1);
//}
body.getUnits().add(ifLeft);
Util.addLnPosTags(ifLeft, binary.left().position());
Util.addLnPosTags(ifLeft.getConditionBox(), binary.left().position());
}
soot.Value rVal = base().createAggressiveExpr(binary.right(), false, false);
boolean rightNeedIf = needSootIf(rVal);
if (!(rVal instanceof soot.jimple.ConditionExpr)) {
rVal = soot.jimple.Jimple.v().newEqExpr(rVal, soot.jimple.IntConstant.v(0));
}
else {
// need to reverse right part of conditional or expr
if (/*!trueNoop.empty() &&*/ inLeftOr == 0){
rVal = reverseCondition((soot.jimple.ConditionExpr)rVal);
}
rVal = handleDFLCond((soot.jimple.ConditionExpr)rVal);
}
if (rightNeedIf){
soot.jimple.IfStmt ifRight;
/*if (!trueNoop.empty()){
if (inLeftOr == 0){
ifRight = soot.jimple.Jimple.v().newIfStmt(rVal, (soot.jimple.Stmt)falseNoop.peek());
}
else {
ifRight = soot.jimple.Jimple.v().newIfStmt(rVal, (soot.jimple.Stmt)trueNoop.peek());
}
}
else {*/
ifRight = soot.jimple.Jimple.v().newIfStmt(rVal, noop2);
//}
body.getUnits().add(ifRight);
Util.addLnPosTags(ifRight, binary.right().position());
Util.addLnPosTags(ifRight.getConditionBox(), binary.right().position());
}
// return if cond will be used in if
/*if (!trueNoop.empty()){
return soot.jimple.IntConstant.v(1);
}*/
body.getUnits().add(noop1);
soot.jimple.Stmt assign2 = soot.jimple.Jimple.v().newAssignStmt(retLocal, soot.jimple.IntConstant.v(1));
body.getUnits().add(assign2);
Util.addLnPosTags(assign2, binary.position());
soot.jimple.Stmt gotoEnd2 = soot.jimple.Jimple.v().newGotoStmt(endNoop);
body.getUnits().add(gotoEnd2);
body.getUnits().add(noop2);
soot.jimple.Stmt assign3 = soot.jimple.Jimple.v().newAssignStmt(retLocal, soot.jimple.IntConstant.v(0));
body.getUnits().add(assign3);
Util.addLnPosTags(assign3, binary.position());
body.getUnits().add(endNoop);
Util.addLnPosTags(assign2, binary.position());
Util.addLnPosTags(assign3, binary.position());
return retLocal;
}
private soot.Local handleCondBinExpr(soot.jimple.ConditionExpr condExpr) {
soot.Local boolLocal = lg.generateLocal(soot.BooleanType.v());
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.Value newVal;
newVal = reverseCondition(condExpr);
newVal = handleDFLCond((soot.jimple.ConditionExpr)newVal);
soot.jimple.Stmt ifStmt = soot.jimple.Jimple.v().newIfStmt(newVal, noop1);
body.getUnits().add(ifStmt);
body.getUnits().add(soot.jimple.Jimple.v().newAssignStmt(boolLocal, soot.jimple.IntConstant.v(1)));
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
body.getUnits().add(noop1);
body.getUnits().add(soot.jimple.Jimple.v().newAssignStmt(boolLocal, soot.jimple.IntConstant.v(0)));
body.getUnits().add(noop2);
return boolLocal;
}
private soot.Local handleCondBinExpr(soot.jimple.ConditionExpr condExpr, boolean reverse) {
soot.Local boolLocal = lg.generateLocal(soot.BooleanType.v());
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.Value newVal = condExpr;
if (reverse){
newVal = reverseCondition(condExpr);
}
newVal = handleDFLCond((soot.jimple.ConditionExpr)newVal);
soot.jimple.Stmt ifStmt = soot.jimple.Jimple.v().newIfStmt(newVal, noop1);
body.getUnits().add(ifStmt);
body.getUnits().add(soot.jimple.Jimple.v().newAssignStmt(boolLocal, soot.jimple.IntConstant.v(1)));
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
body.getUnits().add(noop1);
body.getUnits().add(soot.jimple.Jimple.v().newAssignStmt(boolLocal, soot.jimple.IntConstant.v(0)));
body.getUnits().add(noop2);
return boolLocal;
}
private soot.Local createStringBuffer(polyglot.ast.Expr expr){
// create and add one string buffer
soot.Local local = lg.generateLocal(soot.RefType.v("java.lang.StringBuffer"));
soot.jimple.NewExpr newExpr = soot.jimple.Jimple.v().newNewExpr(soot.RefType.v("java.lang.StringBuffer"));
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(local, newExpr);
body.getUnits().add(assign);
Util.addLnPosTags(assign, expr.position());
soot.SootClass classToInvoke1 = soot.Scene.v().getSootClass("java.lang.StringBuffer");
soot.SootMethodRef methodToInvoke1 = soot.Scene.v().makeMethodRef(classToInvoke1, "<init>", new ArrayList(), soot.VoidType.v(), false);
soot.jimple.SpecialInvokeExpr invoke = soot.jimple.Jimple.v().newSpecialInvokeExpr(local, methodToInvoke1);
soot.jimple.Stmt invokeStmt = soot.jimple.Jimple.v().newInvokeStmt(invoke);
body.getUnits().add(invokeStmt);
Util.addLnPosTags(invokeStmt, expr.position());
return local;
}
private soot.Local createToString(soot.Local sb, polyglot.ast.Expr expr){
// invoke toString on local (type StringBuffer)
soot.Local newString = lg.generateLocal(soot.RefType.v("java.lang.String"));
soot.SootClass classToInvoke2 = soot.Scene.v().getSootClass("java.lang.StringBuffer");
soot.SootMethodRef methodToInvoke2 = soot.Scene.v().makeMethodRef(classToInvoke2, "toString", new ArrayList(), soot.RefType.v("java.lang.String"), false);
soot.jimple.VirtualInvokeExpr toStringInvoke = soot.jimple.Jimple.v().newVirtualInvokeExpr(sb, methodToInvoke2);
soot.jimple.Stmt lastAssign = soot.jimple.Jimple.v().newAssignStmt(newString, toStringInvoke);
body.getUnits().add(lastAssign);
Util.addLnPosTags(lastAssign, expr.position());
return newString;
}
private boolean isStringConcat(polyglot.ast.Expr expr){
if (expr instanceof polyglot.ast.Binary) {
polyglot.ast.Binary bin = (polyglot.ast.Binary)expr;
if (bin.operator() == polyglot.ast.Binary.ADD){
if (bin.type().toString().equals("java.lang.String")) return true;
return false;
}
return false;
}
else if (expr instanceof polyglot.ast.Assign) {
polyglot.ast.Assign assign = (polyglot.ast.Assign)expr;
if (assign.operator() == polyglot.ast.Assign.ADD_ASSIGN){
if (assign.type().toString().equals("java.lang.String")) return true;
return false;
}
return false;
}
return false;
}
/**
* Generates one part of a concatenation String
*/
private soot.Local generateAppends(polyglot.ast.Expr expr, soot.Local sb) {
//System.out.println("generate appends for expr: "+expr);
if (isStringConcat(expr)){
if (expr instanceof polyglot.ast.Binary){
sb = generateAppends(((polyglot.ast.Binary)expr).left(), sb);
sb = generateAppends(((polyglot.ast.Binary)expr).right(), sb);
}
else {
sb = generateAppends(((polyglot.ast.Assign)expr).left(), sb);
sb = generateAppends(((polyglot.ast.Assign)expr).right(), sb);
}
}
else {
soot.Value toApp = base().createAggressiveExpr(expr, false, false);
//System.out.println("toApp: "+toApp+" type: "+toApp.getType());
soot.Type appendType = null;
if (toApp instanceof soot.jimple.StringConstant) {
appendType = soot.RefType.v("java.lang.String");
}
else if (toApp instanceof soot.jimple.NullConstant){
appendType = soot.RefType.v("java.lang.Object");
}
else if (toApp instanceof soot.jimple.Constant) {
appendType = toApp.getType();
}
else if (toApp instanceof soot.Local) {
if (((soot.Local)toApp).getType() instanceof soot.PrimType) {
appendType = ((soot.Local)toApp).getType();
}
else if (((soot.Local)toApp).getType() instanceof soot.RefType) {
if (((soot.Local)toApp).getType().toString().equals("java.lang.String")){
appendType = soot.RefType.v("java.lang.String");
}
else if (((soot.Local)toApp).getType().toString().equals("java.lang.StringBuffer")){
appendType = soot.RefType.v("java.lang.StringBuffer");
}
else{
appendType = soot.RefType.v("java.lang.Object");
}
}
else {
// this is for arrays
appendType = soot.RefType.v("java.lang.Object");
}
}
else if (toApp instanceof soot.jimple.ConditionExpr) {
toApp = handleCondBinExpr((soot.jimple.ConditionExpr)toApp);
appendType = soot.BooleanType.v();
}
// handle shorts
if (appendType instanceof soot.ShortType || appendType instanceof soot.ByteType) {
soot.Local intLocal = lg.generateLocal(soot.IntType.v());
soot.jimple.Expr cast = soot.jimple.Jimple.v().newCastExpr(toApp, soot.IntType.v());
soot.jimple.Stmt castAssign = soot.jimple.Jimple.v().newAssignStmt(intLocal, cast);
body.getUnits().add(castAssign);
toApp = intLocal;
appendType = soot.IntType.v();
}
ArrayList paramsTypes = new ArrayList();
paramsTypes.add(appendType);
ArrayList params = new ArrayList();
params.add(toApp);
soot.SootClass classToInvoke = soot.Scene.v().getSootClass("java.lang.StringBuffer");
soot.SootMethodRef methodToInvoke = soot.Scene.v().makeMethodRef(classToInvoke, "append", paramsTypes, soot.RefType.v("java.lang.StringBuffer"), false);
soot.jimple.VirtualInvokeExpr appendInvoke = soot.jimple.Jimple.v().newVirtualInvokeExpr(sb, methodToInvoke, params);
Util.addLnPosTags(appendInvoke.getArgBox(0), expr.position());
soot.Local tmp = lg.generateLocal(soot.RefType.v("java.lang.StringBuffer"));
soot.jimple.Stmt appendStmt = soot.jimple.Jimple.v().newAssignStmt(tmp, appendInvoke);
sb = tmp;
body.getUnits().add(appendStmt);
Util.addLnPosTags(appendStmt, expr.position());
}
return sb;
}
/**
* Unary Expression Creation
*/
private soot.Value getUnaryLocal(polyglot.ast.Unary unary) {
polyglot.ast.Expr expr = unary.expr();
polyglot.ast.Unary.Operator op = unary.operator();
if (op == polyglot.ast.Unary.POST_INC || op == polyglot.ast.Unary.PRE_INC || op == polyglot.ast.Unary.POST_DEC || op == polyglot.ast.Unary.PRE_DEC) {
if (base().needsAccessor(unary.expr())){
return base().handlePrivateFieldUnarySet(unary);
}
soot.Value left = base().createLHS(unary.expr());
// do necessary cloning
soot.Value leftClone = Jimple.cloneIfNecessary(left);
soot.Local tmp = lg.generateLocal(left.getType());
soot.jimple.AssignStmt stmt1 = soot.jimple.Jimple.v().newAssignStmt(tmp, left);
body.getUnits().add(stmt1);
Util.addLnPosTags(stmt1, unary.position());
soot.Value incVal = base().getConstant(left.getType(), 1);
soot.jimple.BinopExpr binExpr;
if (unary.operator() == polyglot.ast.Unary.PRE_INC || unary.operator() == polyglot.ast.Unary.POST_INC){
binExpr = soot.jimple.Jimple.v().newAddExpr(tmp, incVal);
}
else {
binExpr = soot.jimple.Jimple.v().newSubExpr(tmp, incVal);
}
soot.Local tmp2 = lg.generateLocal(left.getType());
soot.jimple.AssignStmt assign = soot.jimple.Jimple.v().newAssignStmt(tmp2, binExpr);
body.getUnits().add(assign);
//if (base().needsAccessor(unary.expr())){
// base().handlePrivateFieldSet(unary.expr(), tmp2);
//}
//else {
soot.jimple.AssignStmt stmt3 = soot.jimple.Jimple.v().newAssignStmt(leftClone, tmp2);
body.getUnits().add(stmt3);
//}
if (unary.operator() == polyglot.ast.Unary.POST_DEC || unary.operator() == polyglot.ast.Unary.POST_INC){
return tmp;
}
else {
return tmp2;
}
}
/*if (op == polyglot.ast.Unary.POST_INC){
soot.Local retLocal = generateLocal(expr.type());
soot.Value sootExpr = base().createExpr(expr);
soot.jimple.AssignStmt preStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, sootExpr);
body.getUnits().add(preStmt);
soot.jimple.AddExpr addExpr = soot.jimple.Jimple.v().newAddExpr(sootExpr, getConstant(retLocal.getType(), 1));
Util.addLnPosTags(addExpr.getOp1Box(), expr.position());
soot.Local local = generateLocal(expr.type());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(local, addExpr);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, expr.position());
soot.jimple.AssignStmt aStmt = soot.jimple.Jimple.v().newAssignStmt(sootExpr, local);
body.getUnits().add(aStmt);
Util.addLnPosTags(aStmt, expr.position());
Util.addLnPosTags(aStmt, unary.position());
if ((expr instanceof polyglot.ast.Field) || (expr instanceof polyglot.ast.ArrayAccess)) {
//if ((expr instanceof polyglot.ast.Field) && (needsPrivateAccessor((polyglot.ast.Field)expr) || needsProtectedAccessor((polyglot.ast.Field)expr))){
if (base().needsAccessor(expr)){
handlePrivateFieldSet(expr, local);
}
else {
soot.Value actualUnaryExpr = createLHS(expr);
soot.jimple.AssignStmt s = soot.jimple.Jimple.v().newAssignStmt(actualUnaryExpr, local);
body.getUnits().add(s);
Util.addLnPosTags(s, expr.position());
Util.addLnPosTags(s.getLeftOpBox(), expr.position());
}
}
return retLocal;
}
else if (op == polyglot.ast.Unary.POST_DEC) {
soot.Local retLocal = generateLocal(expr.type());
soot.Value sootExpr = base().createExpr(expr);
soot.jimple.AssignStmt preStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, sootExpr);
body.getUnits().add(preStmt);
soot.jimple.SubExpr subExpr = soot.jimple.Jimple.v().newSubExpr(sootExpr, getConstant(retLocal.getType(), 1));
Util.addLnPosTags(subExpr.getOp1Box(), expr.position());
soot.Local local = generateLocal(expr.type());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(local, subExpr);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, expr.position());
soot.jimple.AssignStmt aStmt = soot.jimple.Jimple.v().newAssignStmt(sootExpr, local);
body.getUnits().add(aStmt);
Util.addLnPosTags(aStmt, expr.position());
Util.addLnPosTags(aStmt, unary.position());
if ((expr instanceof polyglot.ast.Field) || (expr instanceof polyglot.ast.ArrayAccess)) {
//if ((expr instanceof polyglot.ast.Field) && (needsPrivateAccessor((polyglot.ast.Field)expr) || needsProtectedAccessor((polyglot.ast.Field)expr))){
if (base().needsAccessor(expr)){
handlePrivateFieldSet(expr, local);
}
else {
soot.Value actualUnaryExpr = createLHS(expr);
soot.jimple.AssignStmt s = soot.jimple.Jimple.v().newAssignStmt(actualUnaryExpr, local);
body.getUnits().add(s);
Util.addLnPosTags(s, expr.position());
Util.addLnPosTags(s.getLeftOpBox(), expr.position());
}
}
return retLocal;
}
else if (op == polyglot.ast.Unary.PRE_INC) {
soot.Value sootExpr = base().createExpr(expr);
soot.jimple.AddExpr addExpr = soot.jimple.Jimple.v().newAddExpr(sootExpr, getConstant(sootExpr.getType(), 1));
Util.addLnPosTags(addExpr.getOp1Box(), expr.position());
soot.Local local = generateLocal(expr.type());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(local, addExpr);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, expr.position());
if ((expr instanceof polyglot.ast.Field) || (expr instanceof polyglot.ast.ArrayAccess) || (expr instanceof polyglot.ast.Local)) {
//if ((expr instanceof polyglot.ast.Field) && (needsPrivateAccessor((polyglot.ast.Field)expr) || needsProtectedAccessor((polyglot.ast.Field)expr))){
if (base().needsAccessor(expr)){
handlePrivateFieldSet(expr, local);
}
else {
soot.Value actualUnaryExpr = createLHS(expr);
body.getUnits().add(soot.jimple.Jimple.v().newAssignStmt(actualUnaryExpr, local));
}
}
return local;
}
else if (op == polyglot.ast.Unary.PRE_DEC) {
soot.Value sootExpr = base().createExpr(expr);
soot.jimple.SubExpr subExpr = soot.jimple.Jimple.v().newSubExpr(sootExpr, getConstant(sootExpr.getType(), 1));
Util.addLnPosTags(subExpr.getOp1Box(), expr.position());
soot.Local local = generateLocal(expr.type());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(local, subExpr);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, expr.position());
if ((expr instanceof polyglot.ast.Field) || (expr instanceof polyglot.ast.ArrayAccess) || (expr instanceof polyglot.ast.Local)) {
//if ((expr instanceof polyglot.ast.Field) && (needsPrivateAccessor((polyglot.ast.Field)expr) || needsProtectedAccessor((polyglot.ast.Field)expr))){
if (base().needsAccessor(expr)){
handlePrivateFieldSet(expr, local);
}
else {
soot.Value actualUnaryExpr = createLHS(expr);
body.getUnits().add(soot.jimple.Jimple.v().newAssignStmt(actualUnaryExpr, local));
}
}
return local;
}*/
else if (op == polyglot.ast.Unary.BIT_NOT) {
soot.jimple.IntConstant int1 = soot.jimple.IntConstant.v(-1);
soot.Local retLocal = generateLocal(expr.type());
soot.Value sootExpr = base().createAggressiveExpr(expr, false, false);
soot.jimple.XorExpr xor = soot.jimple.Jimple.v().newXorExpr(sootExpr, base().getConstant(sootExpr.getType(), -1));
Util.addLnPosTags(xor.getOp1Box(), expr.position());
soot.jimple.Stmt assign1 = soot.jimple.Jimple.v().newAssignStmt(retLocal, xor);
body.getUnits().add(assign1);
Util.addLnPosTags(assign1, unary.position());
return retLocal;
}
else if (op == polyglot.ast.Unary.NEG) {
soot.Value sootExpr;
if (expr instanceof polyglot.ast.IntLit) {
long longVal = ((polyglot.ast.IntLit)expr).value();
if (((polyglot.ast.IntLit)expr).kind() == polyglot.ast.IntLit.LONG){
sootExpr = soot.jimple.LongConstant.v(-longVal);
}
else {
sootExpr = soot.jimple.IntConstant.v(-(int)longVal);
}
}
else if (expr instanceof polyglot.ast.FloatLit){
double doubleVal = ((polyglot.ast.FloatLit)expr).value();
if (((polyglot.ast.FloatLit)expr).kind() == polyglot.ast.FloatLit.DOUBLE){
sootExpr = soot.jimple.DoubleConstant.v(-doubleVal);
}
else {
sootExpr = soot.jimple.FloatConstant.v(-(float)doubleVal);
}
}
else {
soot.Value local = base().createAggressiveExpr(expr, false, false);
soot.jimple.NegExpr negExpr = soot.jimple.Jimple.v().newNegExpr(local);
sootExpr = negExpr;
Util.addLnPosTags(negExpr.getOpBox(), expr.position());
}
soot.Local retLocal = generateLocal(expr.type());
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(retLocal, sootExpr);
body.getUnits().add(assign);
Util.addLnPosTags(assign, expr.position());
return retLocal;
}
else if (op == polyglot.ast.Unary.POS) {
soot.Local retLocal = generateLocal(expr.type());
soot.Value sootExpr = base().createAggressiveExpr(expr, false, false);
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(retLocal, sootExpr);
body.getUnits().add(assign);
Util.addLnPosTags(assign, expr.position());
return retLocal;
}
else if (op == polyglot.ast.Unary.NOT) {
//pop any trueNoop and falseNoop - if its in an if and in a unary
//then it needs old style generation
boolean repush = false;
soot.jimple.Stmt tNoop = null;
soot.jimple.Stmt fNoop = null;
if (!trueNoop.empty() && !falseNoop.empty()){
tNoop = trueNoop.pop();
fNoop = falseNoop.pop();
repush = true;
}
soot.Value local = base().createAggressiveExpr(expr, false, false);
// repush right away to optimize ! for ifs
if (repush){
trueNoop.push(tNoop);
falseNoop.push(fNoop);
}
if (local instanceof soot.jimple.ConditionExpr){
local = handleCondBinExpr((soot.jimple.ConditionExpr)local);
}
soot.jimple.NeExpr neExpr = soot.jimple.Jimple.v().newNeExpr(local, base().getConstant(local.getType(), 0));
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.IfStmt ifStmt;
if (!falseNoop.empty()){
ifStmt = soot.jimple.Jimple.v().newIfStmt(neExpr, falseNoop.peek());
}
else {
ifStmt = soot.jimple.Jimple.v().newIfStmt(neExpr, noop1);
}
body.getUnits().add(ifStmt);
Util.addLnPosTags(ifStmt, expr.position());
Util.addLnPosTags(ifStmt.getConditionBox(), expr.position());
if (!falseNoop.empty()){
return soot.jimple.IntConstant.v(1);
}
soot.Local retLocal = lg.generateLocal(local.getType());
soot.jimple.Stmt assign1 = soot.jimple.Jimple.v().newAssignStmt(retLocal, base().getConstant(retLocal.getType(), 1));
body.getUnits().add(assign1);
Util.addLnPosTags(assign1, expr.position());
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
body.getUnits().add(noop1);
soot.jimple.Stmt assign2 = soot.jimple.Jimple.v().newAssignStmt(retLocal, base().getConstant(retLocal.getType(), 0));
body.getUnits().add(assign2);
Util.addLnPosTags(assign2, expr.position());
body.getUnits().add(noop2);
return retLocal;
}
else {
throw new RuntimeException("Unhandled Unary Expr");
}
}
/**
* Returns a needed constant given a type and val
*/
protected soot.jimple.Constant getConstant(soot.Type type, int val) {
if (type instanceof soot.DoubleType) {
return soot.jimple.DoubleConstant.v(val);
}
else if (type instanceof soot.FloatType) {
return soot.jimple.FloatConstant.v(val);
}
else if (type instanceof soot.LongType) {
return soot.jimple.LongConstant.v(val);
}
else {
return soot.jimple.IntConstant.v(val);
}
}
/**
* Cast Expression Creation
*/
private soot.Value getCastLocal(polyglot.ast.Cast castExpr){
// if its already the right type
if (castExpr.expr().type().equals(castExpr.type()) || (castExpr.type().isClass() && Util.getSootType(castExpr.type()).toString().equals("java.lang.Object"))) {
return base().createAggressiveExpr(castExpr.expr(), false, false);
}
soot.Value val;
val = base().createAggressiveExpr(castExpr.expr(), false, false);
soot.Type type = Util.getSootType(castExpr.type());
soot.jimple.CastExpr cast = soot.jimple.Jimple.v().newCastExpr(val, type);
Util.addLnPosTags(cast.getOpBox(), castExpr.expr().position());
soot.Local retLocal = lg.generateLocal(cast.getCastType());
soot.jimple.Stmt castAssign = soot.jimple.Jimple.v().newAssignStmt(retLocal, cast);
body.getUnits().add(castAssign);
Util.addLnPosTags(castAssign, castExpr.position());
return retLocal;
}
/**
* Procedure Call Helper Methods
* Returns list of params
*/
private ArrayList getSootParams(polyglot.ast.ProcedureCall call) {
ArrayList sootParams = new ArrayList();
Iterator it = call.arguments().iterator();
while (it.hasNext()) {
polyglot.ast.Expr next = (polyglot.ast.Expr)it.next();
soot.Value nextExpr = base().createAggressiveExpr(next, false, false);
if (nextExpr instanceof soot.jimple.ConditionExpr){
nextExpr = handleCondBinExpr((soot.jimple.ConditionExpr)nextExpr);
}
sootParams.add(nextExpr);
}
return sootParams;
}
/**
* Returns list of param types
*/
private ArrayList getSootParamsTypes(polyglot.ast.ProcedureCall call) {
ArrayList sootParamsTypes = new ArrayList();
Iterator it = call.procedureInstance().formalTypes().iterator();
while (it.hasNext()) {
Object next = it.next();
sootParamsTypes.add(Util.getSootType((polyglot.types.Type)next));
}
return sootParamsTypes;
}
/**
* Gets the Soot Method form the given Soot Class
*/
private soot.SootMethodRef getMethodFromClass(soot.SootClass sootClass, String name, ArrayList paramTypes, soot.Type returnType, boolean isStatic) {
soot.SootMethodRef ref = soot.Scene.v().makeMethodRef(sootClass, name, paramTypes, returnType, isStatic);
return ref;
}
/**
* Adds extra params
*/
private void handleFinalLocalParams(ArrayList sootParams, ArrayList sootParamTypes, polyglot.types.ClassType keyType){
HashMap<IdentityKey, AnonLocalClassInfo> finalLocalInfo = soot.javaToJimple.InitialResolver.v().finalLocalInfo();
if (finalLocalInfo != null){
if (finalLocalInfo.containsKey(new polyglot.util.IdentityKey(keyType))){
AnonLocalClassInfo alci = finalLocalInfo.get(new polyglot.util.IdentityKey(keyType));
ArrayList<IdentityKey> finalLocals = alci.finalLocalsUsed();
if (finalLocals != null){
Iterator<IdentityKey> it = finalLocals.iterator();
while (it.hasNext()){
Object next = it.next();
polyglot.types.LocalInstance li = (polyglot.types.LocalInstance)((polyglot.util.IdentityKey)next).object();
sootParamTypes.add(Util.getSootType(li.type()));
sootParams.add(getLocal(li));
}
}
}
}
}
protected soot.Local getThis(soot.Type sootType){
return Util.getThis(sootType, body, getThisMap, lg);
}
protected boolean needsOuterClassRef(polyglot.types.ClassType typeToInvoke){
// anon and local
AnonLocalClassInfo info = InitialResolver.v().finalLocalInfo().get(new polyglot.util.IdentityKey(typeToInvoke));
if (InitialResolver.v().isAnonInCCall(typeToInvoke)) return false;
if ((info != null) && (!info.inStaticMethod())){
return true;
}
// other nested
else if (typeToInvoke.isNested() && !typeToInvoke.flags().isStatic() && !typeToInvoke.isAnonymous() && !typeToInvoke.isLocal()){
return true;
}
return false;
}
/**
* adds outer class params
*/
private void handleOuterClassParams(ArrayList sootParams, soot.Value qVal, ArrayList sootParamsTypes, polyglot.types.ClassType typeToInvoke){
ArrayList needsRef = soot.javaToJimple.InitialResolver.v().getHasOuterRefInInit();
boolean addRef = needsOuterClassRef(typeToInvoke);//(needsRef != null) && (needsRef.contains(Util.getSootType(typeToInvoke)));
if (addRef){
// if adding an outer type ref always add exact type
soot.SootClass outerClass = ((soot.RefType)Util.getSootType(typeToInvoke.outer())).getSootClass();
sootParamsTypes.add(outerClass.getType());
}
if (addRef && !typeToInvoke.isAnonymous() && (qVal != null)){
// for nested and local if qualifier use that for param
sootParams.add(qVal);
}
else if (addRef && !typeToInvoke.isAnonymous()){
soot.SootClass outerClass = ((soot.RefType)Util.getSootType(typeToInvoke.outer())).getSootClass();
sootParams.add(getThis(outerClass.getType()));
}
else if (addRef && typeToInvoke.isAnonymous()){
soot.SootClass outerClass = ((soot.RefType)Util.getSootType(typeToInvoke.outer())).getSootClass();
sootParams.add(getThis(outerClass.getType()));
}
// handle anon qualifiers
if (typeToInvoke.isAnonymous() && (qVal != null)){
sootParamsTypes.add(qVal.getType());
sootParams.add(qVal);
}
}
/**
* Constructor Call Creation
*/
private void createConstructorCall(polyglot.ast.ConstructorCall cCall) {
ArrayList sootParams = new ArrayList();
ArrayList sootParamsTypes = new ArrayList();
polyglot.types.ConstructorInstance cInst = cCall.constructorInstance();
String containerName = null;
if (cInst.container() instanceof polyglot.types.ClassType) {
containerName = ((polyglot.types.ClassType)cInst.container()).fullName();
}
soot.SootClass classToInvoke;
if (cCall.kind() == polyglot.ast.ConstructorCall.SUPER) {
classToInvoke = ((soot.RefType)Util.getSootType(cInst.container())).getSootClass();
}
else if (cCall.kind() == polyglot.ast.ConstructorCall.THIS) {
classToInvoke = body.getMethod().getDeclaringClass();
}
else {
throw new RuntimeException("Unknown kind of Constructor Call");
}
soot.Local base = specialThisLocal;
polyglot.types.ClassType objType = (polyglot.types.ClassType)cInst.container();
soot.Local qVal = null;
if (cCall.qualifier() != null){// && (!(cCall.qualifier() instanceof polyglot.ast.Special && ((polyglot.ast.Special)cCall.qualifier()).kind() == polyglot.ast.Special.THIS)) ){
qVal = (soot.Local)base().createAggressiveExpr(cCall.qualifier(), false, false);
}
handleOuterClassParams(sootParams, qVal, sootParamsTypes, objType);
sootParams.addAll(getSootParams(cCall));
sootParamsTypes.addAll(getSootParamsTypes(cCall));
handleFinalLocalParams(sootParams, sootParamsTypes, (polyglot.types.ClassType)cCall.constructorInstance().container());
soot.SootMethodRef methodToInvoke = getMethodFromClass(classToInvoke, "<init>", sootParamsTypes, soot.VoidType.v(), false);
soot.jimple.SpecialInvokeExpr specialInvokeExpr = soot.jimple.Jimple.v().newSpecialInvokeExpr(base, methodToInvoke, sootParams);
soot.jimple.Stmt invokeStmt = soot.jimple.Jimple.v().newInvokeStmt(specialInvokeExpr);
body.getUnits().add(invokeStmt);
Util.addLnPosTags(invokeStmt, cCall.position());
// this is clearly broken if an outer class this ref was added as first
// param
int numParams = 0;
Iterator invokeParamsIt = cCall.arguments().iterator();
while (invokeParamsIt.hasNext()) {
Util.addLnPosTags(specialInvokeExpr.getArgBox(numParams), ((polyglot.ast.Expr)invokeParamsIt.next()).position());
numParams++;
}
// if method is <init> handle field inits
if (body.getMethod().getName().equals("<init>") && (cCall.kind() == polyglot.ast.ConstructorCall.SUPER)){
handleOuterClassThisInit(body.getMethod());
handleFinalLocalInits();
handleFieldInits(body.getMethod());
handleInitializerBlocks(body.getMethod());
}
}
private void handleFinalLocalInits(){
ArrayList<SootField> finalsList = ((PolyglotMethodSource)body.getMethod().getSource()).getFinalsList();
if (finalsList == null) return;
int paramCount = paramRefCount - finalsList.size();
Iterator<SootField> it = finalsList.iterator();
while (it.hasNext()){
soot.SootField sf = it.next();
soot.jimple.FieldRef fieldRef = soot.jimple.Jimple.v().newInstanceFieldRef(specialThisLocal, sf.makeRef());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(fieldRef, body.getParameterLocal(paramCount));
body.getUnits().add(stmt);
paramCount++;
}
}
/**
* Local Class Decl - Local Inner Class
*/
private void createLocalClassDecl(polyglot.ast.LocalClassDecl cDecl) {
BiMap lcMap = InitialResolver.v().getLocalClassMap();
String name = Util.getSootType(cDecl.decl().type()).toString();
if (!InitialResolver.v().hasClassInnerTag(body.getMethod().getDeclaringClass(), name)){
Util.addInnerClassTag(body.getMethod().getDeclaringClass(), name, null, cDecl.decl().name(), Util.getModifier(cDecl.decl().flags()));
}
}
/**
* New Expression Creation
*/
private soot.Local getNewLocal(polyglot.ast.New newExpr) {
// handle parameters/args
ArrayList sootParams = new ArrayList();
ArrayList sootParamsTypes = new ArrayList();
polyglot.types.ClassType objType = (polyglot.types.ClassType)newExpr.objectType().type();
if (newExpr.anonType() != null){
objType = newExpr.anonType();
// add inner class tags for any anon classes created
String name = Util.getSootType(objType).toString();
polyglot.types.ClassType outerType = objType.outer();
if (!InitialResolver.v().hasClassInnerTag(body.getMethod().getDeclaringClass(), name)){
Util.addInnerClassTag(body.getMethod().getDeclaringClass(), name, null, null, outerType.flags().isInterface() ? soot.Modifier.PUBLIC | soot.Modifier.STATIC : Util.getModifier(objType.flags()));
}
}
else {
// not an anon class but actually invoking a new something
if (!objType.isTopLevel()){
String name = Util.getSootType(objType).toString();
polyglot.types.ClassType outerType = objType.outer();
if (!InitialResolver.v().hasClassInnerTag(body.getMethod().getDeclaringClass(), name)){
Util.addInnerClassTag(body.getMethod().getDeclaringClass(), name, Util.getSootType(outerType).toString(), objType.name(), outerType.flags().isInterface() ? soot.Modifier.PUBLIC | soot.Modifier.STATIC : Util.getModifier(objType.flags()));
}
}
}
soot.RefType sootType = (soot.RefType)Util.getSootType(objType);
soot.Local retLocal = lg.generateLocal(sootType);
soot.jimple.NewExpr sootNew = soot.jimple.Jimple.v().newNewExpr(sootType);
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, sootNew);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, newExpr.position());
Util.addLnPosTags(stmt.getRightOpBox(), newExpr.position());
soot.SootClass classToInvoke = sootType.getSootClass();
// if no qualifier --> X to invoke is static
soot.Value qVal = null;
//System.out.println("new qualifier: "+newExpr.qualifier());
//if (newExpr.qualifier() != null) {
if (newExpr.qualifier() != null){// && (!(newExpr.qualifier() instanceof polyglot.ast.Special && ((polyglot.ast.Special)newExpr.qualifier()).kind() == polyglot.ast.Special.THIS)) ){
qVal = base().createAggressiveExpr(newExpr.qualifier(), false, false);
}
handleOuterClassParams(sootParams, qVal, sootParamsTypes, objType);
boolean repush = false;
soot.jimple.Stmt tNoop = null;
soot.jimple.Stmt fNoop = null;
if (!trueNoop.empty() && !falseNoop.empty()){
tNoop = trueNoop.pop();
fNoop = falseNoop.pop();
repush = true;
}
sootParams.addAll(getSootParams(newExpr));
if (repush){
trueNoop.push(tNoop);
falseNoop.push(fNoop);
}
sootParamsTypes.addAll(getSootParamsTypes(newExpr));
handleFinalLocalParams(sootParams, sootParamsTypes, (polyglot.types.ClassType)objType);
soot.SootMethodRef methodToInvoke = getMethodFromClass(classToInvoke, "<init>", sootParamsTypes, soot.VoidType.v(), false);
soot.jimple.SpecialInvokeExpr specialInvokeExpr = soot.jimple.Jimple.v().newSpecialInvokeExpr(retLocal, methodToInvoke, sootParams);
soot.jimple.Stmt invokeStmt = soot.jimple.Jimple.v().newInvokeStmt(specialInvokeExpr);
body.getUnits().add(invokeStmt);
Util.addLnPosTags(invokeStmt, newExpr.position());
int numParams = 0;
Iterator invokeParamsIt = newExpr.arguments().iterator();
while (invokeParamsIt.hasNext()) {
Util.addLnPosTags(specialInvokeExpr.getArgBox(numParams), ((polyglot.ast.Expr)invokeParamsIt.next()).position());
numParams++;
}
return retLocal;
}
protected soot.SootMethodRef getSootMethodRef(polyglot.ast.Call call){
soot.Type sootRecType;
soot.SootClass receiverTypeClass;
if (Util.getSootType(call.methodInstance().container()).equals(soot.RefType.v("java.lang.Object"))){
sootRecType = soot.RefType.v("java.lang.Object");
receiverTypeClass = soot.Scene.v().getSootClass("java.lang.Object");
}
else {
if (call.target().type() == null){
sootRecType = Util.getSootType(call.methodInstance().container());
}
else {
sootRecType = Util.getSootType(call.target().type());
}
if (sootRecType instanceof soot.RefType){
receiverTypeClass = ((soot.RefType)sootRecType).getSootClass();
}
else if (sootRecType instanceof soot.ArrayType){
receiverTypeClass = soot.Scene.v().getSootClass("java.lang.Object");
}
else {
throw new RuntimeException("call target problem: "+call);
}
}
polyglot.types.MethodInstance methodInstance = call.methodInstance();
soot.Type sootRetType = Util.getSootType(methodInstance.returnType());
ArrayList sootParamsTypes = getSootParamsTypes(call);
soot.SootMethodRef callMethod = soot.Scene.v().makeMethodRef(receiverTypeClass, methodInstance.name(), sootParamsTypes, sootRetType, methodInstance.flags().isStatic());
return callMethod;
}
/**
* Call Expression Creation
*/
private soot.Local getCallLocal(polyglot.ast.Call call){
// handle name
String name = call.name();
// handle receiver/target
polyglot.ast.Receiver receiver = call.target();
//System.out.println("call: "+call+" receiver: "+receiver);
soot.Local baseLocal;
if ((receiver instanceof polyglot.ast.Special) && (((polyglot.ast.Special)receiver).kind() == polyglot.ast.Special.SUPER) && (((polyglot.ast.Special)receiver).qualifier() != null)){
baseLocal = getSpecialSuperQualifierLocal(call);
return baseLocal;
}
baseLocal = (soot.Local)base().getBaseLocal(receiver);
//System.out.println("base local: "+baseLocal);
boolean repush = false;
soot.jimple.Stmt tNoop = null;
soot.jimple.Stmt fNoop = null;
if (!trueNoop.empty() && !falseNoop.empty()){
tNoop = trueNoop.pop();
fNoop = falseNoop.pop();
repush = true;
}
ArrayList sootParams = getSootParams(call);
if (repush){
trueNoop.push(tNoop);
falseNoop.push(fNoop);
}
soot.SootMethodRef callMethod = base().getSootMethodRef(call);
soot.Type sootRecType;
soot.SootClass receiverTypeClass;
if (Util.getSootType(call.methodInstance().container()).equals(soot.RefType.v("java.lang.Object"))){
sootRecType = soot.RefType.v("java.lang.Object");
receiverTypeClass = soot.Scene.v().getSootClass("java.lang.Object");
}
else {
if (call.target().type() == null){
sootRecType = Util.getSootType(call.methodInstance().container());
}
else {
sootRecType = Util.getSootType(call.target().type());
}
if (sootRecType instanceof soot.RefType){
receiverTypeClass = ((soot.RefType)sootRecType).getSootClass();
}
else if (sootRecType instanceof soot.ArrayType){
receiverTypeClass = soot.Scene.v().getSootClass("java.lang.Object");
}
else {
throw new RuntimeException("call target problem: "+call);
}
}
polyglot.types.MethodInstance methodInstance = call.methodInstance();
/*soot.Type sootRetType = Util.getSootType(methodInstance.returnType());
ArrayList sootParamsTypes = getSootParamsTypes(call);
ArrayList sootParams = getSootParams(call);
soot.SootMethodRef callMethod = soot.Scene.v().makeMethodRef(receiverTypeClass, methodInstance.name(), sootParamsTypes, sootRetType, methodInstance.flags().isStatic());*/
boolean isPrivateAccess = false;
//if (call.methodInstance().flags().isPrivate() && !Util.getSootType(call.methodInstance().container()).equals(body.getMethod().getDeclaringClass().getType())){
if (needsAccessor(call)){
soot.SootClass containingClass = ((soot.RefType)Util.getSootType(call.methodInstance().container())).getSootClass();
soot.SootClass classToAddMethTo = containingClass;
if (call.methodInstance().flags().isProtected()){
if (InitialResolver.v().hierarchy() == null){
InitialResolver.v().hierarchy(new soot.FastHierarchy());
}
soot.SootClass addToClass;
if (body.getMethod().getDeclaringClass().hasOuterClass()){
addToClass = body.getMethod().getDeclaringClass().getOuterClass();
while (!InitialResolver.v().hierarchy().canStoreType(containingClass.getType(), addToClass.getType())){
if (addToClass.hasOuterClass()){
addToClass = addToClass.getOuterClass();
}
else {
break;
}
}
}
else{
addToClass = containingClass;
}
classToAddMethTo = addToClass;
}
callMethod = addGetMethodAccessMeth(classToAddMethTo, call).makeRef();
if (!call.methodInstance().flags().isStatic()){
if (call.target() instanceof polyglot.ast.Expr){
sootParams.add(0, baseLocal);
}
else if (body.getMethod().getDeclaringClass().declaresFieldByName("this$0")){
sootParams.add(0, getThis(Util.getSootType(call.methodInstance().container())));//baseLocal);
}
else {
sootParams.add(0, baseLocal);
}
}
isPrivateAccess = true;
}
soot.jimple.InvokeExpr invokeExpr;
if (isPrivateAccess){
// for accessing private methods in outer class -> always static
invokeExpr = soot.jimple.Jimple.v().newStaticInvokeExpr(callMethod, sootParams);
}
else if (soot.Modifier.isInterface(receiverTypeClass.getModifiers()) && methodInstance.flags().isAbstract()) {
// if reciever class is interface and method is abstract -> interface
invokeExpr = soot.jimple.Jimple.v().newInterfaceInvokeExpr(baseLocal, callMethod, sootParams);
}
else if (methodInstance.flags().isStatic()){
// if flag isStatic -> static invoke
invokeExpr = soot.jimple.Jimple.v().newStaticInvokeExpr(callMethod, sootParams);
}
else if (methodInstance.flags().isPrivate()){
// if flag isPrivate -> special invoke
invokeExpr = soot.jimple.Jimple.v().newSpecialInvokeExpr(baseLocal, callMethod, sootParams);
}
else if ((receiver instanceof polyglot.ast.Special) &&
(((polyglot.ast.Special)receiver).kind() == polyglot.ast.Special.SUPER)){
// receiver is special super -> special
invokeExpr = soot.jimple.Jimple.v().newSpecialInvokeExpr(baseLocal, callMethod, sootParams);
}
else {
// else virtual invoke
invokeExpr = soot.jimple.Jimple.v().newVirtualInvokeExpr(baseLocal, callMethod, sootParams);
}
int numParams = 0;
Iterator callParamsIt = call.arguments().iterator();
while (callParamsIt.hasNext()) {
Util.addLnPosTags(invokeExpr.getArgBox(numParams), ((polyglot.ast.Expr)callParamsIt.next()).position());
numParams++;
}
if (invokeExpr instanceof soot.jimple.InstanceInvokeExpr) {
Util.addLnPosTags(((soot.jimple.InstanceInvokeExpr)invokeExpr).getBaseBox(), call.target().position());
}
// create an assign stmt so invoke can be used somewhere else
if (invokeExpr.getMethodRef().returnType().equals(soot.VoidType.v())) {
soot.jimple.Stmt invoke = soot.jimple.Jimple.v().newInvokeStmt(invokeExpr);
body.getUnits().add(invoke);
Util.addLnPosTags(invoke, call.position());
return null;
}
else {
soot.Local retLocal = lg.generateLocal(invokeExpr.getMethodRef().returnType());
soot.jimple.Stmt assignStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, invokeExpr);
// add assign stmt to body
body.getUnits().add(assignStmt);
Util.addLnPosTags(assignStmt, call.position());
return retLocal;
}
}
protected soot.Value getBaseLocal(polyglot.ast.Receiver receiver) {
if (receiver instanceof polyglot.ast.TypeNode) {
return generateLocal(((polyglot.ast.TypeNode)receiver).type());
}
else {
soot.Value val = base().createAggressiveExpr((polyglot.ast.Expr)receiver, false, false);
if (val instanceof soot.jimple.Constant) {
soot.Local retLocal = lg.generateLocal(val.getType());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, val);
body.getUnits().add(stmt);
return retLocal;
}
return val;
}
}
/**
* NewArray Expression Creation
*/
private soot.Local getNewArrayLocal(polyglot.ast.NewArray newArrExpr) {
soot.Type sootType = Util.getSootType(newArrExpr.type());
//System.out.println("creating new array of type: "+sootType);
soot.jimple.Expr expr;
if (newArrExpr.numDims() == 1) {
soot.Value dimLocal;
if (newArrExpr.additionalDims() == 1) {
dimLocal = soot.jimple.IntConstant.v(1);
}
else {
dimLocal = base().createAggressiveExpr((polyglot.ast.Expr)newArrExpr.dims().get(0), false, false);
}
//System.out.println("creating new array: "+((soot.ArrayType)sootType).getElementType());
soot.jimple.NewArrayExpr newArrayExpr = soot.jimple.Jimple.v().newNewArrayExpr(((soot.ArrayType)sootType).getElementType(), dimLocal);
expr = newArrayExpr;
if (newArrExpr.additionalDims() != 1){
Util.addLnPosTags(newArrayExpr.getSizeBox(), ((polyglot.ast.Expr)newArrExpr.dims().get(0)).position());
}
}
else {
ArrayList valuesList = new ArrayList();
Iterator it = newArrExpr.dims().iterator();
while (it.hasNext()){
valuesList.add(base().createAggressiveExpr((polyglot.ast.Expr)it.next(), false, false));
}
if (newArrExpr.additionalDims() != 0) {
valuesList.add(soot.jimple.IntConstant.v(newArrExpr.additionalDims()));
}
soot.jimple.NewMultiArrayExpr newMultiArrayExpr = soot.jimple.Jimple.v().newNewMultiArrayExpr((soot.ArrayType)sootType, valuesList);
expr = newMultiArrayExpr;
Iterator sizeBoxIt = newArrExpr.dims().iterator();
int counter = 0;
while (sizeBoxIt.hasNext()){
Util.addLnPosTags(newMultiArrayExpr.getSizeBox(counter), ((polyglot.ast.Expr)sizeBoxIt.next()).position());
counter++;
}
}
soot.Local retLocal = lg.generateLocal(sootType);
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, expr);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, newArrExpr.position());
Util.addLnPosTags(stmt.getRightOpBox(), newArrExpr.position());
// handle array init if one exists
if (newArrExpr.init() != null) {
soot.Value initVal = getArrayInitLocal(newArrExpr.init(), newArrExpr.type());
soot.jimple.AssignStmt initStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, initVal);
body.getUnits().add(initStmt);
}
return retLocal;
}
/**
* create ArrayInit given init and the array local
*/
private soot.Local getArrayInitLocal(polyglot.ast.ArrayInit arrInit, polyglot.types.Type lhsType) {
//System.out.println("lhs type: "+lhsType);
soot.Local local = generateLocal(lhsType);
//System.out.println("creating new array: "+((soot.ArrayType)local.getType()).getElementType());
soot.jimple.NewArrayExpr arrExpr = soot.jimple.Jimple.v().newNewArrayExpr(((soot.ArrayType)local.getType()).getElementType(), soot.jimple.IntConstant.v(arrInit.elements().size()));
soot.jimple.Stmt assign = soot.jimple.Jimple.v().newAssignStmt(local, arrExpr);
body.getUnits().add(assign);
Util.addLnPosTags(assign, arrInit.position());
Iterator it = arrInit.elements().iterator();
int index = 0;
while (it.hasNext()){
polyglot.ast.Expr elemExpr = (polyglot.ast.Expr)it.next();
soot.Value elem;
if (elemExpr instanceof polyglot.ast.ArrayInit){
if (((polyglot.ast.ArrayInit)elemExpr).type() instanceof polyglot.types.NullType) {
if (lhsType instanceof polyglot.types.ArrayType){
//System.out.println("coming from 1 in get arrayinitlocal"+((polyglot.types.ArrayType)lhsType).base());
elem = getArrayInitLocal((polyglot.ast.ArrayInit)elemExpr, ((polyglot.types.ArrayType)lhsType).base());
}
else {
//System.out.println("coming from 2 in get arrayinitlocal"+((polyglot.types.ArrayType)lhsType).base());
elem = getArrayInitLocal((polyglot.ast.ArrayInit)elemExpr, lhsType);
}
}
else {
//System.out.println("coming from 3 in get arrayinitlocal"+((polyglot.types.ArrayType)lhsType).base());
//elem = getArrayInitLocal((polyglot.ast.ArrayInit)elemExpr, ((polyglot.ast.ArrayInit)elemExpr).type());
elem = getArrayInitLocal((polyglot.ast.ArrayInit)elemExpr, ((polyglot.types.ArrayType)lhsType).base());
}
}
else {
elem = base().createAggressiveExpr(elemExpr, false, false);
}
soot.jimple.ArrayRef arrRef = soot.jimple.Jimple.v().newArrayRef(local, soot.jimple.IntConstant.v(index));
soot.jimple.AssignStmt elemAssign = soot.jimple.Jimple.v().newAssignStmt(arrRef, elem);
body.getUnits().add(elemAssign);
Util.addLnPosTags(elemAssign, elemExpr.position());
Util.addLnPosTags(elemAssign.getRightOpBox(), elemExpr.position());
index++;
}
return local;
}
/**
* create LHS expressions
*/
protected soot.Value createLHS(polyglot.ast.Expr expr) {
if (expr instanceof polyglot.ast.Local) {
return getLocal((polyglot.ast.Local)expr);
}
else if (expr instanceof polyglot.ast.ArrayAccess) {
return getArrayRefLocalLeft((polyglot.ast.ArrayAccess)expr);
}
else if (expr instanceof polyglot.ast.Field) {
return getFieldLocalLeft((polyglot.ast.Field)expr);
}
else {
throw new RuntimeException("Unhandled LHS");
}
}
/**
* Array Ref Expression Creation - LHS
*/
private soot.Value getArrayRefLocalLeft(polyglot.ast.ArrayAccess arrayRefExpr) {
polyglot.ast.Expr array = arrayRefExpr.array();
polyglot.ast.Expr access = arrayRefExpr.index();
soot.Local arrLocal = (soot.Local)base().createAggressiveExpr(array, false, false);
soot.Value arrAccess = base().createAggressiveExpr(access, false, false);
soot.Local retLocal = generateLocal(arrayRefExpr.type());
soot.jimple.ArrayRef ref = soot.jimple.Jimple.v().newArrayRef(arrLocal, arrAccess);
Util.addLnPosTags(ref.getBaseBox(), arrayRefExpr.array().position());
Util.addLnPosTags(ref.getIndexBox(), arrayRefExpr.index().position());
return ref;
}
/**
* Array Ref Expression Creation
*/
private soot.Value getArrayRefLocal(polyglot.ast.ArrayAccess arrayRefExpr) {
polyglot.ast.Expr array = arrayRefExpr.array();
polyglot.ast.Expr access = arrayRefExpr.index();
soot.Local arrLocal = (soot.Local)base().createAggressiveExpr(array, false, false);
soot.Value arrAccess = base().createAggressiveExpr(access, false, false);
soot.Local retLocal = generateLocal(arrayRefExpr.type());
soot.jimple.ArrayRef ref = soot.jimple.Jimple.v().newArrayRef(arrLocal, arrAccess);
Util.addLnPosTags(ref.getBaseBox(), arrayRefExpr.array().position());
Util.addLnPosTags(ref.getIndexBox(), arrayRefExpr.index().position());
soot.jimple.Stmt stmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, ref);
body.getUnits().add(stmt);
Util.addLnPosTags(stmt, arrayRefExpr.position());
return retLocal;
}
private soot.Local getSpecialSuperQualifierLocal(polyglot.ast.Expr expr){
soot.SootClass classToInvoke;
ArrayList methodParams = new ArrayList();
if (expr instanceof polyglot.ast.Call){
polyglot.ast.Special target = (polyglot.ast.Special)((polyglot.ast.Call)expr).target();
classToInvoke = ((soot.RefType)Util.getSootType(target.qualifier().type())).getSootClass();
methodParams = getSootParams((polyglot.ast.Call)expr);
}
else if (expr instanceof polyglot.ast.Field){
polyglot.ast.Special target = (polyglot.ast.Special)((polyglot.ast.Field)expr).target();
classToInvoke = ((soot.RefType)Util.getSootType(target.qualifier().type())).getSootClass();
}
else {
throw new RuntimeException("Trying to create special super qualifier for: "+expr+" which is not a field or call");
}
// make an access method
soot.SootMethod methToInvoke = makeSuperAccessMethod(classToInvoke, expr);
// invoke it
soot.Local classToInvokeLocal = Util.getThis(classToInvoke.getType(), body, getThisMap, lg);
methodParams.add(0, classToInvokeLocal);
soot.jimple.InvokeExpr invokeExpr = soot.jimple.Jimple.v().newStaticInvokeExpr(methToInvoke.makeRef(), methodParams);
// return the local of return type if not void
if (!methToInvoke.getReturnType().equals(soot.VoidType.v())){
soot.Local retLocal = lg.generateLocal(methToInvoke.getReturnType());
soot.jimple.AssignStmt stmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, invokeExpr);
body.getUnits().add(stmt);
return retLocal;
}
else {
body.getUnits().add(soot.jimple.Jimple.v().newInvokeStmt(invokeExpr));
return null;
}
}
/**
* Special Expression Creation
*/
private soot.Local getSpecialLocal(polyglot.ast.Special specialExpr) {
//System.out.println(specialExpr);
if (specialExpr.kind() == polyglot.ast.Special.SUPER) {
if (specialExpr.qualifier() == null){
return specialThisLocal;
}
else {
// this isn't enough
// need to getThis for the type which may be several levels up
// add access$N method to class of the type which returns
// field or method wanted
// invoke it
// and it needs to be called specially when getting fields
// or calls because need to know field or method to access
// as it access' a field or meth in the super class of the
// outer class refered to by the qualifier
return getThis(Util.getSootType(specialExpr.qualifier().type()));
}
}
else if (specialExpr.kind() == polyglot.ast.Special.THIS) {
//System.out.println("this is special this: "+specialExpr);
if (specialExpr.qualifier() == null) {
return specialThisLocal;
}
else {
return getThis(Util.getSootType(specialExpr.qualifier().type()));
}
}
else {
throw new RuntimeException("Unknown Special");
}
}
private soot.SootMethod makeSuperAccessMethod(soot.SootClass classToInvoke, Object memberToAccess){
String name = "access$"+soot.javaToJimple.InitialResolver.v().getNextPrivateAccessCounter()+"00";
ArrayList paramTypes = new ArrayList();
paramTypes.add(classToInvoke.getType());
soot.SootMethod meth;
soot.MethodSource src;
if (memberToAccess instanceof polyglot.ast.Field){
polyglot.ast.Field fieldToAccess = (polyglot.ast.Field)memberToAccess;
meth = new soot.SootMethod(name, paramTypes, Util.getSootType(fieldToAccess.type()), soot.Modifier.STATIC);
PrivateFieldAccMethodSource fSrc = new PrivateFieldAccMethodSource(
Util.getSootType(fieldToAccess.type()),
fieldToAccess.name(),
fieldToAccess.flags().isStatic(),
((soot.RefType)Util.getSootType(fieldToAccess.target().type())).getSootClass()
);
src = fSrc;
}
else if (memberToAccess instanceof polyglot.ast.Call){
polyglot.ast.Call methToAccess = (polyglot.ast.Call)memberToAccess;
paramTypes.addAll(getSootParamsTypes(methToAccess));
meth = new soot.SootMethod(name, paramTypes, Util.getSootType(methToAccess.methodInstance().returnType()), soot.Modifier.STATIC);
PrivateMethodAccMethodSource mSrc = new PrivateMethodAccMethodSource( methToAccess.methodInstance());
src = mSrc;
}
else {
throw new RuntimeException("trying to access unhandled member type: "+memberToAccess);
}
classToInvoke.addMethod(meth);
meth.setActiveBody(src.getBody(meth, null));
meth.addTag(new soot.tagkit.SyntheticTag());
return meth;
}
/**
* InstanceOf Expression Creation
*/
private soot.Local getInstanceOfLocal(polyglot.ast.Instanceof instExpr) {
soot.Type sootType = Util.getSootType(instExpr.compareType().type());
soot.Value local = base().createAggressiveExpr(instExpr.expr(), false, false);
soot.jimple.InstanceOfExpr instOfExpr = soot.jimple.Jimple.v().newInstanceOfExpr(local, sootType);
soot.Local lhs = lg.generateLocal(soot.BooleanType.v());
soot.jimple.AssignStmt instAssign = soot.jimple.Jimple.v().newAssignStmt(lhs, instOfExpr);
body.getUnits().add(instAssign);
Util.addLnPosTags(instAssign, instExpr.position());
Util.addLnPosTags(instAssign.getRightOpBox(), instExpr.position());
Util.addLnPosTags(instOfExpr.getOpBox(), instExpr.expr().position());
return lhs;
}
/**
* Condition Expression Creation - can maybe merge with If
*/
private soot.Local getConditionalLocal(polyglot.ast.Conditional condExpr){
// handle cond
soot.jimple.Stmt noop1 = soot.jimple.Jimple.v().newNopStmt();
polyglot.ast.Expr condition = condExpr.cond();
createBranchingExpr(condition, noop1, false);
soot.Local retLocal = generateLocal(condExpr.type());
// handle consequence
polyglot.ast.Expr consequence = condExpr.consequent();
soot.Value conseqVal = base().createAggressiveExpr(consequence, false, false);
if (conseqVal instanceof soot.jimple.ConditionExpr) {
conseqVal = handleCondBinExpr((soot.jimple.ConditionExpr)conseqVal);
}
soot.jimple.AssignStmt conseqAssignStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, conseqVal);
body.getUnits().add(conseqAssignStmt);
Util.addLnPosTags(conseqAssignStmt, condExpr.position());
Util.addLnPosTags(conseqAssignStmt.getRightOpBox(), consequence.position());
soot.jimple.Stmt noop2 = soot.jimple.Jimple.v().newNopStmt();
soot.jimple.Stmt goto1 = soot.jimple.Jimple.v().newGotoStmt(noop2);
body.getUnits().add(goto1);
// handle alternative
body.getUnits().add(noop1);
polyglot.ast.Expr alternative = condExpr.alternative();
if (alternative != null){
soot.Value altVal = base().createAggressiveExpr(alternative, false, false);
if (altVal instanceof soot.jimple.ConditionExpr) {
altVal = handleCondBinExpr((soot.jimple.ConditionExpr)altVal);
}
soot.jimple.AssignStmt altAssignStmt = soot.jimple.Jimple.v().newAssignStmt(retLocal, altVal);
body.getUnits().add(altAssignStmt);
Util.addLnPosTags(altAssignStmt, condExpr.position());
Util.addLnPosTags(altAssignStmt, alternative.position());
Util.addLnPosTags(altAssignStmt.getRightOpBox(), alternative.position());
}
body.getUnits().add(noop2);
return retLocal;
}
/**
* Utility methods
*/
/*private boolean isLitOrLocal(polyglot.ast.Expr exp) {
if (exp instanceof polyglot.ast.Lit) return true;
if (exp instanceof polyglot.ast.Local) return true;
else return false;
}*/
/**
* Extra Local Variables Generation
*/
protected soot.Local generateLocal(polyglot.types.Type polyglotType) {
soot.Type type = Util.getSootType(polyglotType);
return lg.generateLocal(type);
}
protected soot.Local generateLocal(soot.Type sootType){
return lg.generateLocal(sootType);
}
}