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. 17
      jode/jode/flow/CatchBlock.java
  3. 95
      jode/jode/flow/CatchFinallyBlock.java
  4. 3
      jode/jode/flow/ConditionalBlock.java
  5. 8
      jode/jode/flow/CreateForInitializer.java
  6. 478
      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. 74
      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. * Returns all sub block of this structured block.
*/ */
public StructuredBlock[] getSubBlocks() { public StructuredBlock[] getSubBlocks() {
if (subBlock != null) { return (subBlock != null)
StructuredBlock[] result = { subBlock }; ? new StructuredBlock[] { subBlock }
return result; : new StructuredBlock[0];
}
return new StructuredBlock[0];
} }
public void dumpInstruction(jode.TabbedPrintWriter writer) public void dumpInstruction(jode.TabbedPrintWriter writer)

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

@ -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. * Returns all sub block of this structured block.
*/ */
public StructuredBlock[] getSubBlocks() { public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { trueBlock }; return new StructuredBlock[] { trueBlock };
return result;
} }
/** /**

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

@ -19,10 +19,7 @@
package jode.flow; package jode.flow;
import java.util.*; import java.util.*;
import jode.TabbedPrintWriter; import jode.*;
import jode.Expression;
import jode.CodeAnalyzer;
import jode.Decompiler;
/** /**
* A flow block is the structure of which the flow graph consists. A * A flow block is the structure of which the flow graph consists. A
@ -112,37 +109,13 @@ public class FlowBlock {
} }
public int getNextAddr() { public int getNextAddr() {
return addr+length; if (block instanceof RawTryCatchBlock)
return ((RawTryCatchBlock)block).getTryBlock()
.jump.destination.getNextAddr();
else
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;
}
}
/** /**
* This method optimizes the jumps to successor. * This method optimizes the jumps to successor.
* @param successor The successing flow block * @param successor The successing flow block
@ -659,16 +632,6 @@ public class FlowBlock {
while (!appendBlock.contains(jump.prev)) { while (!appendBlock.contains(jump.prev)) {
appendBlock = appendBlock.outer; 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 /* appendBlock can't be null now, because the
* outermost block contains every structured block. * outermost block contains every structured block.
@ -813,32 +776,96 @@ public class FlowBlock {
updateInOut(this, false); updateInOut(this, false);
while (lastModified != block) { while (lastModified != block)
lastModified = lastModified.outer; 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);
}
}
/* If there is only one jump to the beginning and it is the transformation:
* last jump and (there is a do/while(0) block surrounding do {
* everything but the last instruction, or the last /* If there is only one jump to the beginning and it is the
* instruction is a increase/decrease statement), replace the * last jump and (there is a do/while(0) block surrounding
* do/while(0) with a for(;;last_instr) resp. create a new one * everything but the last instruction, or the last
* and replace breaks to do/while with continue to for. * instruction is a increase/decrease statement), replace the
*/ * do/while(0) with a for(;;last_instr) resp. create a new one
/* XXX implement above */ * and replace breaks to do/while with continue to for.
/* XXX condition for do/while(cond) blocks */ */
{
/* Otherwise: */ 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 */
/* Otherwise: */
/* create a new while(true) block. /* create a new while(true) block.
*/ */
StructuredBlock bodyBlock = block; StructuredBlock bodyBlock = block;
@ -853,18 +880,18 @@ public class FlowBlock {
LoopBlock whileBlock = LoopBlock whileBlock =
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE);
whileBlock.replace(bodyBlock, bodyBlock); whileBlock.replace(bodyBlock, bodyBlock);
whileBlock.setBody(bodyBlock); whileBlock.setBody(bodyBlock);
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
bodyBlock = optimizeJumps(this, bodyBlock); bodyBlock = optimizeJumps(this, bodyBlock);
/* if there are further jumps to this, replace every jump with a /* if there are further jumps to this, replace every jump with a
* continue to while block and return true. * continue to while block and return true.
*/ */
Enumeration enum = successors.elements(); enum = successors.elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement(); Jump jump = (Jump) enum.nextElement();
@ -897,7 +924,7 @@ public class FlowBlock {
(new BreakBlock(breakToBlock, breaklevel > 1)); (new BreakBlock(breakToBlock, breaklevel > 1));
} }
/* Now remove the jump of block if it points to this. /* Now remove the jump of block if it points to this.
*/ */
if (bodyBlock.jump != null && if (bodyBlock.jump != null &&
@ -905,7 +932,7 @@ public class FlowBlock {
bodyBlock.removeJump(); bodyBlock.removeJump();
lastModified = whileBlock; lastModified = whileBlock;
} } while (false);
/* remove ourself from the predecessor list. /* remove ourself from the predecessor list.
*/ */
@ -934,19 +961,9 @@ public class FlowBlock {
if (jump == null || jump.destination != END_OF_METHOD) if (jump == null || jump.destination != END_OF_METHOD)
continue; continue;
while (!appendBlock.contains(jump.prev)) { while (!appendBlock.contains(jump.prev))
appendBlock = appendBlock.outer; 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 /* appendBlock can't be null now, because the
* outermost block contains every structured block. * outermost block contains every structured block.
*/ */
@ -1007,12 +1024,13 @@ public class FlowBlock {
static Transformation[] exprTrafos = { static Transformation[] exprTrafos = {
new RemoveEmpty(), new RemoveEmpty(),
new CreateExpression(), new CreateExpression(),
new CreatePostIncExpression(), new CreatePrePostIncExpression(),
new CreateAssignExpression(), new CreateAssignExpression(),
new CreateNewConstructor(), new CreateNewConstructor(),
new CombineIfGotoExpressions(), new CombineIfGotoExpressions(),
new CreateIfThenElseOperator(), new CreateIfThenElseOperator(),
new CreateConstantArray(), new CreateConstantArray(),
new CreateForInitializer(),
}; };
@ -1060,6 +1078,8 @@ public class FlowBlock {
* @param end the end of the address range. * @param end the end of the address range.
*/ */
public boolean analyze(int start, int end) { public boolean analyze(int start, int end) {
if (Decompiler.debugAnalyze)
System.err.println("analyze("+start+", "+end+")");
try { try {
jode.TabbedPrintWriter writer = null; jode.TabbedPrintWriter writer = null;
if (Decompiler.isFlowDebugging) if (Decompiler.isFlowDebugging)
@ -1067,6 +1087,13 @@ public class FlowBlock {
boolean changed = false; 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) { while (true) {
if (Decompiler.isFlowDebugging) { if (Decompiler.isFlowDebugging) {
@ -1101,6 +1128,9 @@ public class FlowBlock {
writer.untab(); writer.untab();
} }
if (Decompiler.debugAnalyze)
System.err.println("T2("+addr+","+(addr+length)
+") succeeded");
/* T2 transformation succeeded. This may /* T2 transformation succeeded. This may
* make another T1 analysis in the previous * make another T1 analysis in the previous
* block possible. * block possible.
@ -1115,18 +1145,16 @@ public class FlowBlock {
/* the Block has no successor where t1 is applicable. /* the Block has no successor where t1 is applicable.
* Finish this analyzation. * Finish this analyzation.
*/ */
if (Decompiler.isFlowDebugging) { if (Decompiler.debugAnalyze)
writer.println("No more successors applicable: " System.err.println
+ start + " - " + end + "; " ("No more successors applicable: "
+ addr + " - " + (addr+length)); + start + " - " + end + "; "
} + addr + " - " + (addr+length));
return changed; return changed;
} else { } else {
/* Only do T1 transformation if the blocks are
* adjacent. */
if (succ.block instanceof SwitchBlock) { if (succ.block instanceof SwitchBlock) {
/* analyze succ, the new region is the /* analyze succ, the new region is the
* continous region of * continuous region of
* [start,end) \cap \compl [addr, addr+length) * [start,end) \cap \compl [addr, addr+length)
* where succ.addr lies in. * where succ.addr lies in.
*/ */
@ -1137,8 +1165,23 @@ public class FlowBlock {
if (succ.analyzeSwitch(newStart, newEnd)) if (succ.analyzeSwitch(newStart, newEnd))
break; 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) || succ.addr+succ.length == addr)
/* Only do T1 transformation if the blocks are
* adjacent. */
&& doT1(succ)) { && doT1(succ)) {
/* T1 transformation succeeded. */ /* T1 transformation succeeded. */
changed = true; changed = true;
@ -1148,30 +1191,221 @@ public class FlowBlock {
writer.tab(); writer.tab();
dumpSource(writer); dumpSource(writer);
writer.untab(); writer.untab();
} }
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; 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;
}
} }
/* Try the next successor. /* Try the next successor.
*/ */
succ = getSuccessor(succ.addr+1, end); succ = getSuccessor(succ.addr+1, end);
} }
} }
} catch (java.io.IOException ioex) { } 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. * Resolves the destinations of all jumps.
*/ */
public void resolveJumps(FlowBlock[] instr) { public void resolveJumps(FlowBlock[] instr) {
if (block instanceof RawTryCatchBlock) {
((RawTryCatchBlock)block).getTryBlock()
.jump.destination.resolveJumps(instr);
}
Enumeration enum = successors.elements(); Enumeration enum = successors.elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement(); Jump jump = (Jump) enum.nextElement();
if (jump != null) { if (jump != null && jump.destination == null) {
if (jump.destAddr == -1) if (jump.destAddr == -1)
jump.destination = END_OF_METHOD; jump.destination = END_OF_METHOD;
else else
jump.destination = instr[jump.destAddr]; 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() { public StructuredBlock getBlock() {
return block; 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. * Returns all sub block of this structured block.
*/ */
public StructuredBlock[] getSubBlocks() { public StructuredBlock[] getSubBlocks() {
if (elseBlock == null) { return (elseBlock == null)
StructuredBlock[] result = { thenBlock }; ? new StructuredBlock[] { thenBlock }
return result; : new StructuredBlock[] { thenBlock, elseBlock };
} else {
StructuredBlock[] result = { thenBlock, elseBlock };
return result;
}
} }
/** /**

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

@ -47,6 +47,11 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
*/ */
Instruction incr; 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. * 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. * Returns all sub block of this structured block.
*/ */
public StructuredBlock[] getSubBlocks() { public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { bodyBlock }; return new StructuredBlock[] { bodyBlock };
return result; }
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) public void dumpInstruction(TabbedPrintWriter writer)
@ -141,9 +166,16 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
writer.print("do"); writer.print("do");
break; break;
case FOR: case FOR:
writer.print("for (" writer.print("for (");
+(init != null ? init.simplify().toString() : "") if (isDeclaration)
+"; "+cond.simplify().toString()+"; " 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()+")"); +incr.simplify().toString()+")");
break; break;
} }
@ -188,6 +220,28 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
mayChangeJump = false; 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 * 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. * 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 { public class RawTryCatchBlock extends StructuredBlock {
int endAddr;
public RawTryCatchBlock(jode.Type type, public RawTryCatchBlock(jode.Type type,
StructuredBlock tryBlock,
Jump endDest, Jump catchDest) { Jump endDest, Jump catchDest) {
this.type = type; this.type = type;
// endBlock = new EmptyBlock(endDest); endAddr = endDest.destAddr;
// endBlock.outer = this;
catchBlock = new EmptyBlock(catchDest); catchBlock = new EmptyBlock(catchDest);
catchBlock.outer = this; catchBlock.outer = this;
}
replace(tryBlock, tryBlock); public FlowBlock chainTo(FlowBlock flow) {
this.tryBlock = tryBlock; FlowBlock first = flow;
tryBlock.outer = this; RawTryCatchBlock parent = null;
while (flow.getBlock() instanceof RawTryCatchBlock
&& (((RawTryCatchBlock) flow.getBlock()).getCatchAddr()
> this.getCatchAddr())) {
// endBlock.setFlowBlock(flowBlock); parent = (RawTryCatchBlock) flow.getBlock();
// if (tryBlock instanceof RawTryCatchBlock flow = parent.getTryBlock().jump.destination;
// && ((RawTryCatchBlock)tryBlock).endBlock.jump.destination }
// == endDest.destination)
// endBlock.jump = null;
// else
// flowBlock.addSuccessor(endDest);
catchBlock.setFlowBlock(flowBlock); tryBlock = new EmptyBlock(new Jump(flow));
flowBlock.addSuccessor(catchDest); 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; 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. * The catch block.
*/ */
@ -101,14 +104,6 @@ public class RawTryCatchBlock extends StructuredBlock {
StructuredBlock newBlock) { StructuredBlock newBlock) {
if (tryBlock == oldBlock) if (tryBlock == oldBlock)
tryBlock = newBlock; 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) else if (catchBlock == oldBlock)
catchBlock = newBlock; catchBlock = newBlock;
else else
@ -120,30 +115,15 @@ public class RawTryCatchBlock extends StructuredBlock {
* Returns all sub block of this structured block. * Returns all sub block of this structured block.
*/ */
public StructuredBlock[] getSubBlocks() { public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { tryBlock/*, endBlock*/, catchBlock }; return new StructuredBlock[] { tryBlock, catchBlock };
return result;
} }
// /**
// * 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) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
writer.println("TRY "+(type != null ? type.toString() : "ALL")); writer.println("TRY "+(type != null ? type.toString() : "ALL"));
writer.tab(); writer.tab();
tryBlock.dumpSource(writer); tryBlock.dumpSource(writer);
writer.untab(); writer.untab();
// writer.println("UNTIL");
// writer.tab();
// endBlock.dumpSource(writer);
// writer.untab();
writer.println("CATCH TO"); writer.println("CATCH TO");
writer.tab(); writer.tab();
catchBlock.dumpSource(writer); catchBlock.dumpSource(writer);

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

@ -39,7 +39,7 @@ public class ReturnBlock extends InstructionContainer {
* @return true if this block should be sorrounded by braces. * @return true if this block should be sorrounded by braces.
*/ */
public boolean needsBraces() { 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. * @param jump The jump that should be moved, may be null.
*/ */
public void moveJump(Jump jump) { public void moveJump(Jump jump) {
removeJump(); removeJump();
this.jump = jump; this.jump = jump;
if (jump != null) { if (jump != null) {
jump.prev.jump = null; jump.prev.jump = null;
@ -458,5 +458,19 @@ public abstract class StructuredBlock {
*/ */
public abstract void dumpInstruction(TabbedPrintWriter writer) public abstract void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException; 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); 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) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {

Loading…
Cancel
Save