Try-Catch-Finally

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@59 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent d131840eec
commit 20ffd055c4
  1. 8
      jode/jode/flow/CaseBlock.java
  2. 15
      jode/jode/flow/CatchBlock.java
  3. 95
      jode/jode/flow/CatchFinallyBlock.java
  4. 3
      jode/jode/flow/ConditionalBlock.java
  5. 6
      jode/jode/flow/CreateForInitializer.java
  6. 458
      jode/jode/flow/FlowBlock.java
  7. 10
      jode/jode/flow/IfThenElseBlock.java
  8. 3
      jode/jode/flow/JsrBlock.java
  9. 64
      jode/jode/flow/LoopBlock.java
  10. 72
      jode/jode/flow/RawTryCatchBlock.java
  11. 2
      jode/jode/flow/RemoveEmpty.java
  12. 2
      jode/jode/flow/ReturnBlock.java
  13. 16
      jode/jode/flow/StructuredBlock.java
  14. 8
      jode/jode/flow/ThrowBlock.java

@ -81,11 +81,9 @@ public class CaseBlock extends StructuredBlock {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
if (subBlock != null) {
StructuredBlock[] result = { subBlock };
return result;
}
return new StructuredBlock[0];
return (subBlock != null)
? new StructuredBlock[] { subBlock }
: new StructuredBlock[0];
}
public void dumpInstruction(jode.TabbedPrintWriter writer)

@ -46,14 +46,18 @@ public class CatchBlock extends StructuredBlock {
*/
LocalInfo exceptionLocal;
public CatchBlock(RawTryCatchBlock rawBlock) {
exceptionType = rawBlock.type;
this.tryBlock = rawBlock.tryBlock;
tryBlock.outer = this;
public CatchBlock(Type type) {
exceptionType = type;
}
static int serialno=0;
public void setTryBlock(StructuredBlock tryBlock) {
this.tryBlock = tryBlock;
tryBlock.outer = this;
tryBlock.setFlowBlock(flowBlock);
}
/**
* Sets the catch block.
* @param catchBlock the catch block.
@ -123,8 +127,7 @@ public class CatchBlock extends StructuredBlock {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { tryBlock, catchBlock };
return result;
return new StructuredBlock[] { tryBlock, catchBlock };
}
/**

@ -0,0 +1,95 @@
/* CatchFinallyBlock Copyright (C) 1997-1998 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.flow;
/**
*
* @author Jochen Hoenicke
*/
public class CatchFinallyBlock extends CatchBlock {
StructuredBlock finallyBlock;
public CatchFinallyBlock() {
super(null);
}
public void setFinallyBlock(StructuredBlock fin) {
finallyBlock = fin;
fin.outer = this;
fin.setFlowBlock(flowBlock);
}
/**
* 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.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (tryBlock == oldBlock)
tryBlock = newBlock;
else if (finallyBlock == oldBlock)
finallyBlock = newBlock;
else
return false;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { tryBlock, finallyBlock };
}
/**
* Determines if there is a sub block, that flows through to the end
* of this block. If this returns true, you know that jump is null.
* @return true, if the jump may be safely changed.
*/
public boolean jumpMayBeChanged() {
return ( tryBlock.jump != null || tryBlock.jumpMayBeChanged())
&& (finallyBlock.jump != null || finallyBlock.jumpMayBeChanged());
}
public void dumpInstruction(jode.TabbedPrintWriter writer)
throws java.io.IOException {
/* avoid ugly nested tries */
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
writer.println("try {");
writer.tab();
}
tryBlock.dumpSource(writer);
writer.untab();
writer.println("} finally {");
writer.tab();
finallyBlock.dumpSource(writer);
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
writer.untab();
writer.println("}");
}
}
}

