/* 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.*; /* Nomair A. Naeem 03-MARCH-2005 PATTERN 1: if(cond1){ if(cond1){ break label_1 break label_1 } -----> } else{ Body1 Body1 } PATTERN 2: if(!cond1){ if(cond1){ Body1 break label_1 } -----> } else{ Body1 break label_1 } The assumption is that if cond1 is true there is an abrupt edge and Body1 will not be executed. So this works only if the else in the original has an abrupt control flow. This can be break/continue/return TO MAKE CODE EFFECIENT BLOCK THE ANALYSIS TO GOING INTO STATEMENTS this is done by overriding the caseASTStatementSequenceNode */ public class IfElseBreaker{ ASTIfNode newIfNode; List<Object> remainingBody; public IfElseBreaker(){ newIfNode=null; remainingBody=null; } public boolean isIfElseBreakingPossiblePatternOne(ASTIfElseNode node){ List<Object> ifBody = node.getIfBody(); if(ifBody.size()!=1){ //we are only interested if size is one return false; } ASTNode onlyNode=(ASTNode)ifBody.get(0); boolean check = checkStmt(onlyNode,node); if(!check){ return false; } //breaking is possible //break and store newIfNode = new ASTIfNode(((ASTLabeledNode)node).get_Label(),node.get_Condition(),ifBody); remainingBody = node.getElseBody(); return true; } public boolean isIfElseBreakingPossiblePatternTwo(ASTIfElseNode node){ List<Object> elseBody = node.getElseBody(); if(elseBody.size()!=1){ //we are only interested if size is one return false; } ASTNode onlyNode=(ASTNode)elseBody.get(0); boolean check = checkStmt(onlyNode,node); if(!check){ return false; } //breaking is possible ASTCondition cond = node.get_Condition(); //flip cond.flip(); newIfNode = new ASTIfNode(((ASTLabeledNode)node).get_Label(),cond,elseBody); remainingBody = node.getIfBody(); return true; } private boolean checkStmt(ASTNode onlyNode,ASTIfElseNode node){ if(!(onlyNode instanceof ASTStatementSequenceNode)){ //only interested in StmtSeq nodes return false; } ASTStatementSequenceNode stmtNode=(ASTStatementSequenceNode)onlyNode; List<Object> statements = stmtNode.getStatements(); if(statements.size()!=1){ //need one stmt only return false; } AugmentedStmt as = (AugmentedStmt)statements.get(0); Stmt stmt = as.get_Stmt(); if(!(stmt instanceof DAbruptStmt)){ //interested in abrupt stmts only return false; } DAbruptStmt abStmt = (DAbruptStmt)stmt; if(!(abStmt.is_Break() || abStmt.is_Continue())){ //interested in breaks and continues only return false; } //make sure that the break is not that of the if //unliekly but good to check SETNodeLabel ifLabel = ((ASTLabeledNode)node).get_Label(); if (ifLabel!=null){ if(ifLabel.toString()!=null){ if(abStmt.is_Break()){ String breakLabel = abStmt.getLabel().toString(); if(breakLabel!=null){ if(breakLabel.compareTo(ifLabel.toString())==0){ //is a break of this label return false; } } } } } return true; } /* The purpose of this method is to replace the ASTIfElseNode given by the var nodeNumber with the new ASTIfNode and to add the remianing list of bodies after this ASTIfNode The new body is then returned; */ public List<Object> createNewBody(List<Object> oldSubBody, int nodeNumber){ if(newIfNode == null) return null; List<Object> newSubBody = new ArrayList<Object>(); if(oldSubBody.size()<= nodeNumber){ //something is wrong since the oldSubBody has lesser nodes than nodeNumber return null; } Iterator<Object> oldIt = oldSubBody.iterator(); int index=0; while(index!=nodeNumber){ newSubBody.add(oldIt.next()); index++; } //check to see that the next is an ASTIfElseNode ASTNode temp = (ASTNode)oldIt.next(); if(!(temp instanceof ASTIfElseNode)) return null; newSubBody.add(newIfNode); newSubBody.addAll(remainingBody); //copy any remaining nodes while(oldIt.hasNext()){ newSubBody.add(oldIt.next()); } return newSubBody; } }