001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1999 Patrick Lam
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: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: package soot.grimp;
027:
028: import soot.options.*;
029:
030: import soot.*;
031: import soot.jimple.*;
032: import soot.jimple.internal.*;
033: import java.util.*;
034:
035: /** Implementation of the Body class for the Grimp IR. */
036: public class GrimpBody extends StmtBody {
037: /**
038: Construct an empty GrimpBody
039: **/
040:
041: GrimpBody(SootMethod m) {
042: super (m);
043: }
044:
045: public Object clone() {
046: Body b = Grimp.v().newBody(getMethod());
047: b.importBodyContentsFrom(this );
048: return b;
049: }
050:
051: /**
052: Constructs a GrimpBody from the given Body.
053: */
054:
055: GrimpBody(Body body) {
056: super (body.getMethod());
057:
058: if (Options.v().verbose())
059: G.v().out.println("[" + getMethod().getName()
060: + "] Constructing GrimpBody...");
061:
062: JimpleBody jBody = null;
063:
064: if (body instanceof JimpleBody)
065: jBody = (JimpleBody) body;
066: else
067: throw new RuntimeException(
068: "Can only construct GrimpBody's from JimpleBody's (for now)");
069:
070: Iterator<Local> localIt = jBody.getLocals().iterator();
071: while (localIt.hasNext())
072: getLocals().add(((localIt.next())));
073: // getLocals().add(((Local)(it.next())).clone());
074:
075: Iterator<Unit> it = jBody.getUnits().iterator();
076:
077: final HashMap<Stmt, Stmt> oldToNew = new HashMap<Stmt, Stmt>(
078: getUnits().size() * 2 + 1, 0.7f);
079: LinkedList updates = new LinkedList();
080:
081: /* we should Grimpify the Stmt's here... */
082: while (it.hasNext()) {
083: Stmt oldStmt = (Stmt) (it.next());
084: final StmtBox newStmtBox = (StmtBox) Grimp.v().newStmtBox(
085: null);
086: final StmtBox updateStmtBox = (StmtBox) Grimp.v()
087: .newStmtBox(null);
088:
089: /* we can't have a general StmtSwapper on Grimp.v() */
090: /* because we need to collect a list of updates */
091: oldStmt.apply(new AbstractStmtSwitch() {
092: public void caseAssignStmt(AssignStmt s) {
093: newStmtBox.setUnit(Grimp.v().newAssignStmt(s));
094: }
095:
096: public void caseIdentityStmt(IdentityStmt s) {
097: newStmtBox.setUnit(Grimp.v().newIdentityStmt(s));
098: }
099:
100: public void caseBreakpointStmt(BreakpointStmt s) {
101: newStmtBox.setUnit(Grimp.v().newBreakpointStmt(s));
102: }
103:
104: public void caseInvokeStmt(InvokeStmt s) {
105: newStmtBox.setUnit(Grimp.v().newInvokeStmt(s));
106: }
107:
108: public void caseEnterMonitorStmt(EnterMonitorStmt s) {
109: newStmtBox
110: .setUnit(Grimp.v().newEnterMonitorStmt(s));
111: }
112:
113: public void caseExitMonitorStmt(ExitMonitorStmt s) {
114: newStmtBox.setUnit(Grimp.v().newExitMonitorStmt(s));
115: }
116:
117: public void caseGotoStmt(GotoStmt s) {
118: newStmtBox.setUnit(Grimp.v().newGotoStmt(s));
119: updateStmtBox.setUnit(s);
120: }
121:
122: public void caseIfStmt(IfStmt s) {
123: newStmtBox.setUnit(Grimp.v().newIfStmt(s));
124: updateStmtBox.setUnit(s);
125: }
126:
127: public void caseLookupSwitchStmt(LookupSwitchStmt s) {
128: newStmtBox
129: .setUnit(Grimp.v().newLookupSwitchStmt(s));
130: updateStmtBox.setUnit(s);
131: }
132:
133: public void caseNopStmt(NopStmt s) {
134: newStmtBox.setUnit(Grimp.v().newNopStmt(s));
135: }
136:
137: public void caseReturnStmt(ReturnStmt s) {
138: newStmtBox.setUnit(Grimp.v().newReturnStmt(s));
139: }
140:
141: public void caseReturnVoidStmt(ReturnVoidStmt s) {
142: newStmtBox.setUnit(Grimp.v().newReturnVoidStmt(s));
143: }
144:
145: public void caseTableSwitchStmt(TableSwitchStmt s) {
146: newStmtBox.setUnit(Grimp.v().newTableSwitchStmt(s));
147: updateStmtBox.setUnit(s);
148: }
149:
150: public void caseThrowStmt(ThrowStmt s) {
151: newStmtBox.setUnit(Grimp.v().newThrowStmt(s));
152: }
153: });
154:
155: /* map old Expr's to new Expr's. */
156: Stmt newStmt = (Stmt) (newStmtBox.getUnit());
157: Iterator useBoxesIt;
158: useBoxesIt = newStmt.getUseBoxes().iterator();
159: while (useBoxesIt.hasNext()) {
160: ValueBox b = (ValueBox) (useBoxesIt.next());
161: b.setValue(Grimp.v().newExpr(b.getValue()));
162: }
163: useBoxesIt = newStmt.getDefBoxes().iterator();
164: while (useBoxesIt.hasNext()) {
165: ValueBox b = (ValueBox) (useBoxesIt.next());
166: b.setValue(Grimp.v().newExpr(b.getValue()));
167: }
168:
169: getUnits().add(newStmt);
170: oldToNew.put(oldStmt, newStmt);
171: if (updateStmtBox.getUnit() != null)
172: updates.add(updateStmtBox.getUnit());
173: }
174:
175: /* fixup stmt's which have had moved targets */
176: it = updates.iterator();
177: while (it.hasNext()) {
178: Stmt stmt = (Stmt) (it.next());
179:
180: stmt.apply(new AbstractStmtSwitch() {
181: public void caseGotoStmt(GotoStmt s) {
182: GotoStmt newStmt = (GotoStmt) (oldToNew.get(s));
183: newStmt
184: .setTarget(oldToNew
185: .get(newStmt.getTarget()));
186: }
187:
188: public void caseIfStmt(IfStmt s) {
189: IfStmt newStmt = (IfStmt) (oldToNew.get(s));
190: newStmt
191: .setTarget(oldToNew
192: .get(newStmt.getTarget()));
193: }
194:
195: public void caseLookupSwitchStmt(LookupSwitchStmt s) {
196: LookupSwitchStmt newStmt = (LookupSwitchStmt) (oldToNew
197: .get(s));
198: newStmt.setDefaultTarget((oldToNew.get(newStmt
199: .getDefaultTarget())));
200: Unit[] newTargList = new Unit[newStmt
201: .getTargetCount()];
202: for (int i = 0; i < newStmt.getTargetCount(); i++)
203: newTargList[i] = (oldToNew.get(newStmt
204: .getTarget(i)));
205: newStmt.setTargets(newTargList);
206: }
207:
208: public void caseTableSwitchStmt(TableSwitchStmt s) {
209: TableSwitchStmt newStmt = (TableSwitchStmt) (oldToNew
210: .get(s));
211: newStmt.setDefaultTarget((oldToNew.get(newStmt
212: .getDefaultTarget())));
213: int tc = newStmt.getHighIndex()
214: - newStmt.getLowIndex() + 1;
215: LinkedList<Unit> newTargList = new LinkedList<Unit>();
216: for (int i = 0; i < tc; i++)
217: newTargList.add(oldToNew.get(newStmt
218: .getTarget(i)));
219: newStmt.setTargets(newTargList);
220: }
221: });
222: }
223:
224: Iterator<Trap> trapIt = jBody.getTraps().iterator();
225: while (trapIt.hasNext()) {
226: Trap oldTrap = trapIt.next();
227: getTraps().add(
228: Grimp.v().newTrap(oldTrap.getException(),
229: (oldToNew.get(oldTrap.getBeginUnit())),
230: (oldToNew.get(oldTrap.getEndUnit())),
231: (oldToNew.get(oldTrap.getHandlerUnit()))));
232: }
233:
234: PackManager.v().getPack("gb").apply(this);
235: }
236: }
|