001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1999-2000 Patrice Pominville, Raja Vallee-Rai
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.toolkits.graph;
027:
028: import soot.util.*;
029: import java.util.*;
030: import soot.*;
031: import soot.baf.*;
032:
033: /**
034: * Represents BasicBlocks that partition
035: * a method body. It is implemented as view on an
036: * underlying Body instance; as a consequence, changes made on a Block
037: * will be automatically reflected in its enclosing method body. Blocks
038: * also exist in the context of a BlockGraph, a CFG for a method where
039: * Block instances are the nodes of the graph. Hence, a Block can be queried
040: * for its successors and predecessors Blocks, as found in this graph.
041: */
042: public class Block {
043: private Unit mHead, mTail;
044: private final Body mBody;
045: private List mPreds, mSuccessors;
046: private int mBlockLength = 0, mIndexInMethod = 0;
047:
048: /**
049: * Constructs a Block in the context of a BlockGraph, and enclosing Body instances.
050: *
051: *
052: * @param aHead The first unit ir this Block.
053: * @param aTail The last unit in this Block.
054: * @param aBody The Block's enclosing Body instance.
055: * @param aIndexInMethod The index of this Block in the list of
056: * Blocks that partition it's enclosing Body instance.
057: * @param aBlockLength The number of units that makeup this block.
058: * @param aBlockGraph The Graph of Blocks in which this block lives.
059: *
060: * @see Body
061: * @see Chain
062: * @see BlockGraph
063: * @see Unit
064: * @see SootMethod
065: */
066: public Block(Unit aHead, Unit aTail, Body aBody,
067: int aIndexInMethod, int aBlockLength, BlockGraph aBlockGraph) {
068: mHead = aHead;
069: mTail = aTail;
070: mBody = aBody;
071: mIndexInMethod = aIndexInMethod;
072: mBlockLength = aBlockLength;
073: }
074:
075: /**
076: * Returns the Block's enclosing Body instance.
077: *
078: * @return The block's chain of instructions.
079: * @see soot.jimple.JimpleBody
080: * @see BafBody
081: * @see Body
082: */
083: public Body getBody() {
084: return mBody;
085: }
086:
087: /**
088: * Returns an iterator for the linear chain of Units that make up the block.
089: *
090: * @return An iterator that iterates over the block's units.
091: * @see Chain
092: * @see Unit
093: */
094: public Iterator iterator() {
095: if (mBody != null) {
096: Chain units = mBody.getUnits();
097: return units.iterator(mHead, mTail);
098: } else {
099: return null;
100: }
101: }
102:
103: /**
104: * Inserts a Unit before some other Unit in this block.
105: *
106: *
107: * @param toInsert A Unit to be inserted.
108: * @param point A Unit in the Block's body
109: * before which we wish to insert the Unit.
110: * @see Unit
111: * @see Chain
112: */
113: public void insertBefore(Unit toInsert, Unit point) {
114: if (point == mHead)
115: mHead = toInsert;
116:
117: Chain methodBody = mBody.getUnits();
118: methodBody.insertBefore(toInsert, point);
119: }
120:
121: /**
122: * Inserts a Unit after some other Unit in the Block.
123: *
124: * @param toInsert A Unit to be inserted.
125: * @param point A Unit in the Block after which we wish to
126: * insert the Unit.
127: * @see Unit
128: */
129: public void insertAfter(Unit toInsert, Unit point) {
130: if (point == mTail)
131: mTail = toInsert;
132:
133: Chain methodBody = mBody.getUnits();
134: methodBody.insertAfter(toInsert, point);
135: }
136:
137: /**
138: * Removes a Unit occuring before some other Unit in the Block.
139: *
140: * @param item A Unit to be remove from the Block's Unit Chain.
141: * @return True if the item could be found and removed.
142: *
143: */
144: public boolean remove(Unit item) {
145: Chain methodBody = mBody.getUnits();
146:
147: if (item == mHead)
148: mHead = (Unit) methodBody.getSuccOf(item);
149: else if (item == mTail)
150: mTail = (Unit) methodBody.getPredOf(item);
151:
152: return methodBody.remove(item);
153: }
154:
155: /**
156: * Returns the Unit occuring immediatly after some other Unit in the block.
157: *
158: * @param aItem The Unit from which we wish to get it's successor.
159: * @return The successor or null if <code>aItem</code> is the tail
160: * for this Block.
161: *
162: */
163: public Unit getSuccOf(Unit aItem) {
164: Chain methodBody = mBody.getUnits();
165: if (aItem != mTail)
166: return (Unit) methodBody.getSuccOf(aItem);
167: else
168: return null;
169: }
170:
171: /**
172: * Returns the Unit occuring immediatly before some other Unit in the block.
173: *
174: * @param aItem The Unit from which we wish to get it's predecessor.
175: * @return The predecessor or null if <code>aItem</code> is the head
176: * for this Block.
177: */
178: public Unit getPredOf(Unit aItem) {
179: Chain methodBody = mBody.getUnits();
180: if (aItem != mHead)
181: return (Unit) methodBody.getPredOf(aItem);
182: else
183: return null;
184: }
185:
186: /**
187: * Set the index of this Block in the list of Blocks that partition
188: * its enclosing Body instance.
189: *
190: * @param aIndexInMethod The index of this Block in the list of
191: * Blocks that partition it's enclosing
192: * Body instance.
193: **/
194: public void setIndexInMethod(int aIndexInMethod) {
195: mIndexInMethod = aIndexInMethod;
196: }
197:
198: /**
199: * Returns the index of this Block in the list of Blocks that partition it's
200: * enclosing Body instance.
201: * @return The index of the block in it's enclosing Body instance.
202: */
203: public int getIndexInMethod() {
204: return mIndexInMethod;
205: }
206:
207: /**
208: * Returns the first unit in this block.
209: * @return The first unit in this block.
210: */
211: public Unit getHead() {
212: return mHead;
213: }
214:
215: /**
216: * Returns the last unit in this block.
217: * @return The last unit in this block.
218: */
219: public Unit getTail() {
220: return mTail;
221: }
222:
223: /**
224: * Sets the list of Blocks that are predecessors of this block in it's enclosing
225: * BlockGraph instance.
226: * @param preds The a List of Blocks that precede this block.
227: *
228: * @see BlockGraph
229: */
230: public void setPreds(List preds) {
231: mPreds = preds;
232: return;
233: }
234:
235: /**
236: * Returns the List of Block that are predecessors to this block,
237: * @return A list of predecessor blocks.
238: * @see BlockGraph
239: */
240: public List getPreds() {
241: return mPreds;
242: }
243:
244: /**
245: * Sets the list of Blocks that are successors of this block in it's enclosing
246: * BlockGraph instance.
247: * @param succs The a List of Blocks that succede this block.
248: *
249: * @see BlockGraph
250: */
251: public void setSuccs(List succs) {
252: mSuccessors = succs;
253: }
254:
255: /**
256: * Returns the List of Blocks that are successors to this block,
257: * @return A list of successorblocks.
258: * @see BlockGraph
259: */
260: public List getSuccs() {
261: return mSuccessors;
262: }
263:
264: Map allMapToUnnamed = new AllMapTo("???");
265:
266: class AllMapTo extends AbstractMap {
267: Object dest;
268:
269: public AllMapTo(Object dest) {
270: this .dest = dest;
271: }
272:
273: public Object get(Object key) {
274: return dest;
275: }
276:
277: public Set entrySet() {
278: throw new UnsupportedOperationException();
279: }
280: }
281:
282: public String toShortString() {
283: return "Block #" + mIndexInMethod;
284: }
285:
286: public String toString() {
287: StringBuffer strBuf = new StringBuffer();
288:
289: // print out predecessors.
290:
291: strBuf.append("Block " + mIndexInMethod + ":"
292: + System.getProperty("line.separator"));
293: strBuf.append("[preds: ");
294: if (mPreds != null) {
295: Iterator it = mPreds.iterator();
296: while (it.hasNext()) {
297:
298: strBuf.append(((Block) it.next()).getIndexInMethod()
299: + " ");
300: }
301: }
302: strBuf.append("] [succs: ");
303: if (mSuccessors != null) {
304: Iterator it = mSuccessors.iterator();
305: while (it.hasNext()) {
306:
307: strBuf.append(((Block) it.next()).getIndexInMethod()
308: + " ");
309: }
310:
311: }
312:
313: strBuf.append("]" + System.getProperty("line.separator"));
314:
315: //strBuf.append(" block" + mIndexInMethod + ":" + System.getProperty("line.separator"));
316:
317: Chain methodUnits = mBody.getUnits();
318: Iterator basicBlockIt = methodUnits.iterator(mHead, mTail);
319:
320: if (basicBlockIt.hasNext()) {
321: Unit someUnit = (Unit) basicBlockIt.next();
322: strBuf.append(someUnit.toString() + ";"
323: + System.getProperty("line.separator"));
324: while (basicBlockIt.hasNext()) {
325: someUnit = (Unit) basicBlockIt.next();
326: if (someUnit == mTail)
327: break;
328: strBuf.append(someUnit.toString() + ";"
329: + System.getProperty("line.separator"));
330: }
331: someUnit = mTail;
332: if (mTail == null)
333: strBuf.append("error: null tail found; block length: "
334: + mBlockLength + ""
335: + System.getProperty("line.separator"));
336: else if (mHead != mTail)
337: strBuf.append(someUnit.toString() + ";"
338: + System.getProperty("line.separator"));
339:
340: }
341: // Or, it could be an empty block (e.g. Start or Stop Block) --NU
342: // else
343: // G.v().out.println("No basic blocks found; must be interface class.");
344:
345: return strBuf.toString();
346: }
347:
348: }
|