001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2005 Jennifer Lhotak
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.javaToJimple.toolkits;
021:
022: import soot.*;
023: import soot.jimple.*;
024: import java.util.*;
025:
026: public class CondTransformer extends BodyTransformer {
027: public CondTransformer(Singletons.Global g) {
028: }
029:
030: public static CondTransformer v() {
031: return G.v().soot_javaToJimple_toolkits_CondTransformer();
032: }
033:
034: private static final int SEQ_LENGTH = 6;
035: private Stmt[] stmtSeq = new Stmt[SEQ_LENGTH];
036: private boolean sameGoto = true;
037:
038: protected void internalTransform(Body b, String phaseName,
039: Map options) {
040:
041: //G.v().out.println("running cond and/or transformer");
042: boolean change = true;
043: /*
044: * the idea is to look for groups of statements of the form
045: * if cond goto L0
046: * if cond goto L0
047: * z0 = 1
048: * goto L1
049: * L0: z0 = 0
050: * L1: if z0 == 0 goto L2
051: * conseq
052: * L2: altern
053: *
054: * and transform to
055: * if cond goto L0
056: * if cond goto L0
057: * conseq
058: * L0: altern
059: *
060: */
061:
062: while (change) {
063: Iterator it = b.getUnits().iterator();
064: int pos = 0;
065: while (it.hasNext()) {
066: change = false;
067: Stmt s = (Stmt) it.next();
068: if (testStmtSeq(s, pos)) {
069: pos++;
070: }
071: if (pos == 6) {
072: // found seq now transform then continue
073: //G.v().out.println("found sequence will transform");
074: change = true;
075: break;
076: }
077: }
078: if (change) {
079: transformBody(b, (Stmt) it.next());
080: pos = 0;
081: stmtSeq = new Stmt[SEQ_LENGTH];
082: }
083: }
084: }
085:
086: private void transformBody(Body b, Stmt next) {
087: // change target of stmts 0 and 1 to target of stmt 5
088: // remove stmts 2, 3, 4, 5
089: Stmt newTarget = null;
090: Stmt oldTarget = null;
091: if (sameGoto) {
092: newTarget = ((IfStmt) stmtSeq[5]).getTarget();
093: } else {
094: newTarget = next;
095: oldTarget = ((IfStmt) stmtSeq[5]).getTarget();
096: }
097: ((IfStmt) stmtSeq[0]).setTarget(newTarget);
098: ((IfStmt) stmtSeq[1]).setTarget(newTarget);
099:
100: for (int i = 2; i <= 5; i++) {
101: b.getUnits().remove(stmtSeq[i]);
102: }
103: if (!sameGoto) {
104: b.getUnits().insertAfter(Jimple.v().newGotoStmt(oldTarget),
105: stmtSeq[1]);
106: }
107: }
108:
109: private boolean testStmtSeq(Stmt s, int pos) {
110: switch (pos) {
111: case 0: {
112: if (s instanceof IfStmt) {
113: stmtSeq[pos] = s;
114: return true;
115: }
116: break;
117: }
118: case 1: {
119: if (s instanceof IfStmt) {
120: if (sameTarget(stmtSeq[pos - 1], s)) {
121: stmtSeq[pos] = s;
122: return true;
123: }
124: }
125: break;
126: }
127: case 2: {
128: if (s instanceof AssignStmt) {
129: stmtSeq[pos] = s;
130: if ((((AssignStmt) s).getRightOp() instanceof IntConstant)
131: && (((IntConstant) ((AssignStmt) s)
132: .getRightOp())).value == 0) {
133: sameGoto = false;
134: }
135: return true;
136: }
137: break;
138: }
139: case 3: {
140: if (s instanceof GotoStmt) {
141: stmtSeq[pos] = s;
142: return true;
143: }
144: break;
145: }
146: case 4: {
147: if (s instanceof AssignStmt) {
148: if (isTarget(((IfStmt) stmtSeq[0]).getTarget(), s)
149: && sameLocal(stmtSeq[2], s)) {
150: stmtSeq[pos] = s;
151: return true;
152: }
153: }
154: break;
155: }
156: case 5: {
157: if (s instanceof IfStmt) {
158: if (isTarget(
159: (Stmt) ((GotoStmt) stmtSeq[3]).getTarget(), s)
160: && sameCondLocal(stmtSeq[4], s)
161: && (((IfStmt) s).getCondition() instanceof EqExpr)) {
162: stmtSeq[pos] = s;
163: return true;
164: } else if (isTarget((Stmt) ((GotoStmt) stmtSeq[3])
165: .getTarget(), s)
166: && sameCondLocal(stmtSeq[4], s)) {
167: stmtSeq[pos] = s;
168: sameGoto = false;
169: return true;
170: }
171: }
172: break;
173: }
174:
175: default: {
176: break;
177: }
178: }
179: return false;
180: }
181:
182: private boolean sameTarget(Stmt s1, Stmt s2) {
183: IfStmt is1 = (IfStmt) s1;
184: IfStmt is2 = (IfStmt) s2;
185: if (is1.getTarget().equals(is2.getTarget())) {
186: return true;
187: }
188: return false;
189: }
190:
191: private boolean isTarget(Stmt s1, Stmt s) {
192: if (s1.equals(s)) {
193: return true;
194: }
195: return false;
196: }
197:
198: private boolean sameLocal(Stmt s1, Stmt s2) {
199: AssignStmt as1 = (AssignStmt) s1;
200: AssignStmt as2 = (AssignStmt) s2;
201: if (as1.getLeftOp().equals(as2.getLeftOp())) {
202: return true;
203: }
204: return false;
205: }
206:
207: private boolean sameCondLocal(Stmt s1, Stmt s2) {
208: AssignStmt as1 = (AssignStmt) s1;
209: IfStmt is2 = (IfStmt) s2;
210: if (is2.getCondition() instanceof BinopExpr) {
211: BinopExpr bs2 = (BinopExpr) is2.getCondition();
212: if (as1.getLeftOp().equals(bs2.getOp1())) {
213: return true;
214: }
215: }
216: return false;
217: }
218: }
|