git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@13 379699f6-c40d-0410-875b-85095c16579estable
parent
5c4d86e1cb
commit
83e1e75c5d
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* EmptyBlock (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.flow; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is the structured block for an empty block. |
||||||
|
*/ |
||||||
|
public class EmptyBlock extends StructuredBlock { |
||||||
|
Instruction instr; |
||||||
|
|
||||||
|
SimpleInstruction(Instruction instr) { |
||||||
|
in = new Vector(); |
||||||
|
out = new Vector(); |
||||||
|
this.instr = instr; |
||||||
|
if (instr instanceof LocalVarOperator) { |
||||||
|
LocalVarOperator varOp = (LocalVarOperator) instr; |
||||||
|
if (varOp.isRead()) |
||||||
|
in.addElement(varOp.getLocalInfo()); |
||||||
|
else /* if (varOp.isWrite()) */ |
||||||
|
out.addElement(varOp.getLocalInfo()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
if (!(instr instanceof NopOperator)) { |
||||||
|
if (instr.getType() != MyType.tVoid) |
||||||
|
writer.print("push "); |
||||||
|
writer.println(instr.toString()+";"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
/* jode.flow.FinallyBlock (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.flow; |
||||||
|
|
||||||
|
/** |
||||||
|
* A FinallyBlock represents the instructions and try catch regions |
||||||
|
* that are generated by javac when you write a finally block. |
||||||
|
* |
||||||
|
* We detect such a block when we look at the exception table. There |
||||||
|
* is always an "any"-exception region (exception class is null) that |
||||||
|
* surrounds the first block. The synchronized-blocks create the same |
||||||
|
* region, so we have to take care of this. |
||||||
|
*/ |
||||||
|
|
||||||
|
public FinallyBlock extends StructuredBlock { |
||||||
|
} |
@ -0,0 +1,252 @@ |
|||||||
|
/* |
||||||
|
* FlowBlock (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.flow; |
||||||
|
|
||||||
|
/** |
||||||
|
* A flow block is the structure of which the flow graph consists. A |
||||||
|
* flow block contains structured code together with some conditional |
||||||
|
* or unconditional jumps to the head of other flow blocks. |
||||||
|
* |
||||||
|
* We do a T1/T2 analysis to combine all flow blocks to a single. If |
||||||
|
* the graph isn't reducible that doesn't work, but java can only |
||||||
|
* produce reducible flow graphs. |
||||||
|
*/ |
||||||
|
public class FlowBlock { |
||||||
|
|
||||||
|
/** |
||||||
|
* The starting address of this flow block. This is mainly used |
||||||
|
* to produce the source code in code order. |
||||||
|
*/ |
||||||
|
int addr; |
||||||
|
|
||||||
|
/** |
||||||
|
* The outermost structructed block in this flow block. |
||||||
|
*/ |
||||||
|
StructuredBlock block; |
||||||
|
|
||||||
|
/** |
||||||
|
* The last modified structured block. |
||||||
|
*/ |
||||||
|
StructuredBlock lastModified; |
||||||
|
|
||||||
|
/** |
||||||
|
* All jumps that this flow block contains. |
||||||
|
*/ |
||||||
|
Vector successors; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is a vector of flow blocks, which reference this block. |
||||||
|
* Only if this vector contains exactly one element, it can be |
||||||
|
* moved into the preceding flow block. |
||||||
|
*/ |
||||||
|
Vector predecessors; |
||||||
|
|
||||||
|
public void optimizeJumps(FlowBlock successor) { |
||||||
|
/* remove all unconditional jumps to the successor which have the |
||||||
|
* end of the block as normal successor. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* replace all conditional jumps to the successor, which are followed |
||||||
|
* by a block which has the end of the block as normal successor, |
||||||
|
* with "if (not condition) block". |
||||||
|
*/ |
||||||
|
|
||||||
|
/* if there are jumps in a while block, which has the end of |
||||||
|
* the block as normal successor or is followed by a |
||||||
|
* unconditional jump to successor, replace jumps with breaks |
||||||
|
* to the while block. If the condition of the while is true, |
||||||
|
* and the first instruction is converted to a conditional break |
||||||
|
* remove that break and use the condition in the while block. |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
/* if there are jumps in an switch block, which has as normal |
||||||
|
* successor the end of this FlowBlock, replace them with a |
||||||
|
* break to the switch block. |
||||||
|
* if there successor isn't the end of this FlowBlock, but |
||||||
|
* there are many, or the next rule could work (some more |
||||||
|
* heuristics?) and there is currently no flow to the end of |
||||||
|
* the switch block, replace all such successors with a break |
||||||
|
* and add a new unconditional jump after the switch block. */ |
||||||
|
|
||||||
|
/* if there are unconditional jumps in an if-then block, which |
||||||
|
* have as normal successor the end of the if-then block, and |
||||||
|
* the if-then block is followed by a single block, which has |
||||||
|
* as normal successor the end of the block, then replace |
||||||
|
* the if-then block with a if-then-else block and remove the |
||||||
|
* unconditional jumps. |
||||||
|
*/ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* Special cases: |
||||||
|
* |
||||||
|
* try-header |
||||||
|
* |- first instruction |
||||||
|
* | ... |
||||||
|
* | last instruction |
||||||
|
* |- optional jump (last+1) |
||||||
|
* | ... |
||||||
|
* `- catch block |
||||||
|
* |
||||||
|
* A try block may have many try-headers with different catch blocks |
||||||
|
* and there may be a finally block: |
||||||
|
* |
||||||
|
* try-header any |
||||||
|
* | try-header |
||||||
|
* |--|- first instruction |
||||||
|
* | | ... |
||||||
|
* | | every jump to outside is preceded by jsr finally |
||||||
|
* | | ... |
||||||
|
* | | last instruction |
||||||
|
* | |- optional jump after catch block (last+1) |
||||||
|
* | | ... | |
||||||
|
* | `- catch block | |
||||||
|
* | ... | |
||||||
|
* | ,-----------------' |
||||||
|
* | |-jump after all catch blocks |
||||||
|
* | v |
||||||
|
* | jsr finally -----------------, |
||||||
|
* |- jump after finally | |
||||||
|
* `- catch any (local_n) v |
||||||
|
* jsr finally ---------------->| |
||||||
|
* throw local_n; | |
||||||
|
* finally: <-----------------------' |
||||||
|
* astore_n |
||||||
|
* ... |
||||||
|
* return_n |
||||||
|
* |
||||||
|
* |
||||||
|
* flow-block |
||||||
|
* finally-block |
||||||
|
* ---> try-header |
||||||
|
* finally { |
||||||
|
* ---> first-finally-instruction |
||||||
|
* |
||||||
|
* A synchronized block uses a similar technique: |
||||||
|
* |
||||||
|
* local_x = monitor object; |
||||||
|
* monitorenter local_x |
||||||
|
* try-header any |
||||||
|
* |- syncronized block |
||||||
|
* | ... |
||||||
|
* | every jump to outside is preceded by jsr monexit ---, |
||||||
|
* | ... | |
||||||
|
* |- monitorexit local_x | |
||||||
|
* | jump after this block (without jsr monexit) | |
||||||
|
* `- catch any (local_n) | |
||||||
|
* monitorexit local_x | |
||||||
|
* throw local_n | |
||||||
|
* monexit: <-----------------------------------------------' |
||||||
|
* astore_n |
||||||
|
* monitorexit local_x |
||||||
|
* return_n |
||||||
|
*/ |
||||||
|
|
||||||
|
public boolean doT1 { |
||||||
|
/* search successor with smallest addr. */ |
||||||
|
|
||||||
|
/* check if this successor has only this block as predecessor. */ |
||||||
|
/* if not, return false. */ |
||||||
|
|
||||||
|
/* The switch case: if the last instruction in this block is a |
||||||
|
* switch block, and all jumps to successor lie in a single case, |
||||||
|
* or if all jumps |
||||||
|
* which doesn't have the end of the block as normal |
||||||
|
* successor, combine the successor with that block. But this |
||||||
|
* doesn't catch all cases. |
||||||
|
*/ |
||||||
|
|
||||||
|
optimizeJumps(successor); |
||||||
|
|
||||||
|
/* if the successor is the dummy return instruction, replace all |
||||||
|
* jumps with a return. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* If there are further jumps, put a do/while(0) block around |
||||||
|
* current block and replace every necessary jump with a break |
||||||
|
* to the do/while block. Then combine the block with a |
||||||
|
* sequential composition. */ |
||||||
|
} |
||||||
|
|
||||||
|
public boolean doT2() { |
||||||
|
/* If there are no jumps to the beginning of this flow block |
||||||
|
* or if this block has other predecessors which weren't |
||||||
|
* considered yet, return false. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* If there is only one jump to the beginning and it is the |
||||||
|
* last jump and (there is a do/while(0) block surrounding |
||||||
|
* everything but the last instruction, or the last |
||||||
|
* instruction is a increase/decrease statement), replace the |
||||||
|
* do/while(0) with a for(;;last_instr) resp. create a new one |
||||||
|
* and replace breaks to do/while with continue. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
/* Otherwise: */ |
||||||
|
optimizeJumps(this); |
||||||
|
|
||||||
|
/* create a new while(true) block. |
||||||
|
*/ |
||||||
|
} |
||||||
|
|
||||||
|
/* if there are further jumps to this, replace every jump with a |
||||||
|
* continue to while block and return true. |
||||||
|
*/ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* A structured block describes a structured program. There may be a |
||||||
|
* Jump after a block (even after a inner structured block), but the |
||||||
|
* goal is, to remove all such jumps and make a single flow block.<p> |
||||||
|
* |
||||||
|
* There are following types of structured blocks: <ul> |
||||||
|
* <li>if-then-(else)-block (IfThenElseBlock)</li> |
||||||
|
* <li>(do)-while/for-block (LoopBlock) |
||||||
|
* <li>switch-block (SwitchBlock) |
||||||
|
* <li>try-catch-finally-block (TryBlock) |
||||||
|
* <li>A block consisting of sub blocks (SequentialBlock) |
||||||
|
* </ul> |
||||||
|
*/ |
||||||
|
public class StructuredBlock { |
||||||
|
/** The surrounding block, or null if this is the outermost block in a |
||||||
|
* flow block. |
||||||
|
*/ |
||||||
|
StructuredBlock parent; |
||||||
|
|
||||||
|
/** The flow block to which this structured block belongs. |
||||||
|
*/ |
||||||
|
FlowBlock flow; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public class ConditionalJump extends Jump { |
||||||
|
Expression condition; |
||||||
|
StructuredBlock prev; |
||||||
|
FlowBlock parent; |
||||||
|
FlowBlock jump, nojump; |
||||||
|
} |
||||||
|
|
||||||
|
public class UnconditionalJump extends Jump { |
||||||
|
StructuredBlock prev; |
||||||
|
FlowBlock parent; |
||||||
|
FlowBlock jump; |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* InstructionBlock (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
*/ |
||||||
|
package jode.flow; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is the structured block for atomic instructions. |
||||||
|
*/ |
||||||
|
public class InstructionBlock extends StructuredBlock { |
||||||
|
Instruction instr; |
||||||
|
|
||||||
|
InstructionBlock(Instruction instr) { |
||||||
|
in = new Vector(); |
||||||
|
out = new Vector(); |
||||||
|
this.instr = instr; |
||||||
|
if (instr instanceof LocalVarOperator) { |
||||||
|
LocalVarOperator varOp = (LocalVarOperator) instr; |
||||||
|
if (varOp.isRead()) |
||||||
|
in.addElement(varOp.getLocalInfo()); |
||||||
|
else /* if (varOp.isWrite()) */ |
||||||
|
out.addElement(varOp.getLocalInfo()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException |
||||||
|
{ |
||||||
|
writer.println("/* empty */"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
/* jode.flow.RawTryCatchBlock (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.flow; |
||||||
|
|
||||||
|
/** |
||||||
|
* A RawTryCatchBlock is created for each exception in the |
||||||
|
* ExceptionHandlers-Attribute. <p> |
||||||
|
* |
||||||
|
* For each catch block (there may be more than one catch block |
||||||
|
* appending a single try block) and for each finally and each |
||||||
|
* synchronized block such a RawTryCatchBlock is created. The |
||||||
|
* finally/synchronized-blocks have a null exception type so that they |
||||||
|
* are easily distinguishable from the catch blocks. <p> |
||||||
|
* |
||||||
|
* A RawTryCatchBlock is an intermediate representation that gets |
||||||
|
* converted later to a CatchBlock, a FinallyBlock or a |
||||||
|
* SynchronizedBlock (after the body is parsed). |
||||||
|
* |
||||||
|
* @date 1998/09/16 |
||||||
|
* @author Jochen Hoenicke |
||||||
|
* @see CatchBlock |
||||||
|
* @see FinallyBlock |
||||||
|
* @see SynchronizedBlock |
||||||
|
*/ |
||||||
|
|
||||||
|
public RawTryCatchBlock extends StructuredBlock { |
||||||
|
|
||||||
|
/** |
||||||
|
* An unconditional jump to the EndBlock. |
||||||
|
*/ |
||||||
|
Jump EndBlock; |
||||||
|
|
||||||
|
/** |
||||||
|
* An unconditional jump to the CatchBlock. |
||||||
|
*/ |
||||||
|
Jump CatchBlock; |
||||||
|
|
||||||
|
/** |
||||||
|
* The type of the exception that is catched. This is null for a |
||||||
|
* synchronized/finally block |
||||||
|
*/ |
||||||
|
Type type; |
||||||
|
} |
@ -0,0 +1,174 @@ |
|||||||
|
/* |
||||||
|
* StructuredBlock (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.flow; |
||||||
|
|
||||||
|
/** |
||||||
|
* A structured block is the building block of the source programm. |
||||||
|
* For every program construct like if, while, try, or blocks there is |
||||||
|
* a corresponding structured block. |
||||||
|
* |
||||||
|
* Some of these Block are only intermediate representation, that get |
||||||
|
* converted to another block later. |
||||||
|
* |
||||||
|
* Every block has to handle the local variables that it contains. |
||||||
|
* This is done by the in/out vectors and the local variable structure |
||||||
|
* themself. Every local variable used in this structured block is |
||||||
|
* either in or out. |
||||||
|
* |
||||||
|
* There are following types of structured blocks: |
||||||
|
* <ul> |
||||||
|
* <li>if-then-(else)-block (IfThenElseBlock) |
||||||
|
* <li>(do)-while/for-block (LoopBlock) |
||||||
|
* <li>switch-block (SwitchBlock) |
||||||
|
* <li>try-catch-block (CatchBlock) |
||||||
|
* <li>try-finally-block (FinallyBlock) |
||||||
|
* <li>synchronized-block (SynchronizedBlock) |
||||||
|
* <li>one-instruction (InstructionBlock) |
||||||
|
* <li>empty-block (EmptyBlock) |
||||||
|
* <li>multi-blocks-block (SequentialBlock) |
||||||
|
* </ul> |
||||||
|
*/ |
||||||
|
|
||||||
|
public abstract class StructuredBlock { |
||||||
|
/* Invariants: |
||||||
|
* in.intersection(out) = empty |
||||||
|
* outer != null => flowblock = outer.flowblock |
||||||
|
* outer == null => flowblock.block = this |
||||||
|
* jump == null => outer != null |
||||||
|
* either getNextBlock() != null |
||||||
|
* or getNextFlowBlock() != null or outer == null |
||||||
|
* either outer.getNextBlock(this) != null |
||||||
|
* or outer.getNextFlowBlock(this) != null |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* The in locals. This are the locals, which are used in this |
||||||
|
* block and whose values may be the result of a assignment |
||||||
|
* outside of the whole flow block. That means, that there is a |
||||||
|
* path from the start of the current flow block, on which the |
||||||
|
* local variable is never assigned |
||||||
|
*/ |
||||||
|
Vector in; |
||||||
|
|
||||||
|
/** |
||||||
|
* The out locals. This are the locals, which must be overwritten |
||||||
|
* until the end of this block. That means, that all paths form |
||||||
|
* the start of the current flow block to the end of this |
||||||
|
* structured block contain a (unconditional) assignment to this |
||||||
|
* local |
||||||
|
*/ |
||||||
|
Vector out; |
||||||
|
|
||||||
|
/** |
||||||
|
* The surrounding structured block. If this is the outermost |
||||||
|
* block in a flow block, outer is null. |
||||||
|
*/ |
||||||
|
StructuredBlock outer; |
||||||
|
|
||||||
|
/** |
||||||
|
* The flow block in which this structured block lies. |
||||||
|
*/ |
||||||
|
FlowBlock flowblock; |
||||||
|
|
||||||
|
/** |
||||||
|
* The jump that follows on this block, or null if there is no |
||||||
|
* jump, but the control flows normal (only allowed if |
||||||
|
* getNextBlock != null). |
||||||
|
*/ |
||||||
|
Jump jump; |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the block where the control will normally flow to, when |
||||||
|
* this block is finished (ignoring the jump after this block). |
||||||
|
*/ |
||||||
|
StructuredBlock getNextBlock() { |
||||||
|
if (outer != null) |
||||||
|
outer.getNextBlock(this); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the flow block where the control will normally flow to, |
||||||
|
* when this block is finished (ignoring the jump after this |
||||||
|
* block). |
||||||
|
* @return null, if the control flows into a non empty structured |
||||||
|
* block or if this is the outermost block. |
||||||
|
*/ |
||||||
|
FlowBlock getNextFlowBlock() { |
||||||
|
if (outer != null) |
||||||
|
outer.getNextFlowBlock(this); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if the jump to the outside has correct monitorexit and |
||||||
|
* jsr instructions attached. |
||||||
|
* @return null, if everything is okay, and a diagnostic message that |
||||||
|
* should be put in a comment otherwise. |
||||||
|
*/ |
||||||
|
String checkJump(Jump jump) { |
||||||
|
if (outer != null) |
||||||
|
return outer.checkJump(jump); |
||||||
|
else if (jump.hasAttachments()) |
||||||
|
return "Unknown attachments: "+jump.describeAttachments() |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the block where the control will normally flow to, when |
||||||
|
* the given sub block is finished (<em>not</em> ignoring the jump |
||||||
|
* after this block). (This is overwritten by SequentialBlock and |
||||||
|
* SwitchBlock). If this isn't called with a direct sub block, |
||||||
|
* the behaviour is undefined, so take care. |
||||||
|
* @return null, if the control flows to another FlowBlock. */ |
||||||
|
StructuredBlock getNextBlock(StructuredBlock subBlock) { |
||||||
|
if (jump != null) |
||||||
|
return null; |
||||||
|
return getNextBlock(); |
||||||
|
} |
||||||
|
|
||||||
|
FlowBlock getNextFlowBlock(StructuredBlock subBlock) { |
||||||
|
if (jump != null) |
||||||
|
return jump; |
||||||
|
return getNextFlowBlock(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Replaces the given sub block with a new block. |
||||||
|
* @param oldBlock the old sub block. |
||||||
|
* @param newBlock the new sub block. |
||||||
|
* @return false, if oldBlock wasn't a direct sub block. |
||||||
|
*/ |
||||||
|
boolean replaceSubBlock(StructuredBlock oldBlock, |
||||||
|
StructuredBlock newBlock) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Print the source code for this structured block. This may be |
||||||
|
* called only once, because it remembers which local variables |
||||||
|
* were declared. |
||||||
|
*/ |
||||||
|
public abstract void dumpSource(TabbedPrintWriter writer) |
||||||
|
throws java.io.IOException; |
||||||
|
} |
Loading…
Reference in new issue