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