switch,break- but not perfect

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@10 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 6951265a2d
commit f3f21e7d2c
  1. 4
      jode/CombineCatchLocal.java
  2. 37
      jode/CreateBreakStatement.java
  3. 84
      jode/CreateSwitchStatements.java
  4. 13
      jode/CreateTryCatchStatements.java
  5. 3
      jode/CreateWhileStatements.java
  6. 4
      jode/jode/decompiler/CodeAnalyzer.java
  7. 6
      jode/jode/decompiler/LocalInfo.java
  8. 25
      jode/jode/decompiler/LocalVariableAnalyzer.java
  9. 25
      jode/jode/decompiler/MethodAnalyzer.java
  10. 77
      jode/jode/expr/BreakInstructionHeader.java
  11. 1
      jode/jode/expr/CatchInstructionHeader.java
  12. 1
      jode/jode/expr/IfInstructionHeader.java
  13. 8
      jode/jode/expr/InstructionHeader.java
  14. 2
      jode/jode/expr/LocalLoadOperator.java
  15. 39
      jode/jode/expr/MethodInstructionHeader.java
  16. 181
      jode/jode/expr/SwitchInstructionHeader.java
  17. 34
      jode/jode/expr/TryCatchInstructionHeader.java
  18. 41
      jode/jode/expr/WhileInstructionHeader.java

@ -4,7 +4,7 @@ import sun.tools.java.Identifier;
public class CombineCatchLocal implements Transformation{ public class CombineCatchLocal implements Transformation{
static Identifier idException = Identifier.lookup("exception"); // static Identifier idException = Identifier.lookup("exception");
public InstructionHeader transform(InstructionHeader ih) { public InstructionHeader transform(InstructionHeader ih) {
CatchInstructionHeader catchIH; CatchInstructionHeader catchIH;
@ -17,10 +17,8 @@ public class CombineCatchLocal implements Transformation{
Instruction instr = ih.getInstruction(); Instruction instr = ih.getInstruction();
if (instr instanceof PopOperator) { if (instr instanceof PopOperator) {
local = new LocalInfo(99); local = new LocalInfo(99);
local.setName(idException);
} else if (instr instanceof LocalStoreOperator) { } else if (instr instanceof LocalStoreOperator) {
local = ((LocalStoreOperator) instr).getLocalInfo(); local = ((LocalStoreOperator) instr).getLocalInfo();
local.setName(idException);
} else } else
return null; return null;
} catch (ClassCastException ex) { } catch (ClassCastException ex) {

@ -0,0 +1,37 @@
package jode;
public class CreateBreakStatement implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
InstructionHeader breakDest;
if (ih.getFlowType() == ih.GOTO)
breakDest = ih.successors[0];
else if (ih.getFlowType() == ih.IFGOTO)
breakDest = ih.successors[1];
else
return null;
boolean needBreakLabel = false, needContLabel = false;
InstructionHeader outer = ih.outer;
while (outer != null) {
if (outer.getBreak() == breakDest) {
if (Decompiler.isVerbose)
System.err.print("b");
return new BreakInstructionHeader
(ih, needBreakLabel?outer.getLabel(): null, true);
}
if (outer.getContinue() == breakDest) {
if (Decompiler.isVerbose)
System.err.print("b");
return new BreakInstructionHeader
(ih, needContLabel?outer.getLabel(): null, false);
}
if (outer.getBreak() != null)
needBreakLabel = true;
if (outer.getContinue() != null)
needContLabel = true;
outer = outer.outer;
}
return null;
}
}

@ -0,0 +1,84 @@
package jode;
import java.util.Enumeration;
public class CreateSwitchStatements implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
if (ih.getFlowType() != ih.SWITCH)
return null;
SimpleSwitchInstructionHeader switchIH =
(SimpleSwitchInstructionHeader) ih;
int defaultCase = switchIH.successors.length - 1;
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 ++;
}
int[] cases = new int[count];
InstructionHeader[] sorted = new InstructionHeader[count];
count = 0;
for (int i=0; i < switchIH.successors.length; i++) {
if (i != defaultCase &&
switchIH.successors[i] == switchIH.successors[defaultCase])
continue;
int insert;
for (insert = 0; insert < count; insert++) {
if (sorted[insert].addr > switchIH.successors[i].addr)
break;
}
if (insert < count) {
System.arraycopy(cases, insert,
cases, insert+1, count-insert);
System.arraycopy(sorted, insert,
sorted, insert+1, count-insert);
}
if (i == defaultCase)
defaultCase = insert;
else
cases[insert] = switchIH.cases[i];
sorted[insert] = switchIH.successors[i];
count++;
}
InstructionHeader endBlock = switchIH.outer.endBlock;
ih = sorted[count-1];
if (ih.outer == switchIH.outer) {
EndSearch:
while (ih != null) {
Enumeration enum = ih.getPredecessors().elements();
while (enum.hasMoreElements()) {
InstructionHeader pred =
(InstructionHeader)enum.nextElement();
if (pred.addr < sorted[count-1].addr &&
(pred.flowType == ih.GOTO ||
(pred.flowType == ih.IFGOTO &&
pred.successors[1] == ih))) {
endBlock = ih;
break EndSearch;
}
}
// 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;
if(Decompiler.isVerbose)
System.err.print("s");
return new SwitchInstructionHeader
(switchIH, cases, sorted, defaultCase, endBlock);
}
}

@ -44,24 +44,19 @@ public class CreateTryCatchStatements implements Transformation {
remaining[index2++] = tryIH.successors[i+1]; remaining[index2++] = tryIH.successors[i+1];
} }
} }
InstructionHeader endBlock = tryIH.outer.endBlock; InstructionHeader endBlock;
if (endIH != catchIH[1]) { if (endIH != catchIH[1]) {
if ((endIH.flowType != endIH.RETURN || if ((endIH.flowType != endIH.RETURN ||
endIH.getInstruction().getType() != MyType.tVoid) && endIH.getInstruction().getType() != MyType.tVoid) &&
endIH.flowType != endIH.GOTO) endIH.flowType != endIH.GOTO)
return null; return null;
if (endIH.successors[0].outer == tryIH.outer) endBlock = endIH.successors[0];
endBlock = endIH.successors[0]; } else
else if (endIH.successors[0] != endBlock) endBlock = tryIH.outer.endBlock;
return null;
}
if (Decompiler.isVerbose) if (Decompiler.isVerbose)
System.err.print("t"); System.err.print("t");
return new TryCatchInstructionHeader return new TryCatchInstructionHeader
(catchIH, endIH, remaining, endBlock); (catchIH, endIH, remaining, endBlock);
} }
} }

