git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@11 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 27 years ago
parent f3f21e7d2c
commit 3360965bb1
  1. 30
      jode/CreateBreakStatement.java
  2. 78
      jode/CreateConstantArray.java
  3. 100
      jode/CreateIfStatements.java
  4. 132
      jode/CreateSwitchStatements.java
  5. 11
      jode/CreateTryCatchStatements.java
  6. 31
      jode/CreateWhileStatements.java
  7. 79
      jode/FlowTransformation.java
  8. 2
      jode/RemoveNop.java
  9. 14
      jode/jode/bytecode/Opcodes.java
  10. 3
      jode/jode/decompiler/ClassAnalyzer.java
  11. 2
      jode/jode/decompiler/CodeAnalyzer.java
  12. 19
      jode/jode/expr/BreakInstructionHeader.java
  13. 58
      jode/jode/expr/CaseInstructionHeader.java
  14. 44
      jode/jode/expr/CreateIfThenElseOperator.java
  15. 75
      jode/jode/expr/IfInstructionHeader.java
  16. 110
      jode/jode/expr/InstructionHeader.java
  17. 23
      jode/jode/expr/MethodInstructionHeader.java
  18. 128
      jode/jode/expr/SwitchInstructionHeader.java
  19. 19
      jode/jode/expr/TryCatchInstructionHeader.java
  20. 57
      jode/jode/expr/WhileInstructionHeader.java

