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