From 2589bb4450ca5ab69b703db81553c5195da4bb93 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 16 Sep 1998 17:50:05 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@15 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/flow/FlowBlock.java | 199 +++++++++++++++++----------- jode/jode/flow/StructuredBlock.java | 13 +- 2 files changed, 132 insertions(+), 80 deletions(-) diff --git a/jode/jode/flow/FlowBlock.java b/jode/jode/flow/FlowBlock.java index e158e49..fe77ea9 100644 --- a/jode/jode/flow/FlowBlock.java +++ b/jode/jode/flow/FlowBlock.java @@ -47,7 +47,7 @@ public class FlowBlock { StructuredBlock lastModified; /** - * All jumps that this flow block contains. + * All Jumps that this flow block contains. */ Vector successors; @@ -58,40 +58,47 @@ public class FlowBlock { */ Vector predecessors; - public void optimizeJumps(FlowBlock successor) { - /* remove all unconditional jumps to the successor which have the - * end of the block as normal successor. + /** + * This method optimizes the jumps to successor. + * Returns true, if all jumps could be eliminated. + */ + public boolean optimizeJumps(FlowBlock successor, + StructuredBlock structBlock) { + /* if the jump is the jump of the structBlock, skip it. */ + + /* remove all jumps to the successor which have the successor + * as getNextFlowBlock(). */ /* 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 the successor is the dummy return instruction, replace all + * jumps with a return. */ - - - /* 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 + /* if there are jumps in a while block or switch block and the + * while/switch block is followed by a jump to successor or has + * successor as getNextFlowBlock(), replace jump with break to + * the innermost such while/switch block. + * + * If the switch block hasn't been breaked before we could + * take some heuristics and add a jump after the switch to + * succesor, so that the above succeeds. + * + * If this is a while and the condition of the while is true, + * and this jump belongs to the first instruction in this + * while block and is inside a ConditionalBlock remove that + * ConditionalBlock an move the condition to the while block. + */ + + /* if there are 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 is followed by a single block, then replace * the if-then block with a if-then-else block and remove the - * unconditional jumps. + * unconditional jump. */ } @@ -162,34 +169,96 @@ public class FlowBlock { public boolean doT1 { /* search successor with smallest addr. */ + Enumeration enum = successors.elements(); + FlowBlock succ = null; + while (enum.hasMoreElements()) { + FlowBlock fb = ((Jump) enum.nextElement()).destination; + if (succ == null || fb.addr < succ.addr) { + succ = fb; + } + } + if (succ == null) { + /* There are no successors at all */ + return false; + } /* check if this successor has only this block as predecessor. */ /* if not, return false. */ + if (succ.predecessors.size() != 1) + 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. + /* First find the innermost block that contains all jumps to this + * successor and the last modified block. */ + Enumeration enum = successors.elements(); + StructuredBlock structBlock = lastModified; + while(enum.hasMoreElements()) { + Jump jump = (Jump) enum.nextElement(); - optimizeJumps(successor); - - /* if the successor is the dummy return instruction, replace all - * jumps with a return. + while (!structBlock.contains(jump.parent)) + structBlock = structBlock.outer; + /* structBlock can't be null now, because the + * outermost block contains every structured block. + */ + } + + /* The switch "fall through" case: if the structBlock is a + * switch, and the successor is the address of a case, and all + * other successors are inside the block preceding that case. + */ + if (case != null) { + SwitchBlock switchBlock = (StructuredBlock) structBlock; + + /* Now put the succ.block into the next case. + */ + switchBlock.replaceSubBlock(nextcase,succ.block); + + /* Do the following modifications on the struct block. */ + structBlock = precedingcase; + + } else { + + /* Prepare the unification of the blocks: Make sure that + * structBlock has a successor outside of this block. This is + * always possible, because it contains lastModified. + */ + if (structBlock.jump == null) { + /* assert(structBlock.jump.getNextFlowBlock() != null) */ + structBlock.setJump(structBlock.getNextFlowBlock()); + } + + /* Now unify the blocks: Create a new SequentialBlock + * containing structBlock and successor.block. Then replace + * structBlock with the new sequential block. + */ + } + + /* Try to eliminate as many jumps as possible. + */ + + optimizeJumps(succ, structBlock); + + /* Now remove the jump of the structBlock if it points to successor. */ + if (structBlock.jump == null) + structBlock.removeJump(); + /* 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. */ + * structBlock and replace every remaining jump with a break + * to the do/while block. + */ + + /* Set last modified to correct value. + */ + lastModified = succ.lastModified; } 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. + * considered yet, return false. The second condition make + * sure that the while isn't created up to the first continue. */ /* If there is only one jump to the beginning and it is the @@ -197,56 +266,28 @@ public class FlowBlock { * 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. + * and replace breaks to do/while with continue to for. */ { /* 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. - */ + /* Try to eliminate as many jumps as possible. + */ + optimizeJumps(this, block); + + /* Now remove the jump of block if it points to this. + */ + + /* 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.

- * - * There are following types of structured blocks:

- */ -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; -} diff --git a/jode/jode/flow/StructuredBlock.java b/jode/jode/flow/StructuredBlock.java index 5e56dcf..8a6fd06 100644 --- a/jode/jode/flow/StructuredBlock.java +++ b/jode/jode/flow/StructuredBlock.java @@ -149,7 +149,7 @@ public abstract class StructuredBlock { FlowBlock getNextFlowBlock(StructuredBlock subBlock) { if (jump != null) - return jump; + return jump.destination; return getNextFlowBlock(); } @@ -164,6 +164,17 @@ public abstract class StructuredBlock { return false; } + /** + * Returns if this block contains the given block. + * @param child the block which should be contained by this block. + * @return false, if child is null, or is not contained in this block. + */ + boolean contains(StructuredBlock child) { + while (child != this && child != null) + child = child.outer; + return (child == this); + } + /** * Print the source code for this structured block. This may be * called only once, because it remembers which local variables