@ -4,12 +4,26 @@ public class CreateBreakStatement implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
InstructionHeader breakDest;
if (ih.getFlowType() == ih.GOTO)
breakDest = ih.successors[0];
breakDest = ih.successors[0].getShadow();
else if (ih.getFlowType() == ih.IFGOTO)
breakDest = ih.successors[1];
breakDest = ih.successors[1].getShadow();
else
return null;
if (breakDest == ih.getEndBlock()) {
/* This is an unnecessary goto, remove it.
*/
if (ih.prevInstruction != null)
ih.prevInstruction.nextInstruction = ih.nextInstruction;
if (ih.nextInstruction != null)
ih.nextInstruction.prevInstruction = ih.prevInstruction;
breakDest.addPredecessors(ih);
breakDest.predecessors.removeElement(ih);
if (Decompiler.isVerbose)
System.err.print("g");
return null;
}
boolean needBreakLabel = false, needContLabel = false;
InstructionHeader outer = ih.outer;
while (outer != null) {
@ -17,13 +31,19 @@ public class CreateBreakStatement implements Transformation {
if (Decompiler.isVerbose)
System.err.print("b");
return new BreakInstructionHeader
(ih, needBreakLabel?outer.getLabel(): null, true);
(ih.BREAK, ih, needBreakLabel?outer.getLabel(): null);
}
if (outer.getContinue() == breakDest) {
if (Decompiler.isVerbose)
System.err.print("b");
System.err.print("c");
return new BreakInstructionHeader
(ih.CONTINUE, ih, needContLabel?outer.getLabel(): null);
}
if (outer.outer == null && outer.getEndBlock() == breakDest) {
if (Decompiler.isVerbose)
System.err.print("r");
return new BreakInstructionHeader
(ih, needContLabel?outer.getLabel(): null, false);
(ih.VOIDRETURN, ih, null);
}
if (outer.getBreak() != null)
needBreakLabel = true;

@ -4,39 +4,20 @@ import sun.tools.java.Type;
public class CreateConstantArray implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
Expression[] consts;
int count;
Expression[] consts = null;
int count = 0;
Type type;
try {
if (ih.getInstruction() instanceof DupOperator)
/* this is not the end of the array assign */
return null;
ih = ih.getSimpleUniquePredecessor();
ArrayStoreOperator store =
(ArrayStoreOperator) ih.getInstruction();
ih = ih.getSimpleUniquePredecessor();
Expression lastconst = (Expression) ih.getInstruction();
ih = ih.getSimpleUniquePredecessor();
Expression lastindexexpr = (Expression) ih.getInstruction();
ConstOperator lastindexop =
(ConstOperator) lastindexexpr.getOperator();
if (!MyType.isOfType(lastindexop.getType(), MyType.tInt))
return null;
int lastindex = Integer.parseInt(lastindexop.getValue());
ih = ih.getSimpleUniquePredecessor();
DupOperator dup = (DupOperator) ih.getInstruction();
if (dup.getDepth() != 0 ||
dup.getCount() != store.getLValueType().stackSize())
return null;
consts = new Expression[lastindex+1];
consts[lastindex] = lastconst;
count = 1;
while (lastindex-- > 0) {
ih = ih.getSimpleUniquePredecessor();
ArrayStoreOperator store2 =
int lastindex = -1;
while (ih.getInstruction() instanceof ArrayStoreOperator) {
ArrayStoreOperator store =
(ArrayStoreOperator) ih.getInstruction();
ih = ih.getSimpleUniquePredecessor();
lastconst = (Expression) ih.getInstruction();
Expression lastconst = (Expression) ih.getInstruction();
ih = ih.getSimpleUniquePredecessor();
Expression indexexpr = (Expression) ih.getInstruction();
ConstOperator indexop =
@ -44,23 +25,34 @@ public class CreateConstantArray implements Transformation {
if (!MyType.isOfType(indexop.getType(), MyType.tUInt))
return null;
int index = Integer.parseInt(indexop.getValue());
if (index > lastindex)
if (index > 0 && consts == null) {
lastindex = index;
consts = new Expression[lastindex+1];
} else if (index < 0 || index > lastindex)
return null;
while (index < lastindex) {
consts[lastindex] = new Expression
(new ConstOperator(MyType.tUnknown, ""),
new Expression[0]);
lastindex--;
}
consts[lastindex] = lastconst;
else {
while (index < lastindex) {
consts[lastindex--] = new Expression
(new ConstOperator(MyType.tUnknown, "0"),
new Expression[0]);
}
}
consts[lastindex--] = lastconst;
ih = ih.getSimpleUniquePredecessor();
dup = (DupOperator) ih.getInstruction();
DupOperator dup = (DupOperator) ih.getInstruction();
if (dup.getDepth() != 0 ||
dup.getCount() != store.getLValueType().stackSize())
return null;
count++;
ih = ih.getSimpleUniquePredecessor();
}
if (count == 0)
return null;
while (lastindex >= 0) {
consts[lastindex--] = new Expression
(new ConstOperator(MyType.tUnknown, "0"),
new Expression[0]);
}
ih = ih.getSimpleUniquePredecessor();
Expression newArrayExpr = (Expression) ih.getInstruction();
NewArrayOperator newArrayOp =
(NewArrayOperator) newArrayExpr.getOperator();
@ -73,13 +65,25 @@ public class CreateConstantArray implements Transformation {
(ConstOperator) countexpr.getOperator();
if (!MyType.isOfType(countop.getType(), MyType.tUInt))
return null;
if (Integer.parseInt(countop.getValue()) != consts.length)
return null;
int arraylength = Integer.parseInt(countop.getValue());
if (arraylength != consts.length) {
if (arraylength < consts.length)
return null;
Expression[] newConsts = new Expression[arraylength];
System.arraycopy(consts, 0, newConsts, 0, consts.length);
for (int i=consts.length; i<arraylength; i++)
newConsts[i] = new Expression
(new ConstOperator(MyType.tUnknown, "0"),
new Expression[0]);
consts = newConsts;
}
} catch (NullPointerException ex) {
return null;
} catch (ClassCastException ex) {
return null;
}
if (Decompiler.isVerbose)
System.err.print("a");
Operator op = new ConstantArrayOperator(type, consts.length);
return ih.combine(4*count+1, new Expression(op, consts));
}

@ -1,56 +1,88 @@
package jode;
public class CreateIfStatements implements Transformation {
public class CreateIfStatements extends FlowTransformation
implements Transformation {
public InstructionHeader transform(InstructionHeader ifgoto) {
if (ifgoto.getFlowType() != ifgoto.IFGOTO ||
ifgoto.nextInstruction == null ||
ifgoto.getSuccessors()[1].getAddress() <=
ifgoto.getSuccessors()[0].getAddress())
return null;
InstructionHeader next = ifgoto.getSuccessors()[1];
InstructionHeader endBlock = next;
if (ifgoto.outer != next.outer) {
if (ifgoto.outer.endBlock != next)
/* elseBlock points to the first instruction of the
* elseBlock or is null if the else block is empty.
* next points to the next instruction after this block
* or is null, if this if is the last instruction in
* this block.
*/
InstructionHeader elseBlock = null, next = null;
if (ifgoto.outer != ifgoto.successors[1].outer) {
if (ifgoto.outer.getEndBlock() != ifgoto.successors[1].getShadow())
/* This doesn't seem to be an if but a if-break
*/
return null;
/* This is an if without else that goes to the end
* of the current block. May be this was a continue,
* but who would know it?
*
* If you like breaks and continues more than ifs,
* simply do the break transformation before the
* if transformation.
*/
next = null;
}
} else {
/* This is a normal if, let us first assume, that there is
* no else part. Then end is successors[1], but that may
* be a while loop, so unoptimized it...
*/
next = UnoptimizeWhileLoops(ifgoto.successors[1]);
if (next != ifgoto.successors[1]) {
ifgoto.successors[1].predecessors.removeElement(ifgoto);
ifgoto.successors[1] = next;
ifgoto.successors[1].predecessors.addElement(ifgoto);
}
InstructionHeader thenStart = ifgoto.nextInstruction;
InstructionHeader thenEnd;
for (thenEnd = thenStart;
thenEnd != null && thenEnd.nextInstruction != next;
thenEnd = thenEnd.nextInstruction) {
}
if (thenEnd == null)
return null;
/* next.prevInstruction is the end of the `then' block.
* If this a goto statement that jumps downward, this is
* probably an `if-then-else'.
*/
InstructionHeader thenEnd = next.prevInstruction;
if (thenEnd.flowType == thenEnd.GOTO) {
if (thenEnd.successors[0].outer == next.outer &&
thenEnd.successors[0].addr >= next.addr) {
InstructionHeader elseStart = null;
InstructionHeader elseEnd = null;
if (next != null &&
thenEnd.getFlowType() == thenEnd.GOTO &&
thenEnd.successors[0].getAddress() > next.getAddress()) {
elseStart = next;
endBlock = next = thenEnd.successors[0];
if (ifgoto.outer != next.outer) {
if (ifgoto.outer.endBlock != next)
return null;
next = null;
}
for (elseEnd = elseStart;
elseEnd != null && elseEnd.nextInstruction != next;
elseEnd = elseEnd.nextInstruction) {
/* this is a normal if-then-else that is
* fully contained in this block.
*/
elseBlock = next;
next = UnoptimizeWhileLoops(thenEnd.successors[0]);
} else if (thenEnd.successors[0].getShadow() ==
ifgoto.outer.getEndBlock()) {
/* this is a normal if-then-else that goes
* to the end of the block.
*
* Again this may also be a continue/break statement,
* but again, who knows.
*/
elseBlock = next;
next = null;
}
}
/* XXX return error or create if-then?
*/
if (elseEnd == null)
return null;
}
/* This was all, the rest is done in the constructor of
* IfInstructionHeader.
*/
if(Decompiler.isVerbose)
System.err.print("i");
return new IfInstructionHeader
(ifgoto, elseStart != null, thenEnd, elseEnd, endBlock);
(ifgoto, elseBlock, next);
}
}

@ -1,7 +1,8 @@
package jode;
import java.util.Enumeration;
public class CreateSwitchStatements implements Transformation {
public class CreateSwitchStatements extends FlowTransformation
implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
if (ih.getFlowType() != ih.SWITCH)
@ -14,8 +15,6 @@ public class CreateSwitchStatements implements Transformation {
int addr = switchIH.nextInstruction.addr;
int count = 1;
for (int i=0; i < switchIH.successors.length; i++) {
if (switchIH.successors[i].addr < addr)
return null;
if (switchIH.successors[i] != switchIH.successors[defaultCase])
count ++;
}
@ -27,6 +26,15 @@ public class CreateSwitchStatements implements Transformation {
if (i != defaultCase &&
switchIH.successors[i] == switchIH.successors[defaultCase])
continue;
InstructionHeader next =
UnoptimizeWhileLoops(switchIH.successors[i]);
if (next != switchIH.successors[i]) {
switchIH.successors[i].predecessors.removeElement(switchIH);
switchIH.successors[i] = next;
switchIH.successors[i].predecessors.addElement(switchIH);
}
int insert;
for (insert = 0; insert < count; insert++) {
if (sorted[insert].addr > switchIH.successors[i].addr)
@ -45,34 +53,120 @@ public class CreateSwitchStatements implements Transformation {
sorted[insert] = switchIH.successors[i];
count++;
}
InstructionHeader endBlock = switchIH.outer.endBlock;
ih = sorted[count-1];
if (ih.outer == switchIH.outer) {
InstructionHeader endBlock = switchIH.outer.getEndBlock();
int lastBlock;
for (lastBlock = count-1; lastBlock>= 0; lastBlock--)
if (sorted[lastBlock].outer == switchIH.outer)
break;
if (lastBlock >= 0) {
EndSearch:
ih = sorted[lastBlock];
while (ih != null) {
Enumeration enum = ih.getPredecessors().elements();
Enumeration enum;
if (ih.flowType == ih.GOTO)
enum = ih.successors[0].getPredecessors().elements();
else
enum = ih.getPredecessors().elements();
while (enum.hasMoreElements()) {
InstructionHeader pred =
(InstructionHeader)enum.nextElement();
if (pred.addr < sorted[count-1].addr &&
if (pred.addr < sorted[lastBlock].addr &&
pred.outer == switchIH.outer &&
(pred.flowType == ih.GOTO ||
(pred.flowType == ih.IFGOTO &&
pred.successors[1] == ih))) {
pred.successors[1] == ih)) &&
ih == UnoptimizeWhileLoops(ih)) {
endBlock = ih;
break EndSearch;
/* search further down, if there are other
* more suitible instructions.
*/
}
}
// if (ih.flowType == ih.GOTO) {
// /* XXX: while loops in default part versus
// * while loops after switches
// */
// endBlock = ih.successors[0];
// break EndSearch;
// }
ih = ih.nextInstruction;
}
} else
endBlock = ih;
}
for (int i=0; i< sorted.length; i++) {
if (sorted[i].outer != switchIH.outer) {
if (sorted[i].getShadow() != endBlock) {
/* Create a new goto at the beginning of
* the switch statement, jumping to the right
* successor.
*/
InstructionHeader[] successors = { sorted[i] };
InstructionHeader dummyGoto =
new InstructionHeader(switchIH.GOTO,
switchIH.addr, switchIH.addr,
successors, switchIH.outer);
sorted[i].predecessors.addElement(dummyGoto);
/* Connect it in the prev/next Instruction chain.
*/
dummyGoto.nextInstruction = switchIH.nextInstruction;
if (dummyGoto.nextInstruction != null)
dummyGoto.nextInstruction.prevInstruction = dummyGoto;
switchIH.nextInstruction = dummyGoto;
dummyGoto.prevInstruction = switchIH;
/* Search all instructions that jump to this point and
* stack them together.
*/
int length = 1;
while (i+length < sorted.length &&
sorted[i+length] == sorted[i])
length++;
/* Move them to the beginning of this array.
*/
System.arraycopy(sorted, 0, sorted, length, i);
int[] tmp = new int[length];
System.arraycopy(cases, i, tmp, 0, length);
System.arraycopy(cases, 0, cases, length, i);
System.arraycopy(tmp, 0, cases, 0, length);
if (defaultCase < i)
defaultCase += length;
else if (defaultCase <= i+length)
defaultCase -= i;
for (int j=0; j<length; j++)
sorted[j] = dummyGoto;
i += length - 1;
} else {
/* Search all instructions that jump to this point and
* stack them together.
*/
int length = 1;
while (i+length < sorted.length &&
sorted[i+length] == sorted[i])
length++;
/* Move them to the end of this array, if they
* aren't already there.
*/
if (i+length < sorted.length) {
System.arraycopy(sorted, i + length, sorted, i,
sorted.length - i - length);
for (int j=length; j>0; j--)
sorted[sorted.length-j] = endBlock;
int[] tmp = new int[length];
System.arraycopy(cases, i, tmp, 0, length);
System.arraycopy(cases, i + length, cases, i,
cases.length - i - length);
System.arraycopy(tmp, 0, cases,
sorted.length - length, length);
if (defaultCase >= i + length)
defaultCase -= length;
else if (defaultCase >=i)
defaultCase += cases.length-i-length;
}
}
}
}
if(Decompiler.isVerbose)
System.err.print("s");

@ -1,6 +1,7 @@
package jode;
public class CreateTryCatchStatements implements Transformation {
public class CreateTryCatchStatements extends FlowTransformation
implements Transformation {
public InstructionHeader transform(InstructionHeader tryIH) {
if (tryIH.getFlowType() != tryIH.TRY ||
@ -46,14 +47,12 @@ public class CreateTryCatchStatements implements Transformation {
}
InstructionHeader endBlock;
if (endIH != catchIH[1]) {
if ((endIH.flowType != endIH.RETURN ||
endIH.getInstruction().getType() != MyType.tVoid) &&
endIH.flowType != endIH.GOTO)
if (endIH.flowType != endIH.GOTO)
return null;
endBlock = endIH.successors[0];
endBlock = UnoptimizeWhileLoops(endIH.successors[0]);
} else
endBlock = tryIH.outer.endBlock;
endBlock = tryIH.outer.getEndBlock();
if (Decompiler.isVerbose)
System.err.print("t");
return new TryCatchInstructionHeader

@ -1,23 +1,40 @@
package jode;
public class CreateWhileStatements implements Transformation {
public class CreateWhileStatements extends FlowTransformation
implements Transformation {
public InstructionHeader transform(InstructionHeader gotoIH) {
if (gotoIH.flowType != gotoIH.GOTO || gotoIH.nextInstruction == null ||
gotoIH.successors[0].addr < gotoIH.nextInstruction.addr)
if (gotoIH.flowType == gotoIH.IFGOTO &&
gotoIH.successors[1] == gotoIH)
/* This is an empty while loop
*/
return new WhileInstructionHeader(gotoIH, gotoIH);
if (gotoIH.flowType != gotoIH.GOTO ||
gotoIH.nextInstruction == null ||
gotoIH.successors[0].addr < gotoIH.nextInstruction.addr ||
gotoIH.outer != gotoIH.successors[0].outer)
return null;
InstructionHeader block = gotoIH.nextInstruction;
InstructionHeader ifgoto = gotoIH.successors[0];
if (ifgoto.getFlowType() != ifgoto.IFGOTO ||
ifgoto.successors[1] != block ||
ifgoto.outer != block.outer)
ifgoto.outer != ifgoto.successors[1].outer)
return null;
InstructionHeader next = UnoptimizeWhileLoops(ifgoto.successors[1]);
if (next != gotoIH.nextInstruction)
return null;
if (next != ifgoto.successors[1]) {
ifgoto.successors[1].predecessors.removeElement(ifgoto);
ifgoto.successors[1] = next;
ifgoto.successors[1].predecessors.addElement(ifgoto);
}
if(Decompiler.isVerbose)
System.err.print("w");
return new WhileInstructionHeader(gotoIH, ifgoto, block);
return new WhileInstructionHeader(gotoIH, ifgoto);
}
}

@ -0,0 +1,79 @@
package jode;
abstract public class FlowTransformation {
/**
* This class reverses javac's optimization of while loops.
* A while loop is normally implemented as follows:
*
* <pre>
* loop: goto cond;
* head: <inner block>
* cond: if <condition> goto head;
* </pre>
*
* The problem is, if a while loop is the destination of a jump
* (e.g. it's in the else-part of an if, but there are many more
* cases). Then the first goto may or may not be removed (depends
* on the special case) and the previous instruction jumps
* directly to cond. <p>
*
* If we detect an if, that jumps backwards, but in the same block
* we assume that it belongs to a while statement and bring it to
* the above standard format. <p>
*
* If this function returns with another Header, it is guaranteed
* that lies in the same block.
*
* @param cond The destination of a jump.
* @return loop, if this is an while. loop is generated on
* the fly if it didn't exists before. If this isn't a while at
* all, the parameter is returned unchanged.
*/
public InstructionHeader UnoptimizeWhileLoops(InstructionHeader dest) {
if (dest.flowType != dest.IFGOTO ||
dest.successors[1].addr >= dest.addr ||
dest.successors[1].outer != dest.outer)
return dest;
/* Okay, initial checking done, this really looks like a while
* statement. Now we call us recursively, in case the first
* instruction of this while loop is a while loop again.<p>
*
* This won't lead to infinite recursion because the
* address of the instruction will always decrease.
*/
InstructionHeader head = UnoptimizeWhileLoops(dest.successors[1]);
/* Now we are at head. Look in front of this if loop is
* already existing. If this is the case simply return it.
*/
if (head.prevInstruction != null &&
head.prevInstruction.flowType == head.GOTO &&
head.prevInstruction.successors[0] == dest)
return head.prevInstruction;
/* No there was no loop label. Create a new one.
*/
InstructionHeader[] successors = { dest };
InstructionHeader loop =
new InstructionHeader(head.GOTO, head.addr, head.addr,
successors, head.outer);
/* Connect it in the prev/next Instruction chain.
*/
loop.prevInstruction = head.prevInstruction;
if (loop.prevInstruction != null)
loop.prevInstruction.nextInstruction = loop;
loop.nextInstruction = head;
head.prevInstruction = loop;
/* Loop has no predecessors, but a successor namely dest.
* The calling function may change this situation.
*/
dest.predecessors.addElement(loop);
return loop;
}
}

@ -5,6 +5,8 @@ public class RemoveNop implements Transformation {
Instruction pred;
try {
NopOperator op = (NopOperator) ih.getInstruction();
if (op == null)
return null;
ih = ih.getSimpleUniquePredecessor();
pred = ih.getInstruction();
if (pred == null)

@ -236,11 +236,10 @@ public abstract class Opcodes implements RuntimeConstants{
(OBJECT_TYPE, opcode - opc_if_acmpeq+Operator.COMPARE_OP));
case opc_goto:
return InstructionHeader.createGoto
(addr, 3, addr+stream.readShort(), new NopOperator());
(addr, 3, addr+stream.readShort());
case opc_jsr:
return InstructionHeader.createGoto //XXX
(addr, 3, addr+stream.readShort(),
new JsrOperator());
(addr, 3, addr+stream.readShort());
case opc_ret:
return InstructionHeader.createReturn //XXX
(addr, 2,
@ -288,11 +287,8 @@ public abstract class Opcodes implements RuntimeConstants{
(addr, 1, new ReturnOperator(retType));
}
case opc_return: {
Type retType = MyType.intersection
(ca.getMethod().mdef.getType().getReturnType(),
VOID_TYPE);
return InstructionHeader.createReturn
(addr, 1, new ReturnOperator(retType));
(addr, 1, null);
}
case opc_getstatic:
case opc_getfield:
@ -446,10 +442,10 @@ public abstract class Opcodes implements RuntimeConstants{
(OBJECT_TYPE, opcode - opc_ifnull+Operator.COMPARE_OP));
case opc_goto_w:
return InstructionHeader.createGoto
(addr, 5, addr + stream.readInt(), new NopOperator());
(addr, 5, addr + stream.readInt());
case opc_jsr_w:
return InstructionHeader.createGoto
(addr, 5, addr+stream.readInt(), new JsrOperator());
(addr, 5, addr+stream.readInt()); // XXX
default:
throw new ClassFormatError("Invalid opcode "+opcode);
}

@ -58,9 +58,10 @@ public class ClassAnalyzer implements Analyzer {
writer.print(", ");
writer.print(interfaces[i].getName().toString());
}
writer.println("");
}
writer.untab();
writer.println(" {");
writer.println("{");
writer.tab();
for (int i=0; i< fields.length; i++)

@ -73,8 +73,8 @@ public class CodeAnalyzer implements Analyzer, Constants {
static Transformation[] simplifyTrafos = { new SimplifyExpression() };
static Transformation[] blockTrafos = {
new CreateTryCatchStatements(),
new CreateBreakStatement(),
new CreateIfStatements(),
new CreateBreakStatement(),
new CreateWhileStatements(),
new CreateSwitchStatements()
};

@ -8,7 +8,6 @@ import java.util.Enumeration;
public class BreakInstructionHeader extends InstructionHeader {
boolean conditional;
boolean isBreak;
String breakLabel;
/**
@ -18,15 +17,14 @@ public class BreakInstructionHeader extends InstructionHeader {
* @param label the label where to break to, may be null.
* @param isBreak is this a break or a continue.
*/
public BreakInstructionHeader(InstructionHeader gotoHeader,
String label,
boolean isBreak) {
public BreakInstructionHeader(int flowType,
InstructionHeader gotoHeader,
String label) {
super(BREAKSTATEMENT, gotoHeader.addr, gotoHeader.nextAddr,
super(flowType, gotoHeader.addr, gotoHeader.nextAddr,
gotoHeader.successors, gotoHeader.outer);
this.instr = gotoHeader.getInstruction();
this.isBreak = isBreak;
this.conditional = (gotoHeader.flowType == IFGOTO);
this.breakLabel = label;
@ -58,14 +56,9 @@ public class BreakInstructionHeader extends InstructionHeader {
if (conditional) {
writer.println("if ("+instr.toString()+")");
writer.tab();
} else {
if (!(instr instanceof NopOperator)) {
if (instr.getType() != MyType.tVoid)
writer.print("push ");
writer.println(instr.toString()+";");
}
}
writer.println((isBreak?"break":"continue") +
writer.println((flowType == BREAK ? "break" :
flowType == CONTINUE ? "continue" : "return") +
(breakLabel != null?" "+breakLabel:"")+";");
if (conditional)

@ -0,0 +1,58 @@
package jode;
import java.util.Enumeration;
public class CaseInstructionHeader extends InstructionHeader {
int label;
boolean isDefault;
public CaseInstructionHeader(int label, boolean isDefault,
//Type type,
int addr,
InstructionHeader parent) {
super(CASESTATEMENT, addr, addr,
new InstructionHeader[1], parent);
this.label = label;
this.isDefault = isDefault;
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
if (Decompiler.isDebugging) {
dumpDebugging(writer);
writer.tab();
}
if (isDefault) {
if (nextInstruction == null && successors[0] == null)
return;
writer.println("default:");
} else
writer.println("case "+label+":" );
writer.tab();
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
writer.untab();
}
/**
* Get the instruction header where the next instruction is.
*/
InstructionHeader getShadow() {
return (successors[0] != null ? successors[0].getShadow() :
getEndBlock());
}
public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next;
if (successors[0] != getEndBlock()) {
for (InstructionHeader ih = successors[0]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}
}
return super.doTransformations(trafo);
}
}

@ -18,6 +18,10 @@ public class CreateIfThenElseOperator implements Transformation{
while (enum.hasMoreElements()) {
try {
ih = (InstructionHeader) enum.nextElement();
if (ih.flowType == ih.GOTO)
ih = ih.getUniquePredecessor();
Expression zeroExpr = (Expression) ih.getInstruction();
ConstOperator zero =
(ConstOperator) zeroExpr.getOperator();
@ -57,46 +61,54 @@ public class CreateIfThenElseOperator implements Transformation{
return next;
}
public InstructionHeader create(InstructionHeader ih) {
public InstructionHeader create(InstructionHeader ih2) {
InstructionHeader ifHeader;
InstructionHeader gotoIH;
Expression e[] = new Expression[3];
InstructionHeader[] succs;
try {
Vector predec = ih.getPredecessors();
Vector predec = ih2.getPredecessors();
if (predec.size() != 1)
return null;
ifHeader = (InstructionHeader) predec.elementAt(0);
if (ifHeader.getFlowType() != ifHeader.IFGOTO)
return null;
succs = ifHeader.getSuccessors();
if (succs[1] != ih ||
succs[0].getNextInstruction() != succs[1] ||
succs[0].getSuccessors().length != 1 ||
succs[1].getSuccessors().length != 1 ||
succs[0].getSuccessors()[0] != succs[1].getSuccessors()[0])
InstructionHeader ih1 = ifHeader.getSuccessors()[0];
gotoIH = ih1.getNextInstruction();
if (ifHeader.getSuccessors()[1] != ih2 ||
ih1.flowType != ifHeader.NORMAL ||
gotoIH.flowType != ifHeader.GOTO ||
ih2.flowType != ifHeader.NORMAL ||
gotoIH.getNextInstruction() != ih2 ||
gotoIH.getSuccessors()[0] != ih2.getNextInstruction())
return null;
e[0] = ((Expression) ifHeader.getInstruction()).negate();
e[1] = (Expression) succs[0].getInstruction();
e[1] = (Expression) ih1.getInstruction();
if (e[1].isVoid())
return null;
e[2] = (Expression) succs[1].getInstruction();
e[2] = (Expression) ih2.getInstruction();
if (e[2].isVoid())
return null;
e[0] = (Expression) ifHeader.getInstruction();
} catch (ClassCastException ex) {
return null;
} catch (NullPointerException ex) {
return null;
}
if (Decompiler.isVerbose)
System.err.print("?");
e[0] = e[0].negate();
IfThenElseOperator iteo = new IfThenElseOperator
(MyType.intersection(e[1].getType(),e[2].getType()));
ih.instr = new Expression(iteo, e);
ih.movePredecessors(ifHeader);
ih.nextInstruction.predecessors.removeElement(ifHeader.successors[0]);
return ih;
ih2.instr = new Expression(iteo, e);
ih2.movePredecessors(ifHeader);
ih2.nextInstruction.predecessors.removeElement(gotoIH);
return ih2;
}
public InstructionHeader transform(InstructionHeader ih) {

@ -34,65 +34,45 @@ public class IfInstructionHeader extends InstructionHeader {
boolean hasElsePart;
/**
* Creates a new if statement. There are several conditions that
* must be met:
* <ul>
* <li><code> ifHeader.successors[0] == thenStart
* </code></li>
* <li><code> ifHeader.successors[1] == thenEnd.nextInstruction
* </code></li>
* <li><code> elseStart == null || (thenEnd.flowType = GOTO &&
* elseEnd.nextInstruction == thenEnd.successors[0])
* </code></li>
* <li><code> elseStart == null || elseStart = thenEnd.nextInstruction
* </code></li>
* <li><code> thenStart.nextInstruction....nextInstruction = thenEnd
* </code></li>
* <li><code> elseStart.nextInstruction....nextInstruction = elseEnd
* </code></li>
* </ul>
* Creates a new if statement.
* @param ifHeader the instruction header whichs contains the
* if goto statement.
* @param thenStart the start of the then part.
* @param thenEnd the end of the then part.
* @param elseStart the start of the else part.
* @param elseEnd the end of the then part.
* @param next the next instruction after the if statement.
* if goto statement, must have a nextInstruction.
* @param elseBlock the start of the else part, same outer, may be null.
* if not null, it must equals ifHeader.successors[1].
* @param next the next instruction after the if statement,
* same outer, may be null.
* @param endBlock the instruction where the control flows after the if,
* outer may differ, not null.
*/
public IfInstructionHeader(InstructionHeader ifHeader,
boolean hasElsePart,
InstructionHeader thenEnd,
InstructionHeader elseEnd,
InstructionHeader endBlock) {
InstructionHeader elseBlock,
InstructionHeader next) {
super(IFSTATEMENT, ifHeader.addr, endBlock.addr,
super(IFSTATEMENT, ifHeader.addr, ifHeader.addr,
ifHeader.successors, ifHeader.outer);
hasElsePart = elseBlock != null;
this.instr = ((Expression)ifHeader.getInstruction()).negate();
this.movePredecessors(ifHeader);
this.endBlock = endBlock;
/* this.moveSuccessors(ifHeader); */
successors[0].predecessors.removeElement(ifHeader);
successors[1].predecessors.removeElement(ifHeader);
successors[0].predecessors.addElement(this);
successors[1].predecessors.addElement(this);
successors[0].prevInstruction = null;
InstructionHeader next = thenEnd.nextInstruction;
thenEnd.nextInstruction = null;
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)
if (ih.outer == outer)
ih.outer = this;
/* unlink the first instruction of the if */
ifHeader.nextInstruction.prevInstruction = null;
/* unlink the last instruction of the if */
if (next != null)
next.prevInstruction.nextInstruction = null;
this.hasElsePart = hasElsePart;
if (hasElsePart) {
thenEnd.flowType = thenEnd.NORMAL;
successors[1].prevInstruction = null;
next = elseEnd.nextInstruction;
elseEnd.nextInstruction = null;
/* unlink the instructions around the else */
elseBlock.prevInstruction.nextInstruction = null;
elseBlock.prevInstruction = null;
for (InstructionHeader ih = successors[1]; ih != null;
ih = ih.nextInstruction)
@ -100,6 +80,14 @@ public class IfInstructionHeader extends InstructionHeader {
ih.outer = this;
}
/* Do this now, because the end of the then part is cut in
* the else part above.
*/
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)
if (ih.outer == outer)
ih.outer = this;
this.nextInstruction = next;
if (next != null)
next.prevInstruction = this;
@ -136,7 +124,10 @@ public class IfInstructionHeader extends InstructionHeader {
braces = successors[1].flowType != NORMAL ||
successors[1].nextInstruction != null;
if (!braces && successors[1].flowType == IFSTATEMENT) {
if (successors[1].flowType == IFSTATEMENT &&
successors[1].nextInstruction == null) {
/* write "else if" */
braces = false;
writer.print("else ");
successors[1].dumpSource(writer);
} else {

@ -27,7 +27,10 @@ public class InstructionHeader {
public final static int FORSTATEMENT = 13;
public final static int SWITCHSTATEMENT = 14;
public final static int TRYCATCHBLOCK = 15;
public final static int BREAKSTATEMENT = 19;
public final static int CASESTATEMENT = 16;
public final static int BREAK = 20;
public final static int CONTINUE = 21;
public final static int VOIDRETURN = 22;
public final static int EMPTY = 99;
@ -55,12 +58,25 @@ public class InstructionHeader {
*/
InstructionHeader nextInstruction, prevInstruction;
/**
* The first instruction after this block. This should be only
* set for blocks, that is headers which are outer of other headers.
* This gives the instruction where the control flows after this
* block.
* This should be implemented for those blocks, that is headers
* which are outer of other headers. This gives the instruction
* where the control flows after this block.
* @return the first instruction after this block.
*/
InstructionHeader endBlock;
InstructionHeader getEndBlock() {
if (nextInstruction != null) {
return nextInstruction.getShadow();
}
return outer.getEndBlock();
}
/**
* Get the instruction header where this jumps to if this is a
* unconditional goto. Otherwise returns this header.
*/
InstructionHeader getShadow() {
return (flowType == GOTO)? successors[0].getShadow() : this;
}
/**
* A more complex doubly linked list of instructions. The
@ -147,7 +163,8 @@ public class InstructionHeader {
* @param instr The underlying Instruction.
*/
public static InstructionHeader createReturn(int addr, int length,
Instruction instr) {
Instruction instr)
{
return new InstructionHeader(RETURN, addr, addr + length,
instr, new int[0]);
}
@ -159,11 +176,10 @@ public class InstructionHeader {
* @param instr The underlying Instruction.
* @param dest The destination address of the jump.
*/
public static InstructionHeader createGoto(int addr, int length, int dest,
Instruction instr) {
public static InstructionHeader createGoto(int addr, int length, int dest)
{
int [] succs = { dest };
return new InstructionHeader (GOTO, addr, addr + length,
instr, succs);
return new InstructionHeader(GOTO, addr, addr + length, null, succs);
}
/**
@ -309,8 +325,8 @@ public class InstructionHeader {
for (int i=0; i<predecessors.size(); i++) {
InstructionHeader ih =
(InstructionHeader)predecessors.elementAt(i);
if (ih.flowType == GOTO ||
(ih.flowType == IFGOTO && ih.successors[1] == this))
if ((ih.flowType == GOTO || ih.flowType == IFGOTO) &&
ih.getEndBlock() != this)
return true;
}
return false;
@ -368,6 +384,7 @@ public class InstructionHeader {
public void dumpDebugging(TabbedPrintWriter writer)
throws java.io.IOException
{
writer.println("");
writer.print(""+toString()+
": <"+addr + " - "+(nextAddr-1)+"> preds: ");
for (int i=0; i<predecessors.size(); i++) {
@ -375,7 +392,7 @@ public class InstructionHeader {
writer.print(""+predecessors.elementAt(i));
}
writer.println("");
writer.print("out: "+outer+" end: "+endBlock+
writer.print("out: "+outer +
" prev: "+prevInstruction+", next: "+ nextInstruction +
" succs: ");
for (int i=0; i<successors.length; i++) {
@ -402,8 +419,23 @@ public class InstructionHeader {
if (flowType == IFGOTO) {
writer.println("if ("+instr.toString()+") goto "+
successors[1].getLabel());
writer.println("if ("+instr.toString()+")");
writer.tab();
if (successors[1] != getEndBlock())
writer.println("goto "+successors[1].getLabel());
else
writer.println("/*empty*/;");
writer.untab();
} else if (flowType == GOTO) {
if (successors[0] != getEndBlock())
writer.println("goto "+successors[0].getLabel());
} else if (flowType == RETURN) {
writer.println((instr != null ? instr.toString() :
"return") + ";");
} else {
@ -413,8 +445,6 @@ public class InstructionHeader {
writer.print("push ");
writer.println(instr.toString()+";");
}
if (flowType == GOTO)
writer.println("goto "+successors[0].getLabel());
}
}
@ -431,11 +461,13 @@ public class InstructionHeader {
* @param from The instruction header which predecessors are moved.
*/
public void movePredecessors(InstructionHeader from) {
if (this == from)
return;
addr = from.addr;
prevInstruction = from.prevInstruction;
if (prevInstruction != null)
if (prevInstruction != null) {
prevInstruction.nextInstruction = this;
}
predecessors = from.predecessors;
for (int i=0; i < predecessors.size(); i++) {
InstructionHeader pre =
@ -445,6 +477,44 @@ public class InstructionHeader {
if (pre.successors[j] == from)
pre.successors[j] = this;
}
from.predecessors = new Vector();
}
/**
* Moves the predecessors from the InstructionHeader <em>from</em> to
* the current instruction. <p>
* The predecessors of <em>from</em> are informed about this change.
* @param from The instruction header which predecessors are moved.
*/
public void addPredecessors(InstructionHeader from) {
for (int i=0; i < from.predecessors.size(); i++) {
InstructionHeader pre =
(InstructionHeader)from.predecessors.elementAt(i);
predecessors.addElement(pre);
for (int j=0; j < pre.successors.length; j++)
if (pre.successors[j] == from)
pre.successors[j] = this;
}
from.predecessors.removeAllElements();
}
/**
* Moves the successors from the InstructionHeader <em>from</em> to
* the current instruction. The current successors are overwritten
* and you must make sure that is has no live InstructionHeaders.
* Also the <em>from</em> InstructionHeader musnt't be used any more.<p>
*
* The successors of <em>from</em> are informed about this change.
* @param from The instruction header which successors are moved.
*/
public void moveSuccessors(InstructionHeader from) {
successors = from.successors;
from.successors = null;
for (int i=0; i < successors.length; i++) {
successors[i].predecessors.removeElement(from);
successors[i].predecessors.addElement(this);
}
}
/**

@ -8,6 +8,7 @@ import sun.tools.java.Type;
* @author Jochen Hoenicke
*/
public class MethodInstructionHeader extends InstructionHeader {
/**
* Create a new InstructionHeader.
* @param addr The address of this Instruction.
@ -20,7 +21,8 @@ public class MethodInstructionHeader extends InstructionHeader {
super(METHOD, 0, instr.length, new InstructionHeader[1], null);
successors[0] = instr[0];
instr[0].predecessors.addElement(this);
endBlock = new InstructionHeader(EMPTY, instr.length, null);
nextInstruction = new InstructionHeader(EMPTY, instr.length, null);
nextInstruction.prevInstruction = this;
for (int addr = 0; addr < instr.length; addr = instr[addr].nextAddr) {
@ -28,9 +30,15 @@ public class MethodInstructionHeader extends InstructionHeader {
instr[addr].resolveSuccessors(instr);
if (instr[addr].flowType == RETURN) {
InstructionHeader[] retSuccs = { endBlock };
InstructionHeader[] retSuccs = { nextInstruction };
instr[addr].successors = retSuccs;
endBlock.predecessors.addElement(instr[addr]);
nextInstruction.predecessors.addElement(instr[addr]);
if (instr[addr].instr == null) {
/* if this is a void return, replace it by a
* goto to the nextInstruction.
*/
instr[addr].flowType = GOTO;
}
}
}
for (int i=0; i<handlers.length; i++) {
@ -39,7 +47,9 @@ public class MethodInstructionHeader extends InstructionHeader {
instr[handlers[i].startPC] = tryIH =
new TryInstructionHeader(tryIH, this);
Type type = handlers[i].exceptionClass.getType();
Type type =
(handlers[i].exceptionClass != null)?
handlers[i].exceptionClass.getType() : MyType.tVoid;
instr[handlers[i].handlerPC] =
new CatchInstructionHeader
(type, env.getTypeString(type),
@ -56,7 +66,7 @@ public class MethodInstructionHeader extends InstructionHeader {
}
public Vector getReturns() {
return endBlock.predecessors;
return nextInstruction.predecessors;
}
public void dumpSource(TabbedPrintWriter writer)
@ -65,6 +75,9 @@ public class MethodInstructionHeader extends InstructionHeader {
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
// dump the last label if it was used.
nextInstruction.dumpSource(writer);
}
public InstructionHeader doTransformations(Transformation[] trafo) {

@ -33,9 +33,6 @@ import java.util.Enumeration;
*/
public class SwitchInstructionHeader extends InstructionHeader {
int[] cases;
int defaultCase;
/**
* Creates a new if statement. There are several conditions that
* must be met:
@ -64,61 +61,86 @@ public class SwitchInstructionHeader extends InstructionHeader {
*/
public SwitchInstructionHeader(InstructionHeader switchIH,
int []cases,
InstructionHeader []successors,
InstructionHeader []caseIHs,
int defaultCase,
InstructionHeader endBlock) {
super(SWITCHSTATEMENT, switchIH.addr, endBlock.addr,
successors, switchIH.outer);
super(SWITCHSTATEMENT, switchIH.addr, switchIH.nextAddr,
new InstructionHeader[caseIHs.length], switchIH.outer);
this.instr = switchIH.getInstruction();
this.movePredecessors(switchIH);
this.endBlock = endBlock;
this.defaultCase = defaultCase;
this.cases = cases;
/* switchIH may have more succesors than we:
* CreateSwitchStatements removes case labels, that are the
* default.
* And the successors of this switch may differ in case that
* dummy gotos were inserted.
*/
for (int i=0; i<switchIH.successors.length; i++)
switchIH.successors[i].predecessors.removeElement(switchIH);
for (int i=0; i<successors.length; i++)
successors[i].predecessors.addElement(this);
for (int i=0; i<successors.length; i++) {
if (successors[i].outer == outer) {
if (successors[i].prevInstruction != null)
successors[i].prevInstruction.nextInstruction = null;
successors[i].prevInstruction = null;
}
}
if (endBlock.outer == outer) {
if (endBlock.prevInstruction != null)
endBlock.prevInstruction.nextInstruction = null;
nextInstruction = endBlock;
endBlock.prevInstruction = this;
} else {
if (endBlock != outer.endBlock) {
/* Create a goto after this block, that
* jumps to endBlock
*/
nextInstruction = new InstructionHeader
(GOTO, endBlock.addr, endBlock.addr,
new InstructionHeader[1], this);
nextInstruction.instr = new NopOperator(MyType.tVoid);
nextInstruction.prevInstruction = this;
nextInstruction.successors[0] = endBlock;
endBlock.predecessors.addElement(nextInstruction);
} else
nextInstruction = null;
} else if (endBlock.getShadow() == outer.getEndBlock())
nextInstruction = null;
else {
/* Create a goto after this block, that
* jumps to endBlock
*/
nextInstruction = new InstructionHeader
(GOTO, endBlock.addr, endBlock.addr,
new InstructionHeader[1], outer);
nextInstruction.prevInstruction = this;
nextInstruction.successors[0] = endBlock;
endBlock.predecessors.addElement(nextInstruction);
}
for (int i=0; i < successors.length && successors[i] != endBlock; i++)
for (InstructionHeader ih = successors[i]; ih != null;
ih = ih.nextInstruction)
int label = 0;
InstructionHeader lastHeader = null;
InstructionHeader ih = switchIH.nextInstruction;
while (ih != null) {
ih.prevInstruction.nextInstruction = null;
ih.prevInstruction = null;
while (label < caseIHs.length && caseIHs[label] == ih) {
successors[label] = new CaseInstructionHeader
(cases[label], label == defaultCase, ih.addr, this);
if (label > 0) {
successors[label-1].
nextInstruction = successors[label];
successors[label].
prevInstruction = successors[label-1];
}
label++;
}
successors[label-1].successors[0] = ih;
ih.predecessors.addElement(successors[label-1]);
while (ih != null &&
(label == caseIHs.length ||
caseIHs[label] != ih)) {
if (ih.outer == outer)
ih.outer = this;
ih.outer = successors[label-1];
ih = ih.nextInstruction;
}
}
while (label < caseIHs.length) {
successors[label] = new CaseInstructionHeader
(cases[label], label == defaultCase, getEndBlock().addr, this);
if (label > 0) {
successors[label-1].
nextInstruction = successors[label];
successors[label].
prevInstruction = successors[label-1];
}
label++;
}
}
/**
@ -127,7 +149,7 @@ public class SwitchInstructionHeader extends InstructionHeader {
* switch instructions.
*/
public InstructionHeader getBreak() {
return endBlock;
return getEndBlock();
}
public void dumpSource(TabbedPrintWriter writer)
@ -146,23 +168,10 @@ public class SwitchInstructionHeader extends InstructionHeader {
writer.println("switch (" + instr.toString() + ") {");
for (int i=0; i<successors.length; i++) {
if (i != defaultCase)
writer.println("case "+cases[i]+":");
if (successors[i] == endBlock)
break;
if (i+1 < successors.length && successors[i] == successors[i+1])
continue;
if (i == defaultCase)
writer.println("default:");
writer.tab();
for (InstructionHeader ih = successors[i]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
writer.untab();
}
int label = 0;
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
writer.println("} ");
if (Decompiler.isDebugging)
@ -171,11 +180,10 @@ public class SwitchInstructionHeader extends InstructionHeader {
public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next;
for (int i=0; i < successors.length && successors[i] != endBlock; i++)
for (InstructionHeader ih = successors[i]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}
for (InstructionHeader ih = successors[0]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}
return super.doTransformations(trafo);
}
}

@ -70,13 +70,11 @@ public class TryCatchInstructionHeader extends InstructionHeader {
if (tryHeader.nextInstruction != null)
tryHeader.nextInstruction.prevInstruction = null;
}
this.endBlock = endBlock;
if (endBlock.outer == outer) {
nextInstruction = endBlock;
endBlock.prevInstruction = this;
} else {
if (endBlock != outer.endBlock) {
} else if (endBlock.getShadow() != outer.getEndBlock()) {
/* Create a goto after this block, that
* jumps to endBlock
*/
@ -87,9 +85,8 @@ public class TryCatchInstructionHeader extends InstructionHeader {
nextInstruction.prevInstruction = this;
nextInstruction.successors[0] = endBlock;
endBlock.predecessors.addElement(nextInstruction);
} else
nextInstruction = null;
}
} else
nextInstruction = null;
if (endHeader != successors[1])
endHeader.successors[0].predecessors.removeElement(endHeader);
@ -117,14 +114,6 @@ public class TryCatchInstructionHeader extends InstructionHeader {
|| ih.nextInstruction == endBlock)
ih.nextInstruction = null;
if (ih.nextInstruction == null &&
(ih.flowType == GOTO ||
(ih.flowType == RETURN &&
ih.getInstruction().getType() == MyType.tVoid)) &&
ih.successors[0] == endBlock)
ih.flowType = NORMAL;
}
}
}
@ -145,7 +134,7 @@ public class TryCatchInstructionHeader extends InstructionHeader {
writer.println("try {");
writer.tab();
if (successors[0] == endBlock)
if (successors[0] == getEndBlock())
writer.print("/* empty?? */");
else {
for (InstructionHeader ih = successors[0]; ih != null;

@ -28,31 +28,39 @@ import java.util.Enumeration;
public class WhileInstructionHeader extends InstructionHeader {
/**
* Creates a new while statement.
* @param prev the goto instruction in front of this while loop.
* @param ifHeader the instruction header which contains the
* if-goto statement.
* @param blockStart the start of the inner block.
* @param blockEnd the end of the inner block.
* @param next the instruction header after this if block.
* @param gotoHeader the goto instruction in front of this while loop.
* @param ifHeader the instruction header which contains the
* if-goto statement.
*/
public WhileInstructionHeader(InstructionHeader prev,
InstructionHeader ifHeader,
InstructionHeader block) {
public WhileInstructionHeader(InstructionHeader gotoHeader,
InstructionHeader ifHeader) {
super(WHILESTATEMENT,
ifHeader.successors[1].addr, ifHeader.successors[0].addr,
gotoHeader.addr, ifHeader.nextAddr,
ifHeader.successors, ifHeader.outer);
this.instr = ifHeader.instr;
this.outer = ifHeader.outer;
this.endBlock = this;
this.movePredecessors(ifHeader);
this.addr = successors[1].addr;
prev.flowType = NORMAL;
this.addPredecessors(ifHeader);
for (int i=0; i < successors.length; i++) {
successors[i].predecessors.removeElement(ifHeader);
successors[i].predecessors.addElement(this);
}
if (successors[0].flowType == GOTO) {
successors[0].predecessors.removeElement(this);
successors[0] = successors[0].successors[0];
successors[0].predecessors.addElement(this);
}
this.prevInstruction = successors[1].prevInstruction;
if (gotoHeader != ifHeader) {
this.addPredecessors(gotoHeader);
gotoHeader.successors[0].predecessors.removeElement(gotoHeader);
}
this.prevInstruction = gotoHeader.prevInstruction;
if (prevInstruction != null)
prevInstruction.nextInstruction = this;
@ -60,23 +68,28 @@ public class WhileInstructionHeader extends InstructionHeader {
if (nextInstruction != null)
nextInstruction.prevInstruction = this;
successors[0].predecessors.removeElement(ifHeader);
successors[1].predecessors.removeElement(ifHeader);
successors[0].predecessors.addElement(this);
successors[1].predecessors.addElement(this);
if (successors[1] != this) {
successors[1].prevInstruction = null;
for (InstructionHeader ih = successors[1]; ih != null;
ih = ih.nextInstruction) {
if (ih.outer == outer)
ih.outer = this;
if (ih.nextInstruction == this)
if (ih.nextInstruction == ifHeader)
ih.nextInstruction = null;
}
}
}
/**
* This should be implemented for those blocks, that is headers
* which are outer of other headers. This gives the instruction
* where the control flows after this block.
* @return the first instruction after this block.
*/
InstructionHeader getEndBlock() {
return this;
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
@ -91,7 +104,7 @@ public class WhileInstructionHeader extends InstructionHeader {
writer.tab();
}
boolean braces = (successors[1] == this ||
boolean braces = (successors[1].flowType != NORMAL ||
successors[1].nextInstruction != null);
writer.println("while (" + instr.toString() + ")" +
(braces ? " {": ""));

Loading…
Cancel
Save