@ -49,8 +49,7 @@ public class ConditionalBlock extends InstructionContainer {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { trueBlock };
return result;
return new StructuredBlock[] { trueBlock };
}
/**

@ -19,6 +19,8 @@
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.StoreInstruction;
public class CreateForInitializer implements Transformation {
@ -42,6 +44,10 @@ public class CreateForInitializer implements Transformation {
initializer =
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction();
if (!(initializer instanceof Expression)
|| !( ((Expression)initializer).getOperator()
instanceof StoreInstruction))
return false;
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {

@ -19,10 +19,7 @@
package jode.flow;
import java.util.*;
import jode.TabbedPrintWriter;
import jode.Expression;
import jode.CodeAnalyzer;
import jode.Decompiler;
import jode.*;
/**
* A flow block is the structure of which the flow graph consists. A
@ -112,35 +109,11 @@ public class FlowBlock {
}
public int getNextAddr() {
return addr+length;
}
/**
* Create a Catch- resp. FinallyBlock (maybe even SynchronizedBlock)
* @param sequBlock a SequentialBlock whose first sub block is a
* RawTryCatchBlock.
*/
public StructuredBlock createCatchBlock(SequentialBlock sequBlock) {
RawTryCatchBlock tryBlock = (RawTryCatchBlock) sequBlock.subBlocks[0];
StructuredBlock catchBlock = sequBlock.subBlocks[1];
if (tryBlock.type != null) {
/*XXX crude hack */
catchBlock.replace(sequBlock, tryBlock);
CatchBlock newBlock = new CatchBlock(tryBlock);
newBlock.replace(catchBlock, catchBlock);
newBlock.setCatchBlock(catchBlock);
if (sequBlock.jump != null) {
if (newBlock.catchBlock.jump == null)
newBlock.catchBlock.moveJump(sequBlock.jump);
else
sequBlock.removeJump();
}
return newBlock;
} else {
/* XXX implement finally */
return sequBlock;
}
if (block instanceof RawTryCatchBlock)
return ((RawTryCatchBlock)block).getTryBlock()
.jump.destination.getNextAddr();
else
return addr+length;
}
/**
@ -659,16 +632,6 @@ public class FlowBlock {
while (!appendBlock.contains(jump.prev)) {
appendBlock = appendBlock.outer;
if (appendBlock instanceof SequentialBlock
&& appendBlock.getSubBlocks()[0]
instanceof RawTryCatchBlock) {
/* We leave the catch block of a raw-try-catch-block.
* We shall now create the Catch- resp. FinallyBlock.
*/
appendBlock =
createCatchBlock((SequentialBlock)appendBlock);
}
}
/* appendBlock can't be null now, because the
* outermost block contains every structured block.
@ -813,30 +776,94 @@ public class FlowBlock {
updateInOut(this, false);
while (lastModified != block) {
while (lastModified != block)
lastModified = lastModified.outer;
if (lastModified instanceof SequentialBlock
&& lastModified.getSubBlocks()[0]
instanceof RawTryCatchBlock) {
/* We leave the catch block of a raw-try-catch-block.
* We shall now create the Catch- resp. FinallyBlock.
*/
lastModified =
createCatchBlock((SequentialBlock)lastModified);
}
}
transformation:
do {
/* 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 to for.
*/
Jump onlyJump = null;
Enumeration enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == null || jump.destination != this)
continue;
if (onlyJump == null)
onlyJump = jump;
else {
onlyJump = null;
break;
}
}
if (onlyJump != null &&
onlyJump.prev instanceof InstructionBlock) {
InstructionBlock prev = (InstructionBlock) onlyJump.prev;
if (prev.outer != null && prev.outer.outer == null
&& prev.outer instanceof SequentialBlock
&& prev.outer.getSubBlocks()[0] instanceof LoopBlock) {
LoopBlock lb = (LoopBlock) prev.outer.getSubBlocks()[0];
if (lb.cond == lb.FALSE && lb.type == lb.DOWHILE) {
/* Replace the do/while(0) with a
* for(;;last_instr) and replace breaks to
* do/while with continue to for.
*/
lb.type = lb.FOR;
lb.cond = lb.TRUE;
lb.incr = prev.getInstruction();
lb.init = null;
lb.replaceBreakContinue();
lb.replace(prev.outer, prev);
prev.removeJump();
lastModified = lb;
break transformation;
}
}
StructuredBlock sb = prev;
while (sb.outer != null
&& sb.outer instanceof SequentialBlock
&& sb.outer.getSubBlocks()[1] == sb)
sb = sb.outer;
Instruction instr = prev.getInstruction();
Operator op;
if (instr instanceof Expression
&& ((op = ((Expression)instr).getOperator())
instanceof jode.StoreInstruction
|| op instanceof jode.IIncOperator)
&& sb.outer == null) {
/* The only jump is the jump of the last
* instruction prev */
LoopBlock forBlock =
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE);
forBlock.replace(sb, sb);
forBlock.setBody(sb);
prev.outer.getSubBlocks()[0].replace(prev.outer, null);
forBlock.incr = instr;
prev.removeJump();
lastModified = forBlock;
break transformation;
}
}
/* XXX condition for do/while(cond) blocks */
/* 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 to for.
*/
/* XXX implement above */
/* XXX condition for do/while(cond) blocks */
{
/* Otherwise: */
/* create a new while(true) block.
@ -864,7 +891,7 @@ public class FlowBlock {
/* if there are further jumps to this, replace every jump with a
* continue to while block and return true.
*/
Enumeration enum = successors.elements();
enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
@ -905,7 +932,7 @@ public class FlowBlock {
bodyBlock.removeJump();
lastModified = whileBlock;
}
} while (false);
/* remove ourself from the predecessor list.
*/
@ -934,19 +961,9 @@ public class FlowBlock {
if (jump == null || jump.destination != END_OF_METHOD)
continue;
while (!appendBlock.contains(jump.prev)) {
while (!appendBlock.contains(jump.prev))
appendBlock = appendBlock.outer;
if (appendBlock instanceof SequentialBlock
&& appendBlock.getSubBlocks()[0]
instanceof RawTryCatchBlock) {
/* We leave the catch block of a raw-try-catch-block.
* We shall now create the Catch- resp. FinallyBlock.
*/
appendBlock =
createCatchBlock((SequentialBlock)appendBlock);
}
}
/* appendBlock can't be null now, because the
* outermost block contains every structured block.
*/
@ -1007,12 +1024,13 @@ public class FlowBlock {
static Transformation[] exprTrafos = {
new RemoveEmpty(),
new CreateExpression(),
new CreatePostIncExpression(),
new CreatePrePostIncExpression(),
new CreateAssignExpression(),
new CreateNewConstructor(),
new CombineIfGotoExpressions(),
new CreateIfThenElseOperator(),
new CreateConstantArray(),
new CreateForInitializer(),
};
@ -1060,6 +1078,8 @@ public class FlowBlock {
* @param end the end of the address range.
*/
public boolean analyze(int start, int end) {
if (Decompiler.debugAnalyze)
System.err.println("analyze("+start+", "+end+")");
try {
jode.TabbedPrintWriter writer = null;
if (Decompiler.isFlowDebugging)
@ -1067,6 +1087,13 @@ public class FlowBlock {
boolean changed = false;
if (block instanceof RawTryCatchBlock) {
/* analyze the try and catch blocks separately
* and create a new CatchBlock afterwards.
*/
changed |= analyzeCatchBlock(start, end);
}
while (true) {
if (Decompiler.isFlowDebugging) {
@ -1101,6 +1128,9 @@ public class FlowBlock {
writer.untab();
}
if (Decompiler.debugAnalyze)
System.err.println("T2("+addr+","+(addr+length)
+") succeeded");
/* T2 transformation succeeded. This may
* make another T1 analysis in the previous
* block possible.
@ -1115,18 +1145,16 @@ public class FlowBlock {
/* the Block has no successor where t1 is applicable.
* Finish this analyzation.
*/
if (Decompiler.isFlowDebugging) {
writer.println("No more successors applicable: "
+ start + " - " + end + "; "
+ addr + " - " + (addr+length));
}
if (Decompiler.debugAnalyze)
System.err.println
("No more successors applicable: "
+ start + " - " + end + "; "
+ addr + " - " + (addr+length));
return changed;
} else {
/* Only do T1 transformation if the blocks are
* adjacent. */
if (succ.block instanceof SwitchBlock) {
/* analyze succ, the new region is the
* continous region of
* continuous region of
* [start,end) \cap \compl [addr, addr+length)
* where succ.addr lies in.
*/
@ -1137,8 +1165,23 @@ public class FlowBlock {
if (succ.analyzeSwitch(newStart, newEnd))
break;
} if ((succ.addr == addr+length
}
if (succ.block instanceof RawTryCatchBlock) {
/* analyze the try and catch blocks separately
* and create a new CatchBlock afterwards.
*/
int newStart = (succ.addr > addr)
? addr+length : start;
int newEnd = (succ.addr > addr)
? end : addr;
if (succ.analyzeCatchBlock(newStart, newEnd)) {
break;
}
}
if ((succ.addr == addr+length
|| succ.addr+succ.length == addr)
/* Only do T1 transformation if the blocks are
* adjacent. */
&& doT1(succ)) {
/* T1 transformation succeeded. */
changed = true;
@ -1150,19 +1193,36 @@ public class FlowBlock {
writer.untab();
}
break;
} else {
/* analyze succ, the new region is the
* continous region of
* [start,end) \cap \compl [addr, addr+length)
* where succ.addr lies in.
*/
int newStart = (succ.addr > addr)
? addr+length : start;
int newEnd = (succ.addr > addr)
? end : addr;
if (succ.analyze(newStart, newEnd))
break;
}
/* Check if all predecessors of succ
* lie in range [start,end). Otherwise
* we have no chance to combine succ
*/
Enumeration enum = succ.predecessors.elements();
while (enum.hasMoreElements()) {
int predAddr =
((FlowBlock)enum.nextElement()).addr;
if (predAddr < start || predAddr >= end) {
if (Decompiler.debugAnalyze)
System.err.println
("breaking analyze("
+ start + ", " + end + "); "
+ addr + " - " + (addr+length));
return changed;
}
}
/* analyze succ, the new region is the
* continuous region of
* [start,end) \cap \compl [addr, addr+length)
* where succ.addr lies in.
*/
int newStart = (succ.addr > addr)
? addr+length : start;
int newEnd = (succ.addr > addr)
? end : addr;
if (succ.analyze(newStart, newEnd))
break;
}
/* Try the next successor.
@ -1171,7 +1231,181 @@ public class FlowBlock {
}
}
} catch (java.io.IOException ioex) {
return false;
throw new AssertError(ioex.toString());
}
}
/**
* Create a Catch- resp. FinallyBlock (maybe even SynchronizedBlock).
* The root block MUST be a RawTryCatchBlock.
* @param start the start address
* @param end and the end address of FlowBlocks, we may use.
*/
public boolean analyzeCatchBlock(int start, int end) {
if (Decompiler.debugAnalyze)
System.err.println("analyzeCatch("+start+", "+end+")");
RawTryCatchBlock rawBlock = (RawTryCatchBlock) block;
FlowBlock tryFlow = rawBlock.tryBlock.jump.destination;
FlowBlock catchFlow = rawBlock.catchBlock.jump.destination;
boolean changed = false;
tryFlow.analyze(addr, catchFlow.addr);
catchFlow.analyze(catchFlow.addr, end);
updateInOut(tryFlow, true);
rawBlock.tryBlock.removeJump();
tryFlow.getBlock().replace(rawBlock.tryBlock, null);
mergeSuccessors(tryFlow);
length += tryFlow.length;
updateInOut(catchFlow, true);
rawBlock.catchBlock.removeJump();
catchFlow.block.replace(rawBlock.catchBlock, null);
mergeSuccessors(catchFlow);
length += catchFlow.length;
if (rawBlock.type != null) {
CatchBlock newBlock = new CatchBlock(rawBlock.type);
newBlock.replace(rawBlock, rawBlock);
newBlock.setTryBlock(rawBlock.tryBlock);
newBlock.setCatchBlock(rawBlock.catchBlock);
lastModified = newBlock;
changed = true;
} else if (catchFlow.block instanceof SequentialBlock) {
SequentialBlock catchBlock = null;
int type = 0;
try {
catchBlock = (SequentialBlock) catchFlow.block;
if (((Expression)((InstructionBlock)catchBlock.subBlocks[0])
.instr).getOperator() instanceof jode.MonitorExitOperator
&& ((ThrowBlock)catchBlock.subBlocks[1]).instr
instanceof jode.NopOperator)
/* This is a synchronized block */
type = 2;
else if
(((SequentialBlock)catchBlock.subBlocks[1]).subBlocks[0]
instanceof JsrBlock
&& ((LocalStoreOperator)
((Expression)
((InstructionBlock)catchBlock.subBlocks[0])
.instr).getOperator())
.matches((LocalLoadOperator)
((Expression)
((ThrowBlock)
((SequentialBlock)catchBlock.subBlocks[1]).
subBlocks[1])
.instr).getOperator()))
/* Wow that was complicated :-)
* But now we know that the catch block looks
* exactly like we exspected.
*/
type = 1;
} catch (ClassCastException ex) {
/* don't do transformations */
}
if (type == 2) {
/* This is a synchronized block */
throw new AssertError ("Synchronized not implemented yet");
} else if (type == 1) {
/* Finally block */
FlowBlock subRoutine =
((JsrBlock)catchBlock.subBlocks[1].getSubBlocks()[0])
.innerBlock.jump.destination;
subRoutine.analyzeSubRoutine(addr+length, end);
updateInOut(subRoutine, true);
length += subRoutine.length;
Enumeration enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump)enum.nextElement();
if (jump != null && jump.destination == subRoutine) {
if (jump.prev instanceof EmptyBlock
&& jump.prev.outer instanceof JsrBlock) {
/* XXX
* Could check much more here!
*/
StructuredBlock prevBlock = null;
StructuredBlock jsrBlock = jump.prev.outer;
if (jsrBlock.outer instanceof SequentialBlock) {
if (jsrBlock.outer.getSubBlocks()[1]
== jsrBlock) {
prevBlock =
jsrBlock.outer.getSubBlocks()[0];
prevBlock.replace(jsrBlock.outer,
jsrBlock.outer);
} else if (jsrBlock.outer.outer instanceof
SequentialBlock) {
prevBlock =
jsrBlock.outer.outer
.getSubBlocks()[0];
jsrBlock.outer.getSubBlocks()[1]
.replace(jsrBlock.outer,
jsrBlock.outer);
}
}
if (prevBlock != null) {
if (prevBlock.jump == null)
prevBlock.moveJump(jsrBlock.jump);
else
jsrBlock.removeJump();
} else {
EmptyBlock eb = new EmptyBlock();
eb.moveJump(jsrBlock.jump);
eb.replace(jsrBlock, jump.prev);
}
jump.prev.removeJump();
} else
throw new AssertError("wrong jsr");
}
}
CatchFinallyBlock newBlock = new CatchFinallyBlock();
newBlock.replace(rawBlock, rawBlock);
newBlock.setTryBlock(rawBlock.tryBlock);
newBlock.setFinallyBlock(subRoutine.block);
lastModified = newBlock;
changed = true;
}
}
checkConsistent();
if (Decompiler.debugAnalyze)
System.err.println("analyzeCatch("+start+", "+end+") "
+(changed?"succeeded":"failed")
+"; "+addr+","+(addr+length));
return changed;
}
public void analyzeSubRoutine(int start, int end) {
analyze(start, end);
/* throws ClassCastException if something isn't as exspected. */
SequentialBlock sequBlock = (SequentialBlock) block;
LocalStoreOperator store = (LocalStoreOperator)
((Expression)((InstructionBlock)sequBlock.subBlocks[0]).instr)
.getOperator();
while (sequBlock.subBlocks[1] instanceof SequentialBlock)
sequBlock = (SequentialBlock) sequBlock.subBlocks[1];
if (! ((RetBlock)sequBlock.subBlocks[1]).local
.equals(store.getLocalInfo()))
throw new AssertError("Ret doesn't match");
if (sequBlock.outer == null) {
new EmptyBlock().replace(sequBlock, sequBlock);
} else {
sequBlock.subBlocks[0].replace(sequBlock, sequBlock);
block.getSubBlocks()[1].replace(block, block);
}
}
@ -1260,17 +1494,21 @@ public class FlowBlock {
* Resolves the destinations of all jumps.
*/
public void resolveJumps(FlowBlock[] instr) {
if (block instanceof RawTryCatchBlock) {
((RawTryCatchBlock)block).getTryBlock()
.jump.destination.resolveJumps(instr);
}
Enumeration enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump != null) {
if (jump != null && jump.destination == null) {
if (jump.destAddr == -1)
jump.destination = END_OF_METHOD;
else
jump.destination = instr[jump.destAddr];
if (!jump.destination.predecessors.contains(this))
jump.destination.predecessors.addElement(this);
}
if (!jump.destination.predecessors.contains(this))
jump.destination.predecessors.addElement(this);
}
}
@ -1347,4 +1585,18 @@ public class FlowBlock {
public StructuredBlock getBlock() {
return block;
}
public String toString() {
try {
java.io.StringWriter strw = new java.io.StringWriter();
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(strw, " ");
writer.println(super.toString());
writer.tab();
dumpSource(writer);
return strw.toString();
} catch (java.io.IOException ex) {
return super.toString();
}
}
}

@ -126,13 +126,9 @@ public class IfThenElseBlock extends StructuredBlock {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
if (elseBlock == null) {
StructuredBlock[] result = { thenBlock };
return result;
} else {
StructuredBlock[] result = { thenBlock, elseBlock };
return result;
}
return (elseBlock == null)
? new StructuredBlock[] { thenBlock }
: new StructuredBlock[] { thenBlock, elseBlock };
}
/**

@ -60,8 +60,7 @@ public class JsrBlock extends StructuredBlock {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { innerBlock };
return result;
return new StructuredBlock[] { innerBlock };
}
public void dumpInstruction(jode.TabbedPrintWriter writer)

@ -47,6 +47,11 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
*/
Instruction incr;
/**
* True, if the initializer is a declaration.
*/
boolean isDeclaration;
/**
* The type of the loop. This must be one of DOWHILE, WHILE or FOR.
*/
@ -120,8 +125,28 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { bodyBlock };
return result;
return new StructuredBlock[] { bodyBlock };
}
public void dumpDeclaration(TabbedPrintWriter writer, LocalInfo local)
throws java.io.IOException
{
if (type == FOR && init != null
&& (outer == null || !outer.used.contains(local))
&& init instanceof Expression
&& ((Expression)init).getOperator() instanceof LocalStoreOperator
&& ((LocalStoreOperator) ((Expression)init).getOperator())
.getLocalInfo() == local.getLocalInfo()) {
isDeclaration = true;
} else
super.dumpDeclaration(writer, local);
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
isDeclaration = false;
super.dumpSource(writer);
}
public void dumpInstruction(TabbedPrintWriter writer)
@ -141,9 +166,16 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
writer.print("do");
break;
case FOR:
writer.print("for ("
+(init != null ? init.simplify().toString() : "")
+"; "+cond.simplify().toString()+"; "
writer.print("for (");
if (isDeclaration)
writer.print(((LocalStoreOperator)
((Expression)init).getOperator())
.getLocalInfo().getType().toString()
+ " " + init.simplify().toString());
else if (init != null)
writer.print(init.simplify().toString());
writer.print("; "+cond.simplify().toString()+"; "
+incr.simplify().toString()+")");
break;
}
@ -188,6 +220,28 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
mayChangeJump = false;
}
/**
* Replace all breaks to this block with a continue to this block.
*/
public void replaceBreakContinue() {
java.util.Stack todo = new java.util.Stack();
todo.push(this);
while (!todo.isEmpty()) {
StructuredBlock[] subs =
((StructuredBlock)todo.pop()).getSubBlocks();
for (int i=0; i<subs.length; i++) {
if (subs[i] instanceof BreakBlock) {
BreakBlock breakblk = (BreakBlock) subs[i];
if (breakblk.breaksBlock == this) {
new ContinueBlock(this, breakblk.label != null)
.replace(breakblk, null);
}
}
todo.push(subs[i]);
}
}
}
/**
* Determines if there is a sub block, that flows through to the end
* of this block. If this returns true, you know that jump is null.

@ -42,31 +42,40 @@ import jode.TabbedPrintWriter;
public class RawTryCatchBlock extends StructuredBlock {
int endAddr;
public RawTryCatchBlock(jode.Type type,
StructuredBlock tryBlock,
Jump endDest, Jump catchDest) {
this.type = type;
// endBlock = new EmptyBlock(endDest);
// endBlock.outer = this;
endAddr = endDest.destAddr;
catchBlock = new EmptyBlock(catchDest);
catchBlock.outer = this;
}
replace(tryBlock, tryBlock);
this.tryBlock = tryBlock;
tryBlock.outer = this;
public FlowBlock chainTo(FlowBlock flow) {
FlowBlock first = flow;
RawTryCatchBlock parent = null;
while (flow.getBlock() instanceof RawTryCatchBlock
&& (((RawTryCatchBlock) flow.getBlock()).getCatchAddr()
> this.getCatchAddr())) {
// endBlock.setFlowBlock(flowBlock);
// if (tryBlock instanceof RawTryCatchBlock
// && ((RawTryCatchBlock)tryBlock).endBlock.jump.destination
// == endDest.destination)
// endBlock.jump = null;
// else
// flowBlock.addSuccessor(endDest);
parent = (RawTryCatchBlock) flow.getBlock();
flow = parent.getTryBlock().jump.destination;
}
catchBlock.setFlowBlock(flowBlock);
flowBlock.addSuccessor(catchDest);
tryBlock = new EmptyBlock(new Jump(flow));
tryBlock.outer = this;
new FlowBlock(flow.code, flow.addr, 0, this);
if (parent == null) {
/* We are the outermost try block */
return flowBlock;
} else {
/* Chain into existing try block list */
parent.getTryBlock().jump.destination = flowBlock;
return first;
}
}
/**
@ -74,12 +83,6 @@ public class RawTryCatchBlock extends StructuredBlock {
*/
StructuredBlock tryBlock;
// /**
// * An empty block containing an unconditional jump to the EndBlock.
// * Or null if the try block is completely read.
// */
// StructuredBlock endBlock;
/**
* The catch block.
*/
@ -101,14 +104,6 @@ public class RawTryCatchBlock extends StructuredBlock {
StructuredBlock newBlock) {
if (tryBlock == oldBlock)
tryBlock = newBlock;
// if (tryBlock instanceof RawTryCatchBlock
// && ((RawTryCatchBlock)tryBlock).endBlock.jump.destination
// == endBlock.jump.destination) {
// endBlock.removeJump();
// }
// } else if (endBlock == oldBlock) {
// endBlock = newBlock;
else if (catchBlock == oldBlock)
catchBlock = newBlock;
else
@ -120,30 +115,15 @@ public class RawTryCatchBlock extends StructuredBlock {
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { tryBlock/*, endBlock*/, catchBlock };
return result;
return new StructuredBlock[] { tryBlock, catchBlock };
}
// /**
// * Determines if there is a sub block, that flows through to the end
// * of this block. If this returns true, you know that jump is null.
// * @return true, if the jump may be safely changed.
// */
// public boolean jumpMayBeChanged() {
// return ( tryBlock.jump != null || tryBlock.jumpMayBeChanged())
// && (catchBlock.jump != null || catchBlock.jumpMayBeChanged());
// }
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException {
writer.println("TRY "+(type != null ? type.toString() : "ALL"));
writer.tab();
tryBlock.dumpSource(writer);
writer.untab();
// writer.println("UNTIL");
// writer.tab();
// endBlock.dumpSource(writer);
// writer.untab();
writer.println("CATCH TO");
writer.tab();
catchBlock.dumpSource(writer);

@ -47,7 +47,7 @@ public class RemoveEmpty implements Transformation {
if (prev.jump != null)
return false;
instr = (Instruction) prev.getInstruction();
instr.setType(instr.getType().intersection(prevInstr.getType()));
instr.setType(prevInstr.getType());
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {

@ -39,7 +39,7 @@ public class ReturnBlock extends InstructionContainer {
* @return true if this block should be sorrounded by braces.
*/
public boolean needsBraces() {
return false;
return declare != null && !declare.isEmpty();
}
/**

@ -278,7 +278,7 @@ public abstract class StructuredBlock {
* @param jump The jump that should be moved, may be null.
*/
public void moveJump(Jump jump) {
removeJump();
removeJump();
this.jump = jump;
if (jump != null) {
jump.prev.jump = null;
@ -458,5 +458,19 @@ public abstract class StructuredBlock {
*/
public abstract void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException;
public String toString() {
try {
java.io.StringWriter strw = new java.io.StringWriter();
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(strw, " ");
writer.println(super.toString());
writer.tab();
dumpSource(writer);
return strw.toString();
} catch (java.io.IOException ex) {
return super.toString();
}
}
}

@ -29,6 +29,14 @@ public class ThrowBlock extends InstructionContainer {
super(instr);
}
/**
* Tells if this block needs braces when used in a if or while block.
* @return true if this block should be sorrounded by braces.
*/
public boolean needsBraces() {
return declare != null && !declare.isEmpty();
}
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException
{

Loading…
Cancel
Save