Labelled Blocks

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1416 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 13 years ago
parent 0277d99ebb
commit 7a96e31c81
  1. 35
      jode/src/net/sf/jode/flow/FlowBlock.java
  2. 161
      jode/src/net/sf/jode/flow/LabelledBlock.java
  3. 5
      jode/src/net/sf/jode/flow/StructuredBlock.java

@ -226,7 +226,13 @@ public class FlowBlock {
if (jumps == null) if (jumps == null)
return null; return null;
Jump remainingJumps = null; Jump remainingJumps = null;
/* find the smallest block containing all jumps */
lastModified = jumps.prev; lastModified = jumps.prev;
for (Jump jump = jumps.next; jump != null; jump = jump.next) {
while (!lastModified.contains(jump.prev))
lastModified = lastModified.outer;
}
StructuredBlock b = lastModified.outer; StructuredBlock b = lastModified.outer;
while (b != null) { while (b != null) {
if (b.outer instanceof TryBlock if (b.outer instanceof TryBlock
@ -282,7 +288,7 @@ public class FlowBlock {
ConditionalBlock cb = (ConditionalBlock) prev.outer; ConditionalBlock cb = (ConditionalBlock) prev.outer;
Expression instr = cb.getInstruction(); Expression instr = cb.getInstruction();
/* This is a jump inside an ConditionalBlock. /* This is a jump inside a ConditionalBlock.
* *
* cb is the conditional block, * cb is the conditional block,
* prev the empty block containing the jump * prev the empty block containing the jump
@ -290,7 +296,7 @@ public class FlowBlock {
if (cb.jump != null) { if (cb.jump != null) {
/* This can only happen if cb also jumps to succ. /* This can only happen if cb also jumps to succ.
* This is a weired "if (cond) empty"-block. We * This is a weird "if (cond) empty"-block. We
* transform it by hand. * transform it by hand.
*/ */
prev.removeJump(); prev.removeJump();
@ -335,6 +341,8 @@ public class FlowBlock {
loopBlock.setCondition(instr.negate()); loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); loopBlock.moveDefinitions(cb, null);
if (loopBlock.contains(lastModified))
lastModified = loopBlock;
cb.removeBlock(); cb.removeBlock();
continue; continue;
} }
@ -371,6 +379,8 @@ public class FlowBlock {
loopBlock.setType(LoopBlock.DOWHILE); loopBlock.setType(LoopBlock.DOWHILE);
loopBlock.setCondition(instr.negate()); loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); loopBlock.moveDefinitions(cb, null);
if (loopBlock.contains(lastModified))
lastModified = loopBlock;
cb.removeBlock(); cb.removeBlock();
continue; continue;
} }
@ -590,11 +600,11 @@ public class FlowBlock {
/** /**
* Resolve remaining jumps to the successor by generating break * Resolve remaining jumps to the successor by generating break
* instructions. As last resort generate a do while(false) block. * instructions. As last resort generate a labelled block.
* @param jumps The jump list that need to be resolved. * @param jumps The jump list that need to be resolved.
*/ */
void resolveRemaining(Jump jumps) { void resolveRemaining(Jump jumps) {
LoopBlock doWhileFalse = null; LabelledBlock labelledBlock = null;
StructuredBlock outerMost = lastModified; StructuredBlock outerMost = lastModified;
boolean removeLast = false; boolean removeLast = false;
for (; jumps != null; jumps = jumps.next) { for (; jumps != null; jumps = jumps.next) {
@ -622,19 +632,18 @@ public class FlowBlock {
prevBlock.removeJump(); prevBlock.removeJump();
if (breakToBlock == null) { if (breakToBlock == null) {
/* Nothing else helped, so put a do/while(0) /* Nothing else helped, so put a labelled
* block around outerMost and break to that * block around outerMost and break to that
* block. * block.
*/ */
if (doWhileFalse == null) { if (labelledBlock == null) {
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE, labelledBlock = new LabelledBlock();
LoopBlock.FALSE);
} }
/* Adapt outermost, so that it contains the break. */ /* Adapt outermost, so that it contains the break. */
while (!outerMost.contains(prevBlock)) while (!outerMost.contains(prevBlock))
outerMost = outerMost.outer; outerMost = outerMost.outer;
prevBlock.appendBlock prevBlock.appendBlock
(new BreakBlock(doWhileFalse, breaklevel > 0)); (new BreakBlock(labelledBlock, true));
} else } else
prevBlock.appendBlock prevBlock.appendBlock
(new BreakBlock(breakToBlock, breaklevel > 1)); (new BreakBlock(breakToBlock, breaklevel > 1));
@ -643,10 +652,10 @@ public class FlowBlock {
if (removeLast) if (removeLast)
lastModified.removeJump(); lastModified.removeJump();
if (doWhileFalse != null) { if (labelledBlock != null) {
doWhileFalse.replace(outerMost); labelledBlock.replace(outerMost);
doWhileFalse.setBody(outerMost); labelledBlock.setBody(outerMost);
lastModified = doWhileFalse; lastModified = labelledBlock;
} }
} }

@ -0,0 +1,161 @@
/* LoopBlock Copyright (C) 1998-2002 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: LoopBlock.java 1411 2012-03-01 22:39:08Z hoenicke $
*/
package net.sf.jode.flow;
import net.sf.jode.decompiler.TabbedPrintWriter;
/**
* This is the structured block for an Loop block.
*/
public class LabelledBlock extends StructuredBlock implements BreakableBlock {
/**
* The body of this labelled block. This is always a valid block and not null.
*/
StructuredBlock bodyBlock;
/**
* The stack after the break.
*/
VariableStack breakedStack;
/**
* The serial number for labels.
*/
static int serialno = 0;
/**
* The label of this instruction, or null if it needs no label.
*/
String label = null;
public LabelledBlock() {
}
public void setBody(StructuredBlock body) {
bodyBlock = body;
bodyBlock.outer = this;
body.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 (bodyBlock != oldBlock)
return false;
bodyBlock = newBlock;
newBlock.outer = this;
oldBlock.outer = null;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { bodyBlock };
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
super.dumpSource(writer);
}
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException
{
if (label != null) {
writer.untab();
writer.println(label+":");
writer.tab();
}
boolean needBrace = bodyBlock.needsBraces();
if (needBrace)
writer.openBrace();
else
writer.println();
writer.tab();
bodyBlock.dumpSource(writer);
writer.untab();
writer.closeBrace();
}
/**
* Returns the label of this block and creates a new label, if
* there wasn't a label previously.
*/
public String getLabel() {
if (label == null)
label = "label_"+(serialno++);
return label;
}
/**
* Is called by BreakBlock, to tell us that this block is breaked.
*/
public void setBreaked() {
}
/**
* This is called after the analysis is completely done. It
* will remove all PUSH/stack_i expressions, (if the bytecode
* is correct).
* @param stack the stack at begin of the block
* @return null if there is no way to the end of this block,
* otherwise the stack after the block has executed.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
VariableStack afterBody = bodyBlock.mapStackToLocal(stack);
mergeBreakedStack(afterBody);
return breakedStack;
}
/**
* Is called by BreakBlock, to tell us what the stack can be after a
* break.
* @return false if the stack is inconsistent.
*/
public void mergeBreakedStack(VariableStack stack) {
if (breakedStack != null)
breakedStack.merge(stack);
else
breakedStack = stack;
}
public void removePush() {
bodyBlock.removePush();
}
/**
* 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 false;
}
}

@ -336,8 +336,11 @@ public abstract class StructuredBlock {
if (jump != null) if (jump != null)
outer.getSubBlocks()[0].moveJump(jump); outer.getSubBlocks()[0].moveJump(jump);
outer.getSubBlocks()[0].replace(outer); outer.getSubBlocks()[0].replace(outer);
} else } else {
if (outer.jump != null)
outer.getSubBlocks()[1].moveJump(outer.jump);
outer.getSubBlocks()[1].replace(outer); outer.getSubBlocks()[1].replace(outer);
}
return; return;
} }

Loading…
Cancel
Save