@ -9,9 +9,6 @@ public class CreateWhileStatements implements Transformation {
return null; return null;
InstructionHeader block = gotoIH.nextInstruction; InstructionHeader block = gotoIH.nextInstruction;
if (block == null)
block = gotoIH.outer.endBlock;
InstructionHeader ifgoto = gotoIH.successors[0]; InstructionHeader ifgoto = gotoIH.successors[0];
if (ifgoto.getFlowType() != ifgoto.IFGOTO || if (ifgoto.getFlowType() != ifgoto.IFGOTO ||

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

@ -43,8 +43,10 @@ public class LocalInfo {
if (shadow != null) if (shadow != null)
shadow.combineWith(li); shadow.combineWith(li);
li = li.getLocalInfo(); li = li.getLocalInfo();
if (this != li) if (this != li) {
shadow = li; shadow = li;
li.setType(type);
}
} }
/** /**
@ -98,7 +100,7 @@ public class LocalInfo {
return shadow.setType(newType); return shadow.setType(newType);
this.type = MyType.intersection(this.type, newType); this.type = MyType.intersection(this.type, newType);
if (this.type == MyType.tError) if (this.type == MyType.tError)
System.err.println("Type error in "+name.toString()); System.err.println("Type error in "+getName());
return this.type; return this.type;
} }

@ -120,7 +120,14 @@ public class LocalVariableAnalyzer {
continue; continue;
} }
if (instr.getInstruction() instanceof LocalVarOperator) { if (instr instanceof MethodInstructionHeader) {
/* This is the first instruction
*/
for (int i=0; i < argLocals.length; i++) {
if (reads[i] != null)
argLocals[i].combineWith(reads[i]);
}
} else if (instr.getInstruction() instanceof LocalVarOperator) {
if (Decompiler.isVerbose) if (Decompiler.isVerbose)
System.err.print("."); System.err.print(".");
@ -146,23 +153,13 @@ public class LocalVariableAnalyzer {
} }
predec = instr.getPredecessors().elements(); predec = instr.getPredecessors().elements();
if (predec.hasMoreElements()) { while (predec.hasMoreElements()) {
while (predec.hasMoreElements()) { instrStack.push(predec.nextElement());
instrStack.push(predec.nextElement()); readsStack.push(reads);
readsStack.push(reads);
}
} else {
/* This is the first instruction
*/
for (int i=0; i < argLocals.length; i++) {
if (reads[i] != null)
argLocals[i].combineWith(reads[i]);
}
} }
} }
if (!mdef.isStatic()) if (!mdef.isStatic())
argLocals[0].setName(Constants.idThis); argLocals[0].setName(Constants.idThis);
// System.err.println("done!");
} }
public void createLocalInfo(CodeAnalyzer code) { public void createLocalInfo(CodeAnalyzer code) {

@ -35,21 +35,26 @@ public class MethodAnalyzer implements Analyzer, Constants {
{ {
if (code == null) if (code == null)
return; return;
if (Decompiler.isVerbose) // if (Decompiler.isVerbose)
System.err.print(mdef.getName().toString()+": locals "); // System.err.print(mdef.getName().toString()+": ");
lva.createLocalInfo(code); // lva.createLocalInfo(code);
if (Decompiler.isVerbose) { // code.analyze();
System.err.println(""); // if (Decompiler.isVerbose)
System.err.print("code "); // System.err.println("");
}
code.analyze();
if (Decompiler.isVerbose)
System.err.println("");
} }
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
if (code != null) {
if (Decompiler.isVerbose)
System.err.print(mdef.getName().toString()+": ");
lva.createLocalInfo(code);
code.analyze();
if (Decompiler.isVerbose)
System.err.println("");
}
writer.println(""); writer.println("");
String modif = Modifier.toString(mdef.getModifiers()); String modif = Modifier.toString(mdef.getModifiers());
if (modif.length() > 0) if (modif.length() > 0)

@ -0,0 +1,77 @@
package jode;
import java.util.Enumeration;
/** This instruction header represents an break, continue or an
* if + break/continue statement.
*/
public class BreakInstructionHeader extends InstructionHeader {
boolean conditional;
boolean isBreak;
String breakLabel;
/**
* Creates a new break statement.
* @param gotoHeader the instruction header whichs contains the
* (maybe conditonal) goto statement.
* @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) {
super(BREAKSTATEMENT, gotoHeader.addr, gotoHeader.nextAddr,
gotoHeader.successors, gotoHeader.outer);
this.instr = gotoHeader.getInstruction();
this.isBreak = isBreak;
this.conditional = (gotoHeader.flowType == IFGOTO);
this.breakLabel = label;
this.movePredecessors(gotoHeader);
this.successors = gotoHeader.successors;
for (int i=0; i< successors.length; i++) {
successors[i].predecessors.removeElement(gotoHeader);
successors[i].predecessors.addElement(this);
}
this.nextInstruction = gotoHeader.nextInstruction;
if (nextInstruction != null)
nextInstruction.prevInstruction = this;
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
if (Decompiler.isDebugging) {
dumpDebugging(writer);
writer.tab();
}
if (needsLabel()) {
writer.untab();
writer.println(getLabel()+": ");
writer.tab();
}
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") +
(breakLabel != null?" "+breakLabel:"")+";");
if (conditional)
writer.untab();
if (Decompiler.isDebugging)
writer.untab();
}
}

@ -48,6 +48,7 @@ public class CatchInstructionHeader extends InstructionHeader {
return false; return false;
this.local = local; this.local = local;
local.setType(type);
successors = next.successors; successors = next.successors;
nextInstruction = next.nextInstruction; nextInstruction = next.nextInstruction;
if (nextInstruction != null) if (nextInstruction != null)

@ -71,7 +71,6 @@ public class IfInstructionHeader extends InstructionHeader {
this.instr = ((Expression)ifHeader.getInstruction()).negate(); this.instr = ((Expression)ifHeader.getInstruction()).negate();
this.movePredecessors(ifHeader); this.movePredecessors(ifHeader);
this.outer = ifHeader.outer;
this.endBlock = endBlock; this.endBlock = endBlock;
successors[0].predecessors.removeElement(ifHeader); successors[0].predecessors.removeElement(ifHeader);
successors[1].predecessors.removeElement(ifHeader); successors[1].predecessors.removeElement(ifHeader);

@ -25,7 +25,9 @@ public class InstructionHeader {
public final static int WHILESTATEMENT = 11; public final static int WHILESTATEMENT = 11;
public final static int DOWHILESTATEMENT = 12; public final static int DOWHILESTATEMENT = 12;
public final static int FORSTATEMENT = 13; public final static int FORSTATEMENT = 13;
public final static int TRYCATCHBLOCK = 14; public final static int SWITCHSTATEMENT = 14;
public final static int TRYCATCHBLOCK = 15;
public final static int BREAKSTATEMENT = 19;
public final static int EMPTY = 99; public final static int EMPTY = 99;
@ -298,6 +300,8 @@ public class InstructionHeader {
* Returns true if this instruction header needs a label. * Returns true if this instruction header needs a label.
*/ */
protected boolean needsLabel() { protected boolean needsLabel() {
if (label != null)
return true;
/* An instruction my have only one prevInstruction, but /* An instruction my have only one prevInstruction, but
* may have more then one predecessor that has its * may have more then one predecessor that has its
* nextInstruction pointing to us. * nextInstruction pointing to us.
@ -371,7 +375,7 @@ public class InstructionHeader {
writer.print(""+predecessors.elementAt(i)); writer.print(""+predecessors.elementAt(i));
} }
writer.println(""); writer.println("");
writer.print("outend: "+outer.endBlock+ writer.print("out: "+outer+" end: "+endBlock+
" prev: "+prevInstruction+", next: "+ nextInstruction + " prev: "+prevInstruction+", next: "+ nextInstruction +
" succs: "); " succs: ");
for (int i=0; i<successors.length; i++) { for (int i=0; i<successors.length; i++) {

@ -29,7 +29,7 @@ implements LocalVarOperator {
} }
public Type getType() { public Type getType() {
// System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType()); // System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType());
return local.getType(); return local.getType();
} }

@ -8,8 +8,6 @@ import sun.tools.java.Type;
* @author Jochen Hoenicke * @author Jochen Hoenicke
*/ */
public class MethodInstructionHeader extends InstructionHeader { public class MethodInstructionHeader extends InstructionHeader {
InstructionHeader first, last;
/** /**
* Create a new InstructionHeader. * Create a new InstructionHeader.
* @param addr The address of this Instruction. * @param addr The address of this Instruction.
@ -19,30 +17,21 @@ public class MethodInstructionHeader extends InstructionHeader {
public MethodInstructionHeader(JodeEnvironment env, public MethodInstructionHeader(JodeEnvironment env,
InstructionHeader[] instr, InstructionHeader[] instr,
BinaryExceptionHandler[] handlers) { BinaryExceptionHandler[] handlers) {
super(METHOD, 0, instr.length, new InstructionHeader[0], null); super(METHOD, 0, instr.length, new InstructionHeader[1], null);
first = new InstructionHeader(EMPTY, 0, this); successors[0] = instr[0];
last = new InstructionHeader(EMPTY, instr.length, this); instr[0].predecessors.addElement(this);
endBlock = new InstructionHeader(EMPTY, instr.length, null);
first.nextInstruction = instr[0];
instr[0].prevInstruction = first;
for (int addr = 0; ; addr = instr[addr].nextAddr) { for (int addr = 0; addr < instr.length; addr = instr[addr].nextAddr) {
instr[addr].outer = this; instr[addr].outer = this;
instr[addr].resolveSuccessors(instr); instr[addr].resolveSuccessors(instr);
if (instr[addr].flowType == RETURN) { if (instr[addr].flowType == RETURN) {
InstructionHeader[] lastArr = { last }; InstructionHeader[] retSuccs = { endBlock };
instr[addr].successors = lastArr; instr[addr].successors = retSuccs;
last.predecessors.addElement(instr[addr]); endBlock.predecessors.addElement(instr[addr]);
}
if (instr[addr].nextAddr == instr.length) {
instr[addr].nextInstruction = last;
last.prevInstruction = instr[addr];
break;
} }
} }
for (int i=0; i<handlers.length; i++) { for (int i=0; i<handlers.length; i++) {
InstructionHeader tryIH = instr[handlers[i].startPC]; InstructionHeader tryIH = instr[handlers[i].startPC];
@ -60,29 +49,27 @@ public class MethodInstructionHeader extends InstructionHeader {
InstructionHeader catchIH = instr[handlers[i].handlerPC]; InstructionHeader catchIH = instr[handlers[i].handlerPC];
((TryInstructionHeader)tryIH).addHandler(endIH, catchIH); ((TryInstructionHeader)tryIH).addHandler(endIH, catchIH);
} }
endBlock = last;
} }
public InstructionHeader getFirst() { public InstructionHeader getFirst() {
return first.nextInstruction; return successors[0];
} }
public Vector getReturns() { public Vector getReturns() {
return last.predecessors; return endBlock.predecessors;
} }
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
for (InstructionHeader ih = first.nextInstruction; for (InstructionHeader ih = successors[0]; ih != null;
ih != last; ih = ih.nextInstruction) ih = ih.nextInstruction)
ih.dumpSource(writer); ih.dumpSource(writer);
} }
public InstructionHeader doTransformations(Transformation[] trafo) { public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next; InstructionHeader next;
for (InstructionHeader ih = first.nextInstruction; for (InstructionHeader ih = successors[0]; ih != null; ih = next) {
ih != last; ih = next) {
if ((next = ih.doTransformations(trafo)) == null) if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction(); next = ih.getNextInstruction();
} }

@ -0,0 +1,181 @@
package jode;
import java.util.Enumeration;
/**
* This instruction header represents an if instruction. The
* linkage of the instructions is as follow:
* <pre>
* A: ....
* <p>
* prev = A, next = H, pred = normal, succ = {C,E}
* B: switch ( value ) {
* <p>
* case 1:
* <p>
* prev = null, next = D, pred = {B}, succ = {D}
* C: then-instr 1
* <p>
* prev = C, next = H!, pred = normal succ = {E}
* D: instructions of then part
* <p>
* case 2:
* <p>
* prev = null, next = D, pred = {B}, succ = {D}
* E: else-instr 1
* <p>
* prev = E, next = null, pred = normal, succ = normal
* F: instructions of then part
* <p>
* }
* prev = B, ..., pred = normal, succ = normal
* H: ...
* </pre>
*/
public class SwitchInstructionHeader extends InstructionHeader {
int[] cases;
int defaultCase;
/**
* 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>
* @param ifHeader the instruction header whichs contains the
* if goto statement.
* @param cases the values belonging to the case labels.
* @param successors the successors of this instruction (the cases).
* This array must be sorted from low to high addresses.
* @param defaultCase the position of the default case in the array.
* @param endBlock the next instruction after this switch statement.
*/
public SwitchInstructionHeader(InstructionHeader switchIH,
int []cases,
InstructionHeader []successors,
int defaultCase,
InstructionHeader endBlock) {
super(SWITCHSTATEMENT, switchIH.addr, endBlock.addr,
successors, 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.
*/
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;
}
for (int i=0; i < successors.length && successors[i] != endBlock; i++)
for (InstructionHeader ih = successors[i]; ih != null;
ih = ih.nextInstruction)
if (ih.outer == outer)
ih.outer = this;
}
/**
* Returns the InstructionHeader where a break of this instruction
* would jump to. Does only make sense for do/while/for-loops and
* switch instructions.
*/
public InstructionHeader getBreak() {
return endBlock;
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
if (Decompiler.isDebugging) {
dumpDebugging(writer);
writer.tab();
}
if (needsLabel()) {
writer.untab();
writer.println(getLabel()+": ");
writer.tab();
}
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();
}
writer.println("} ");
if (Decompiler.isDebugging)
writer.untab();
}
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();
}
return super.doTransformations(trafo);
}
}

@ -64,16 +64,32 @@ public class TryCatchInstructionHeader extends InstructionHeader {
tryHeader.prevInstruction = null; tryHeader.prevInstruction = null;
tryHeader.successors = remaining; tryHeader.successors = remaining;
} else { } else {
successors[0] = tryHeader.nextInstruction; successors[0] = tryHeader.successors[0];
if (successors[0] != null) { successors[0].predecessors.removeElement(tryHeader);
successors[0].prevInstruction = null; successors[0].predecessors.addElement(this);
successors[0].predecessors.addElement(this); if (tryHeader.nextInstruction != null)
} tryHeader.nextInstruction.prevInstruction = null;
} }
this.endBlock = endBlock; this.endBlock = endBlock;
this.nextInstruction = (endBlock.outer == outer) ? endBlock : null;
if (nextInstruction != null) if (endBlock.outer == outer) {
nextInstruction = endBlock;
endBlock.prevInstruction = this; 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;
}
if (endHeader != successors[1]) if (endHeader != successors[1])
endHeader.successors[0].predecessors.removeElement(endHeader); endHeader.successors[0].predecessors.removeElement(endHeader);
@ -129,8 +145,8 @@ public class TryCatchInstructionHeader extends InstructionHeader {
writer.println("try {"); writer.println("try {");
writer.tab(); writer.tab();
if (successors[0] == null) if (successors[0] == endBlock)
writer.print("/* empty */"); writer.print("/* empty?? */");
else { else {
for (InstructionHeader ih = successors[0]; ih != null; for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction) ih = ih.nextInstruction)

@ -60,18 +60,21 @@ public class WhileInstructionHeader extends InstructionHeader {
if (nextInstruction != null) if (nextInstruction != null)
nextInstruction.prevInstruction = this; nextInstruction.prevInstruction = this;
successors[1].prevInstruction = null;
ifHeader.prevInstruction.nextInstruction = null;
successors[0].predecessors.removeElement(ifHeader); successors[0].predecessors.removeElement(ifHeader);
successors[1].predecessors.removeElement(ifHeader); successors[1].predecessors.removeElement(ifHeader);
successors[0].predecessors.addElement(this); successors[0].predecessors.addElement(this);
successors[1].predecessors.addElement(this); successors[1].predecessors.addElement(this);
for (InstructionHeader ih = successors[1]; ih != null; if (successors[1] != this) {
ih = ih.nextInstruction) successors[1].prevInstruction = null;
if (ih.outer == outer) for (InstructionHeader ih = successors[1]; ih != null;
ih.outer = this; ih = ih.nextInstruction) {
if (ih.outer == outer)
ih.outer = this;
if (ih.nextInstruction == this)
ih.nextInstruction = null;
}
}
} }
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
@ -88,14 +91,18 @@ public class WhileInstructionHeader extends InstructionHeader {
writer.tab(); writer.tab();
} }
boolean braces = successors[1].nextInstruction != null; boolean braces = (successors[1] == this ||
successors[1].nextInstruction != null);
writer.println("while (" + instr.toString() + ")" + writer.println("while (" + instr.toString() + ")" +
(braces ? " {": "")); (braces ? " {": ""));
writer.tab(); writer.tab();
for (InstructionHeader ih = successors[1]; ih != null; if (successors[1] != this) {
ih = ih.nextInstruction) for (InstructionHeader ih = successors[1]; ih != null;
ih.dumpSource(writer); ih = ih.nextInstruction)
ih.dumpSource(writer);
} else
writer.println("/* empty */");
writer.untab(); writer.untab();
if (braces) if (braces)
@ -124,10 +131,12 @@ public class WhileInstructionHeader extends InstructionHeader {
public InstructionHeader doTransformations(Transformation[] trafo) { public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next; InstructionHeader next;
for (InstructionHeader ih = successors[1]; ih != null; ih = next) { if (successors[1] != this)
if ((next = ih.doTransformations(trafo)) == null) for (InstructionHeader ih = successors[1]; ih != null; ih = next) {
next = ih.getNextInstruction(); if ((next = ih.doTransformations(trafo)) == null)
} next = ih.getNextInstruction();
}
return super.doTransformations(trafo); return super.doTransformations(trafo);
} }
} }

Loading…
Cancel
Save