git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@10 379699f6-c40d-0410-875b-85095c16579estable
parent
6951265a2d
commit
f3f21e7d2c
@ -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); |
||||
} |
||||
} |
||||
|
||||
|
@ -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(); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
Loading…
Reference in new issue