/* 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 soot.*; import java.util.*; import soot.dava.internal.SET.*; import soot.dava.internal.AST.*; import soot.dava.toolkits.base.AST.analysis.DepthFirstAdapter; /* * CHANGE LOG: * Nomair A Naeem * 17th April 2006 * The class was implemented all wrong since the case methods were being overriddern and hence * the analysis was nto going into all children. * * changed this by overridding out methods instead of case * * * Class serves two purposes. * If you know there is a useless labeled block then its static methods can be invoked * as done by the ASTCleaner * * It can also be used to apply the UselessLabelFinder to all nodes of the AST * if that is done then make sure to set the ASTAnalysisModified */ public class UselessLabeledBlockRemover extends DepthFirstAdapter{ boolean changed=false; public UselessLabeledBlockRemover(){ } public UselessLabeledBlockRemover(boolean verbose){ super(verbose); } public void outASTMethodNode(ASTMethodNode node){ if(changed) G.v().ASTTransformations_modified = true; } public void inASTMethodNode(ASTMethodNode node){ changed=UselessLabelFinder.v().findAndKill(node); } /* public void caseASTSynchronizedBlockNode(ASTSynchronizedBlockNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTLabeledBlockNode (ASTLabeledBlockNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTUnconditionalLoopNode (ASTUnconditionalLoopNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTSwitchNode(ASTSwitchNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTIfNode(ASTIfNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTIfElseNode(ASTIfElseNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTWhileNode(ASTWhileNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTForLoopNode(ASTForLoopNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTDoWhileNode(ASTDoWhileNode node){ changed=UselessLabelFinder.v().findAndKill(node); } public void caseASTTryNode(ASTTryNode node){ changed=UselessLabelFinder.v().findAndKill(node); } */ public void outASTSynchronizedBlockNode(ASTSynchronizedBlockNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTLabeledBlockNode (ASTLabeledBlockNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTUnconditionalLoopNode (ASTUnconditionalLoopNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTSwitchNode(ASTSwitchNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTIfNode(ASTIfNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTIfElseNode(ASTIfElseNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTWhileNode(ASTWhileNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTForLoopNode(ASTForLoopNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTDoWhileNode(ASTDoWhileNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public void outASTTryNode(ASTTryNode node){ boolean modified=UselessLabelFinder.v().findAndKill(node); if(modified) changed=true; } public static void removeLabeledBlock(ASTNode node, ASTLabeledBlockNode labelBlock, int subBodyNumber, int nodeNumber){ if(!(node instanceof ASTIfElseNode)){ //these are the nodes which always have one subBody List<Object> subBodies = node.get_SubBodies(); if(subBodies.size()!=1){ //there is something wrong throw new RuntimeException("Please report this benchmark to the programmer"); } List<Object> onlySubBody = (List<Object>)subBodies.get(0); /* The onlySubBody contains the labeledBlockNode to be removed at location given by the nodeNumber variable */ List<Object> newBody = createNewSubBody(onlySubBody,nodeNumber,labelBlock); if(newBody==null){ //something went wrong return; } if(node instanceof ASTMethodNode){ ((ASTMethodNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else if(node instanceof ASTSynchronizedBlockNode){ ((ASTSynchronizedBlockNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else if(node instanceof ASTLabeledBlockNode){ ((ASTLabeledBlockNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else if(node instanceof ASTUnconditionalLoopNode){ ((ASTUnconditionalLoopNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else if(node instanceof ASTIfNode){ ((ASTIfNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else if(node instanceof ASTWhileNode){ ((ASTWhileNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else if(node instanceof ASTDoWhileNode){ ((ASTDoWhileNode)node).replaceBody(newBody); G.v().ASTTransformations_modified = true; //System.out.println("REMOVED LABEL"); } else { //there is no other case something is wrong if we get here return; } } else{//its an ASTIfElseNode //if its an ASIfElseNode then check which Subbody has the labeledBlock if(subBodyNumber!=0 && subBodyNumber!=1){ //something bad is happening dont do nothin //System.out.println("Error-------not modifying AST"); return; } List<Object> subBodies = node.get_SubBodies(); if(subBodies.size()!=2){ //there is something wrong throw new RuntimeException("Please report this benchmark to the programmer"); } List<Object> toModifySubBody = (List<Object>)subBodies.get(subBodyNumber); /* The toModifySubBody contains the labeledBlockNode to be removed at location given by the nodeNumber variable */ List<Object> newBody = createNewSubBody(toModifySubBody,nodeNumber,labelBlock); if(newBody==null){ //something went wrong return; } if(subBodyNumber==0){ //the if body was modified //System.out.println("REMOVED LABEL"); G.v().ASTTransformations_modified = true; ((ASTIfElseNode)node).replaceBody(newBody,(List<Object>)subBodies.get(1)); } else if(subBodyNumber==1){ //else body was modified //System.out.println("REMOVED LABEL"); G.v().ASTTransformations_modified = true; ((ASTIfElseNode)node).replaceBody((List<Object>)subBodies.get(0),newBody); } else{//realllly shouldnt come here //something bad is happening dont do nothin //System.out.println("Error-------not modifying AST"); return; } }//end of ASTIfElseNode } public static List<Object> createNewSubBody(List<Object> oldSubBody,int nodeNumber,ASTLabeledBlockNode labelBlock){ //create a new SubBody List<Object> newSubBody = new ArrayList<Object>(); //this is an iterator of ASTNodes Iterator<Object> it = oldSubBody.iterator(); //copy to newSubBody all nodes until you get to nodeNumber int index=0; while(index!=nodeNumber ){ if(!it.hasNext()){ return null; } newSubBody.add(it.next()); index++; } //at this point the iterator is pointing to the ASTLabeledBlock to be removed //just to make sure check this ASTNode toRemove = (ASTNode)it.next(); if(!(toRemove instanceof ASTLabeledBlockNode)){ //something is wrong return null; } else{ ASTLabeledBlockNode toRemoveNode = (ASTLabeledBlockNode)toRemove; //just double checking that this is a null label SETNodeLabel label = toRemoveNode.get_Label(); if(label.toString()!=null){ //something is wrong we cant remove a non null label return null; } //so this is the label to remove //removing a label means bringing all its bodies one step up the hierarchy List<Object> blocksSubBodies = toRemoveNode.get_SubBodies(); //we know this is a labeledBlock so it has only one subBody List onlySubBodyOfLabeledBlock = (List)blocksSubBodies.get(0); //all these subBodies should be added to the newSubbody newSubBody.addAll(onlySubBodyOfLabeledBlock); } //add any remaining nodes in the oldSubBody to the new one while(it.hasNext()){ newSubBody.add(it.next()); } //newSubBody is ready return it return newSubBody; } }