001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2005 Nomair A. Naeem
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package soot.dava.toolkits.base.AST.transformations;
021:
022: import java.util.*;
023: import soot.jimple.*;
024: import soot.dava.internal.SET.*;
025: import soot.dava.internal.AST.*;
026: import soot.dava.internal.asg.*;
027: import soot.dava.internal.javaRep.*;
028:
029: public class StrengthenByIf {
030: /*
031: We know this method is called when there is a while node which has a body
032: consisting entirely of one ASTIfNode
033: */
034: public static List<ASTNode> getNewNode(ASTNode loopNode,
035: ASTIfNode ifNode) {
036: List<Object> ifBody = ifNode.getIfBody();
037: String label = isItOnlyBreak(ifBody);
038: if (label != null) {
039: //only one break statement and it is breaking some label
040:
041: //make sure its breaking the label on the loop
042: if (((ASTLabeledNode) loopNode).get_Label().toString() != null) {
043:
044: if (((ASTLabeledNode) loopNode).get_Label().toString()
045: .compareTo(label) == 0) {
046: //the if has a single break breaking the loop
047: //pattern 1 matched
048:
049: if (loopNode instanceof ASTWhileNode) {
050: ASTCondition outerCond = ((ASTWhileNode) loopNode)
051: .get_Condition();
052: //flip the inner condition
053: ASTCondition innerCond = ifNode.get_Condition();
054: innerCond.flip();
055: //aggregate the two conditions
056: ASTCondition newCond = new ASTAndCondition(
057: outerCond, innerCond);
058: //make empty body
059: List<Object> newWhileBody = new ArrayList<Object>();
060: //SETNodeLabel newLabel = ((ASTWhileNode)loopNode).get_Label();
061:
062: // dont need any label name since the body of the while is empty
063: SETNodeLabel newLabel = new SETNodeLabel();
064:
065: //make new ASTWhileNode
066: List<ASTNode> toReturn = new ArrayList<ASTNode>();
067: toReturn.add(new ASTWhileNode(newLabel,
068: newCond, newWhileBody));
069: return toReturn;
070:
071: } else if (loopNode instanceof ASTDoWhileNode) {
072: /*
073: What to do when the ASTDoWhileNode only has one
074: body which is a break of the whileNode???
075: */
076: return null;
077: } else if (loopNode instanceof ASTUnconditionalLoopNode) {
078: /*
079: An UnconditionalLoopNode has a single If Condition
080: which breaks the loop
081: In this case
082: Create an ASTWhileLoop Node with the flipped Condition
083: of the If statement
084: */
085:
086: //flip the inner condition
087: ASTCondition innerCond = ifNode.get_Condition();
088: innerCond.flip();
089:
090: //make empty body
091: List<Object> newWhileBody = new ArrayList<Object>();
092: //SETNodeLabel newLabel = ((ASTUnconditionalLoopNode)loopNode).get_Label();
093:
094: // dont need any label name since the body of the while is empty
095: SETNodeLabel newLabel = new SETNodeLabel();
096:
097: //make new ASTWhileNode
098: List<ASTNode> toReturn = new ArrayList<ASTNode>();
099: toReturn.add(new ASTWhileNode(newLabel,
100: innerCond, newWhileBody));
101: return toReturn;
102: }
103: }//if the labels match
104: }
105: }//the first Pattern was a match
106: else if (loopNode instanceof ASTUnconditionalLoopNode
107: && ifBody.size() == 1) {
108: //try the UnconditionalLoopNode pattern
109:
110: //we need one stmtSeq Node
111: ASTNode tempNode = (ASTNode) ifBody.get(0);
112: if (tempNode instanceof ASTStatementSequenceNode) {
113: //a stmtSeq
114: List<Object> statements = ((ASTStatementSequenceNode) tempNode)
115: .getStatements();
116: Iterator<Object> stIt = statements.iterator();
117: while (stIt.hasNext()) {
118: AugmentedStmt as = (AugmentedStmt) stIt.next();
119: Stmt stmt = as.get_Stmt();
120: if (stmt instanceof DAbruptStmt
121: && !(stIt.hasNext())) {
122: //this is an abrupt stmt and the last stmt
123: DAbruptStmt abStmt = (DAbruptStmt) stmt;
124: if (abStmt.is_Break()) {
125: //last statement and that too a break
126: String loopLabel = ((ASTLabeledNode) loopNode)
127: .get_Label().toString();
128: String breakLabel = abStmt.getLabel()
129: .toString();
130: if (loopLabel != null && breakLabel != null) {
131: if (loopLabel.compareTo(breakLabel) == 0) {
132:
133: //pattern matched
134: //flip the inner condition
135: ASTCondition innerCond = ifNode
136: .get_Condition();
137: innerCond.flip();
138:
139: //make empty body
140: List<Object> newWhileBody = new ArrayList<Object>();
141: SETNodeLabel newLabel = ((ASTUnconditionalLoopNode) loopNode)
142: .get_Label();
143:
144: //make new ASTWhileNode
145: List<ASTNode> toReturn = new ArrayList<ASTNode>();
146: toReturn.add(new ASTWhileNode(
147: newLabel, innerCond,
148: newWhileBody));
149:
150: // Add the statementSequenceNode AFTER the whileNode except for the laststmt
151: Iterator<Object> tempIt = statements
152: .iterator();
153: List<Object> newStmts = new ArrayList<Object>();
154: while (tempIt.hasNext()) {
155: Object tempStmt = tempIt.next();
156: if (tempIt.hasNext()) {
157: newStmts.add(tempStmt);
158: }
159: }
160: toReturn
161: .add(new ASTStatementSequenceNode(
162: newStmts));
163: return toReturn;
164: }//labels are the same
165: }//labels are non null
166: }//is a break stmt
167: } else if (stmt instanceof ReturnStmt
168: || stmt instanceof ReturnVoidStmt) {
169: if (!(stIt.hasNext())) {
170: //return obj/return;
171: //flip cond
172: ASTCondition innerCond = ifNode
173: .get_Condition();
174: innerCond.flip();
175:
176: //make empty body
177: List<Object> newWhileBody = new ArrayList<Object>();
178: //SETNodeLabel newLabel = ((ASTUnconditionalLoopNode)loopNode).get_Label();
179:
180: // dont need any label name since the body of the while is empty
181: SETNodeLabel newLabel = new SETNodeLabel();
182:
183: //make new ASTWhileNode
184: List<ASTNode> toReturn = new ArrayList<ASTNode>();
185: toReturn.add(new ASTWhileNode(newLabel,
186: innerCond, newWhileBody));
187:
188: // Add the statementSequenceNode AFTER the whileNode except for the laststmt
189: Iterator<Object> tempIt = statements
190: .iterator();
191: List<Object> newStmts = new ArrayList<Object>();
192: while (tempIt.hasNext()) {
193: newStmts.add(tempIt.next());
194: }
195: toReturn.add(new ASTStatementSequenceNode(
196: newStmts));
197: return toReturn;
198: }
199: }
200: }//end of going through statements
201: }//end of stmtSEq node
202: }//end of else if
203: return null;
204: }//end of method
205:
206: /*
207: Given a body of a node the method checks for the following:
208: 1, the body has only one node
209: 2, the node is a statementSequenceNode
210: 3, There is only one statement in the stmt seq node
211: 4, the stmt is a break stmt
212:
213: If the conditions are true the label of the break stmt is returned
214: otherwise null is returned
215: */
216: private static String isItOnlyBreak(List<Object> body) {
217: if (body.size() != 1) {
218: //this is more than one we need one stmtSeq Node
219: return null;
220: }
221: ASTNode tempNode = (ASTNode) body.get(0);
222: if (!(tempNode instanceof ASTStatementSequenceNode)) {
223: //not a stmtSeq
224: return null;
225: }
226:
227: List<Object> statements = ((ASTStatementSequenceNode) tempNode)
228: .getStatements();
229: if (statements.size() != 1) {
230: //we need one break
231: return null;
232: }
233: AugmentedStmt as = (AugmentedStmt) statements.get(0);
234: Stmt stmt = as.get_Stmt();
235: if (!(stmt instanceof DAbruptStmt)) {
236: //this is not a break stmt
237: return null;
238: }
239: DAbruptStmt abStmt = (DAbruptStmt) stmt;
240: if (!(abStmt.is_Break())) {
241: //we need a break
242: return null;
243: }
244: return abStmt.getLabel().toString();
245: }
246: }
|