/* 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 18-FEB-2005 PATTERN ONE: label_1: while(cond1){ label_1: if(cond2){ while(cond1 && cond2){ Body 1 Body1 } } else{ break label_1 } } The important thing is that Body2 should contain an abrupt edge out of the while loop. If Body2 is just a break and nothing else the body2 in the transformed version is empty PATTERN TWO: label_1: while(true){ label_1: if(cond2){ while(cond2){ Body 1 Body1 } } else{ Body2 Body 2 } } TO MAKE CODE EFFECIENT BLOCK THE ANALYSIS TO GOING INTO STATEMENTS this is done by overriding the caseASTStatementSequenceNode */ public class StrengthenByIfElse{ /* We know this method is called when there is a loop node which has a body consisting entirely of one ASTIfElseNode */ public static List<ASTNode> getNewNode(ASTNode loopNode, ASTIfElseNode ifElseNode){ //make sure that elsebody has only a stmtseq node List<Object> elseBody = (ifElseNode).getElseBody(); if(elseBody.size()!=1){ //this is more than one we need one stmtSeq Node return null; } ASTNode tempNode = (ASTNode)elseBody.get(0); if(!(tempNode instanceof ASTStatementSequenceNode)){ //not a stmtSeq return null; } List<Object> statements = ((ASTStatementSequenceNode)tempNode).getStatements(); Iterator<Object> stmtIt = statements.iterator(); while(stmtIt.hasNext()){ AugmentedStmt as = (AugmentedStmt)stmtIt.next(); Stmt stmt = as.get_Stmt(); if(stmt instanceof DAbruptStmt){ //this is a abrupt stmt DAbruptStmt abStmt = (DAbruptStmt)stmt; if(!(abStmt.is_Break())){ //we need a break return null; } else{ if(stmtIt.hasNext()){ //a break should be the last stmt return null; } SETNodeLabel label = abStmt.getLabel(); String labelBroken=label.toString(); String loopLabel= ((ASTLabeledNode)loopNode).get_Label().toString(); if(labelBroken != null && loopLabel != null){//stmt breaks some label if(labelBroken.compareTo(loopLabel)==0){ //we have found a break breaking this label //make sure that if the orignal was an ASTWhileNode then there was //ONLY a break statement if(loopNode instanceof ASTWhileNode){ if(statements.size()!=1){ //more than 1 statement return null; } } //pattern matched ASTWhileNode newWhileNode = makeWhileNode(ifElseNode,loopNode); if(newWhileNode == null){ return null; } List<ASTNode> toReturn = new ArrayList<ASTNode>(); toReturn.add(newWhileNode); // Add the statementSequenceNode AFTER the whileNode except for the laststmt if(statements.size()!=1){ //size 1 means that the only stmt is a break stmt 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 matched }//non null labels }//end of break stmt }//stmt is an abrupt stmt else if (stmt instanceof ReturnStmt || stmt instanceof ReturnVoidStmt){ if(!(loopNode instanceof ASTUnconditionalLoopNode)){ //this pattern is only possible for while(true) return null; } if(stmtIt.hasNext()){ //returns should come in the end return null; } //pattern matched ASTWhileNode newWhileNode = makeWhileNode(ifElseNode,loopNode); if(newWhileNode == null){ return null; } List<ASTNode> toReturn = new ArrayList<ASTNode>(); toReturn.add(newWhileNode); // Add the statementSequenceNode AFTER the whileNode Iterator<Object> tempIt = statements.iterator(); List<Object> newStmts = new ArrayList<Object>(); while(tempIt.hasNext()){ Object tempStmt = tempIt.next(); newStmts.add(tempStmt); } toReturn.add(new ASTStatementSequenceNode(newStmts)); return toReturn; }//if stmt was a return stmt }//going through the stmts return null; }//end of method private static ASTWhileNode makeWhileNode(ASTIfElseNode ifElseNode, ASTNode loopNode){ ASTCondition outerCond = null; ASTCondition innerCond = ifElseNode.get_Condition(); ASTCondition newCond = null; if(loopNode instanceof ASTWhileNode){ outerCond=((ASTWhileNode)loopNode).get_Condition(); newCond = new ASTAndCondition(outerCond,innerCond); } else if (loopNode instanceof ASTUnconditionalLoopNode){ newCond = innerCond; } else{ //not dealing with the case of ASTDoWhileNode return null; } List<Object> loopBody = ifElseNode.getIfBody(); SETNodeLabel newLabel = ((ASTLabeledNode)loopNode).get_Label(); //make new ASTWhileNode return new ASTWhileNode(newLabel,newCond,loopBody); } }//end class