/* Soot - a J*va Optimization Framework * Copyright (C) 2005 Nomair A. Naeem * * 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.dava.toolkits.base.AST.transformations; import java.util.*; import soot.jimple.*; import soot.dava.internal.SET.*; import soot.dava.internal.AST.*; import soot.dava.internal.asg.*; import soot.dava.internal.javaRep.*; public class StrengthenByIf{ /* We know this method is called when there is a while node which has a body consisting entirely of one ASTIfNode */ public static List<ASTNode> getNewNode(ASTNode loopNode, ASTIfNode ifNode){ List<Object> ifBody = ifNode.getIfBody(); String label = isItOnlyBreak(ifBody); if(label != null){ //only one break statement and it is breaking some label //make sure its breaking the label on the loop if(((ASTLabeledNode)loopNode).get_Label().toString()!=null){ if(((ASTLabeledNode)loopNode).get_Label().toString().compareTo(label)==0){ //the if has a single break breaking the loop //pattern 1 matched if(loopNode instanceof ASTWhileNode){ ASTCondition outerCond = ((ASTWhileNode)loopNode).get_Condition(); //flip the inner condition ASTCondition innerCond = ifNode.get_Condition(); innerCond.flip(); //aggregate the two conditions ASTCondition newCond = new ASTAndCondition(outerCond,innerCond); //make empty body List<Object> newWhileBody = new ArrayList<Object>(); //SETNodeLabel newLabel = ((ASTWhileNode)loopNode).get_Label(); // dont need any label name since the body of the while is empty SETNodeLabel newLabel = new SETNodeLabel(); //make new ASTWhileNode List<ASTNode> toReturn = new ArrayList<ASTNode>(); toReturn.add(new ASTWhileNode(newLabel,newCond,newWhileBody)); return toReturn; } else if(loopNode instanceof ASTDoWhileNode){ /* What to do when the ASTDoWhileNode only has one body which is a break of the whileNode??? */ return null; } else if (loopNode instanceof ASTUnconditionalLoopNode){ /* An UnconditionalLoopNode has a single If Condition which breaks the loop In this case Create an ASTWhileLoop Node with the flipped Condition of the If statement */ //flip the inner condition ASTCondition innerCond = ifNode.get_Condition(); innerCond.flip(); //make empty body List<Object> newWhileBody = new ArrayList<Object>(); //SETNodeLabel newLabel = ((ASTUnconditionalLoopNode)loopNode).get_Label(); // dont need any label name since the body of the while is empty SETNodeLabel newLabel = new SETNodeLabel(); //make new ASTWhileNode List<ASTNode> toReturn = new ArrayList<ASTNode>(); toReturn.add(new ASTWhileNode(newLabel,innerCond,newWhileBody)); return toReturn; } }//if the labels match } }//the first Pattern was a match else if(loopNode instanceof ASTUnconditionalLoopNode && ifBody.size()==1){ //try the UnconditionalLoopNode pattern //we need one stmtSeq Node ASTNode tempNode = (ASTNode)ifBody.get(0); if(tempNode instanceof ASTStatementSequenceNode){ //a stmtSeq List<Object> statements = ((ASTStatementSequenceNode)tempNode).getStatements(); Iterator<Object> stIt = statements.iterator(); while(stIt.hasNext()){ AugmentedStmt as = (AugmentedStmt)stIt.next(); Stmt stmt = as.get_Stmt(); if(stmt instanceof DAbruptStmt && !(stIt.hasNext())){ //this is an abrupt stmt and the last stmt DAbruptStmt abStmt = (DAbruptStmt)stmt; if(abStmt.is_Break()){ //last statement and that too a break String loopLabel = ((ASTLabeledNode)loopNode).get_Label().toString(); String breakLabel= abStmt.getLabel().toString(); if(loopLabel != null && breakLabel!=null){ if(loopLabel.compareTo(breakLabel)==0){ //pattern matched //flip the inner condition ASTCondition innerCond = ifNode.get_Condition(); innerCond.flip(); //make empty body List<Object> newWhileBody = new ArrayList<Object>(); SETNodeLabel newLabel = ((ASTUnconditionalLoopNode)loopNode).get_Label(); //make new ASTWhileNode List<ASTNode> toReturn = new ArrayList<ASTNode>(); toReturn.add(new ASTWhileNode(newLabel,innerCond,newWhileBody)); // Add the statementSequenceNode AFTER the whileNode except for the laststmt Iterator<Object> tempIt = statements.iterator(); List<Object> newStmts = new ArrayList<Object>(); while(tempIt.hasNext()){ Object tempStmt = tempIt.next(); if(tempIt.hasNext()){ newStmts.add(tempStmt); } } toReturn.add(new ASTStatementSequenceNode(newStmts)); return toReturn; }//labels are the same }//labels are non null }//is a break stmt } else if (stmt instanceof ReturnStmt || stmt instanceof ReturnVoidStmt){ if(!(stIt.hasNext())){ //return obj/return; //flip cond ASTCondition innerCond = ifNode.get_Condition(); innerCond.flip(); //make empty body List<Object> newWhileBody = new ArrayList<Object>(); //SETNodeLabel newLabel = ((ASTUnconditionalLoopNode)loopNode).get_Label(); // dont need any label name since the body of the while is empty SETNodeLabel newLabel = new SETNodeLabel(); //make new ASTWhileNode List<ASTNode> toReturn = new ArrayList<ASTNode>(); toReturn.add(new ASTWhileNode(newLabel,innerCond,newWhileBody)); // Add the statementSequenceNode AFTER the whileNode except for the laststmt Iterator<Object> tempIt = statements.iterator(); List<Object> newStmts = new ArrayList<Object>(); while(tempIt.hasNext()){ newStmts.add(tempIt.next()); } toReturn.add(new ASTStatementSequenceNode(newStmts)); return toReturn; } } }//end of going through statements }//end of stmtSEq node }//end of else if return null; }//end of method /* Given a body of a node the method checks for the following: 1, the body has only one node 2, the node is a statementSequenceNode 3, There is only one statement in the stmt seq node 4, the stmt is a break stmt If the conditions are true the label of the break stmt is returned otherwise null is returned */ private static String isItOnlyBreak(List<Object> body){ if(body.size()!=1){ //this is more than one we need one stmtSeq Node return null; } ASTNode tempNode = (ASTNode)body.get(0); if(!(tempNode instanceof ASTStatementSequenceNode)){ //not a stmtSeq return null; } List<Object> statements = ((ASTStatementSequenceNode)tempNode).getStatements(); if(statements.size()!=1){ //we need one break return null; } AugmentedStmt as = (AugmentedStmt)statements.get(0); Stmt stmt = as.get_Stmt(); if(!(stmt instanceof DAbruptStmt)){ //this is not a break stmt return null; } DAbruptStmt abStmt = (DAbruptStmt)stmt; if(!(abStmt.is_Break())){ //we need a break return null; } return abStmt.getLabel().toString(); } }