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; |
package jode; |
||||||
|
|
||||||
public class CreateWhileStatements implements Transformation { |
public class CreateWhileStatements extends FlowTransformation |
||||||
|
implements Transformation { |
||||||
|
|
||||||
public InstructionHeader transform(InstructionHeader gotoIH) { |
public InstructionHeader transform(InstructionHeader gotoIH) { |
||||||
|
|
||||||
if (gotoIH.flowType != gotoIH.GOTO || gotoIH.nextInstruction == null || |
if (gotoIH.flowType == gotoIH.IFGOTO && |
||||||
gotoIH.successors[0].addr < gotoIH.nextInstruction.addr) |
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; |
return null; |
||||||
|
|
||||||
InstructionHeader block = gotoIH.nextInstruction; |
|
||||||
InstructionHeader ifgoto = gotoIH.successors[0]; |
InstructionHeader ifgoto = gotoIH.successors[0]; |
||||||
|
|
||||||
if (ifgoto.getFlowType() != ifgoto.IFGOTO || |
if (ifgoto.getFlowType() != ifgoto.IFGOTO || |
||||||
ifgoto.successors[1] != block || |
ifgoto.outer != ifgoto.successors[1].outer) |
||||||
ifgoto.outer != block.outer) |
return null; |
||||||
|
|
||||||
|
InstructionHeader next = UnoptimizeWhileLoops(ifgoto.successors[1]); |
||||||
|
if (next != gotoIH.nextInstruction) |
||||||
return null; |
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) |
if(Decompiler.isVerbose) |
||||||
System.err.print("w"); |
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