mainly fixing...

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@26 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 27 years ago
parent fe217fd8ac
commit de468af3b8
  1. 40
      jode/jode/decompiler/CodeAnalyzer.java
  2. 74
      jode/jode/flow/CombineIfGotoExpressions.java
  3. 14
      jode/jode/flow/CreateExpression.java
  4. 95
      jode/jode/flow/CreateNewConstructor.java
  5. 151
      jode/jode/flow/FlowBlock.java
  6. 30
      jode/jode/flow/SimplifyExpression.java
  7. 1
      jode/jode/flow/StructuredBlock.java

@ -70,6 +70,7 @@ public class CodeAnalyzer implements Analyzer, Constants {
addr = instr[addr].getNextAddr(); addr = instr[addr].getNextAddr();
} }
methodHeader = instr[0]; methodHeader = instr[0];
methodHeader.makeStartBlock();
/* XXX do something with handlers */ /* XXX do something with handlers */
} }
@ -101,11 +102,11 @@ public class CodeAnalyzer implements Analyzer, Constants {
new jode.flow.CreateExpression(), new jode.flow.CreateExpression(),
// new CreatePostIncExpression(), // new CreatePostIncExpression(),
// new CreateAssignExpression(), // new CreateAssignExpression(),
// new CreateNewConstructor(), new jode.flow.CreateNewConstructor(),
// new CombineIfGotoExpressions(), new jode.flow.CombineIfGotoExpressions(),
// new CreateIfThenElseOperator(), // new CreateIfThenElseOperator(),
// new CreateConstantArray(), // new CreateConstantArray(),
// new SimplifyExpression() new jode.flow.SimplifyExpression()
}; };
public void analyze() public void analyze()
@ -113,6 +114,7 @@ public class CodeAnalyzer implements Analyzer, Constants {
/* XXX optimize */ /* XXX optimize */
Stack todo = new Stack(); Stack todo = new Stack();
FlowBlock flow = methodHeader; FlowBlock flow = methodHeader;
analyzation:
while (true) { while (true) {
/* First do some non flow transformations. */ /* First do some non flow transformations. */
@ -134,31 +136,37 @@ public class CodeAnalyzer implements Analyzer, Constants {
} }
FlowBlock succ = flow.getSuccessor(); FlowBlock succ = flow.getSuccessor();
if (succ != null) { while (succ != null && !flow.doT1(succ)) {
if (!flow.doT1(succ)) { /* T1 transformation failed. */
if (!todo.contains(succ) && succ != flow) {
/* T1 transformation failed, now succeed with /* succ wasn't tried before, succeed with
* successor and put flow on the stack. * successor and put flow on the stack.
*/ */
if (todo.contains(succ)) {
/* This is a sign that the flow graph is not
* reducible. We give up immediately!
*/
break;
}
todo.push(flow); todo.push(flow);
flow = succ; flow = succ;
continue analyzation;
} }
} else {
/* Block has no successor. /* Try the next successor.
*/
succ = flow.getSuccessor(succ);
}
if (succ == null) {
/* the Block has no successor where t1 is applicable.
* *
* If everything is okay the stack should be empty now, * If everything is okay the stack should be empty now,
* and the program is transformed correctly. * and the program is transformed correctly.
* *
* Otherwise flow transformation didn't succeeded. * Otherwise flow transformation didn't succeeded.
*/ */
break; System.err.println("breaking analyzation; flow: "
+ flow.getLabel());
while (!todo.isEmpty()) {
System.err.println("on Stack: "
+ ((FlowBlock)todo.pop()).getLabel());
}
break analyzation;
} }
} }
} }

@ -0,0 +1,74 @@
/*
* CombineIfGotoExpressions (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.flow;
import java.util.Vector;
import jode.Expression;
import jode.MyType;
import jode.BinaryOperator;
public class CombineIfGotoExpressions implements Transformation{
public boolean transform(FlowBlock flow) {
Expression[] e;
ConditionalBlock cb;
Jump prevJump;
int operator;
try {
cb = (ConditionalBlock) flow.lastModified;
SequentialBlock sequBlock = (SequentialBlock) cb.outer;
if (sequBlock.subBlocks[1] != cb)
return false;
// jode.Assert.assert(sequBlock.jump == null)
ConditionalBlock cbprev =
(ConditionalBlock) sequBlock.subBlocks[0];
if (cbprev.jump != null)
return false;
prevJump = ((EmptyBlock) cbprev.trueBlock).jump;
if (prevJump.destination == cb.jump.destination) {
e = new Expression[2];
operator = BinaryOperator.LOG_AND_OP;
e[1] = (Expression)cb.getInstruction();
e[0] = ((Expression)cbprev.getInstruction()).negate();
} else if (prevJump.destination
== ((EmptyBlock) cb.trueBlock).jump.destination) {
e = new Expression[2];
operator = BinaryOperator.LOG_OR_OP;
e[1] = (Expression)cb.getInstruction();
e[0] = (Expression)cbprev.getInstruction();
} else
return false;
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
prevJump.prev.removeJump();
Expression cond =
new Expression(new BinaryOperator(MyType.tBoolean, operator), e);
cb.setInstruction(cond);
cb.replace(cb.outer);
return true;
}
}

@ -44,16 +44,20 @@ public class CreateExpression implements Transformation {
int params; int params;
StructuredBlock block; StructuredBlock block;
try {
System.err.println("Transformation on: "+flow.getLabel());
flow.checkConsistent();
} catch (RuntimeException ex) {
try { try {
jode.TabbedPrintWriter writer = jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " "); new jode.TabbedPrintWriter(System.err, " ");
writer.tab(); writer.tab();
System.err.println("Transformation on: "+flow.getLabel());
flow.block.dumpSource(writer); flow.block.dumpSource(writer);
flow.checkConsistent(); } catch (java.io.IOException ioex) {
System.err.println("; lastModified is: "); }
flow.lastModified.dumpSource(writer); }
} catch (java.io.IOException ex) {}
try { try {
SequentialBlock sequBlock; SequentialBlock sequBlock;
block = flow.lastModified; block = flow.lastModified;

@ -0,0 +1,95 @@
/*
* CreateNewConstructor (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.flow;
import jode.InvokeOperator;
import jode.Expression;
import jode.ConstructorOperator;
import jode.DupOperator;
import jode.NewOperator;
public class CreateNewConstructor implements Transformation{
public boolean transform(FlowBlock flow) {
SequentialBlock sequBlock;
InvokeOperator constrCall;
Expression exprs[];
try {
InstructionBlock block;
block = (InstructionBlock) flow.lastModified;
constrCall = (InvokeOperator) block.getInstruction();
if (!constrCall.isConstructor())
return false;
int params = constrCall.getOperandCount();
exprs = new Expression[params];
sequBlock = (SequentialBlock) block.outer;
if (sequBlock.getSubBlocks()[1] != block)
return false;
for (int i = params-1; i>0; i--) {
block = (InstructionBlock) sequBlock.getSubBlocks()[0];
if (block.jump != null)
return false;
exprs[i] = (Expression) block.getInstruction();
if (exprs[i].isVoid()) {
if (i == params-1)
return false;
Expression e = exprs[i+1].tryToCombine(exprs[i]);
if (e == null)
return false;
i++;
SequentialBlock subExprBlock =
(SequentialBlock) sequBlock.getSubBlocks()[1];
subExprBlock.replace(sequBlock);
sequBlock = subExprBlock;
((InstructionContainer)subExprBlock.getSubBlocks()[0]).
setInstruction(e);
exprs[i] = e;
}
sequBlock = (SequentialBlock)sequBlock.outer;
}
block = (InstructionBlock) sequBlock.getSubBlocks()[0];
DupOperator dup = (DupOperator) block.getInstruction();
if (dup.getCount() != 1 && dup.getDepth() != 0)
return false;
sequBlock = (SequentialBlock)sequBlock.outer;
block = (InstructionBlock) sequBlock.getSubBlocks()[0];
exprs[0] = (Expression) block.getInstruction();
if (exprs[0].isVoid())
return false;
NewOperator op = (NewOperator) exprs[0].getOperator();
if (constrCall.getClassType() != op.getType())
return false;
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
((InstructionContainer) flow.lastModified).setInstruction
(new Expression(new ConstructorOperator(constrCall.getClassType(),
constrCall.getField()),
exprs));
flow.lastModified.replace(sequBlock);
return true;
}
}

@ -70,6 +70,9 @@ public class FlowBlock {
* This is a vector of flow blocks, which reference this block. * This is a vector of flow blocks, which reference this block.
* Only if this vector contains exactly one element, it can be * Only if this vector contains exactly one element, it can be
* moved into the preceding flow block. * moved into the preceding flow block.
*
* If this vectors contains the null element, this is the first
* flow block in a method.
*/ */
Vector predecessors; Vector predecessors;
@ -436,10 +439,11 @@ public class FlowBlock {
/** /**
* Search for an apropriate successor. * Search for an apropriate successor.
* @return the successor with smallest address * @param prevSucc The successor, that was previously tried.
* or null if there isn't a successor at all. * @return the successor with smallest address greater than prevSucc
* or null if there isn't any further successor at all.
*/ */
public FlowBlock getSuccessor() { public FlowBlock getSuccessor(FlowBlock prevSucc) {
/* search successor with smallest addr. */ /* search successor with smallest addr. */
Enumeration enum = successors.elements(); Enumeration enum = successors.elements();
FlowBlock succ = null; FlowBlock succ = null;
@ -448,13 +452,25 @@ public class FlowBlock {
if (jump == null) if (jump == null)
continue; continue;
FlowBlock fb = jump.destination; FlowBlock fb = jump.destination;
if (prevSucc != null && fb.addr <= prevSucc.addr)
continue;
if (succ == null || fb.addr < succ.addr) { if (succ == null || fb.addr < succ.addr) {
System.err.println("trying "+fb.getLabel());
succ = fb; succ = fb;
} }
} }
return succ; return succ;
} }
/**
* Search for an apropriate successor.
* @return the successor with smallest address
* or null if there isn't a successor at all.
*/
public FlowBlock getSuccessor() {
return getSuccessor(null);
}
public void checkConsistent() { public void checkConsistent() {
if (block.outer != null || block.flowBlock != this) { if (block.outer != null || block.flowBlock != this) {
throw new RuntimeException("Inconsistency"); throw new RuntimeException("Inconsistency");
@ -500,18 +516,21 @@ public class FlowBlock {
succ.predecessors.elementAt(0) != this)) succ.predecessors.elementAt(0) != this))
return false; return false;
try { try{
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("doing T1 analysis on: "+getLabel()); System.err.println("doing T1 analysis on: "+getLabel());
block.dumpSource(writer);
checkConsistent(); checkConsistent();
System.err.println("and "+succ.getLabel()); System.err.println("and "+succ.getLabel());
succ.block.dumpSource(writer);
succ.checkConsistent(); succ.checkConsistent();
} catch (java.io.IOException ex) {} } catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
succ.block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* First find the innermost block that contains all jumps to this /* First find the innermost block that contains all jumps to this
* successor and the last modified block. * successor and the last modified block.
@ -599,29 +618,36 @@ public class FlowBlock {
} }
try { try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("before optimizeJump: "+getLabel()); System.err.println("before optimizeJump: "+getLabel());
block.dumpSource(writer);
checkConsistent();
} catch (java.io.IOException ex) {}
checkConsistent(); checkConsistent();
} catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
appendBlock = optimizeJumps(succ, appendBlock); appendBlock = optimizeJumps(succ, appendBlock);
try { try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("after optimizeJump: "+getLabel()); System.err.println("after optimizeJump: "+getLabel());
block.dumpSource(writer);
checkConsistent();
} catch (java.io.IOException ex) {}
System.err.println("XXX");
checkConsistent(); checkConsistent();
} catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* Now remove the jump of the appendBlock if it points to successor. /* Now remove the jump of the appendBlock if it points to successor.
*/ */
if (appendBlock.jump != null && if (appendBlock.jump != null &&
@ -687,34 +713,51 @@ public class FlowBlock {
/* T1 transformation succeeded */ /* T1 transformation succeeded */
try { try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("T1 succeeded:"); System.err.println("T1 succeeded:");
block.dumpSource(writer);
checkConsistent(); checkConsistent();
} catch (java.io.IOException ex) {} } catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
return true; return true;
} }
public boolean doT2() { public boolean doT2() {
/* If there are no jumps to the beginning of this flow block /* If there are no jumps to the beginning of this flow block
* or if this block has other predecessors which weren't * or if this block has other predecessors with a higher
* considered yet, return false. The second condition make * address, return false. The second condition make sure that
* sure that the while isn't created up to the first continue. * the while isn't created up to the first continue. */
*/ if (!predecessors.contains(this))
if (!predecessors.contains(this)
/* || complicated second condition XXX */ )
return false; return false;
Enumeration preds = predecessors.elements();
while (preds.hasMoreElements()) {
FlowBlock predFlow = (FlowBlock) preds.nextElement();
if (predFlow != null && predFlow.addr > addr) {
System.err.println("refusing T2 on: "+getLabel()+
" because of "+predFlow.getLabel());
/* XXX Is this enough to refuse T2 trafo ??? */
return false;
}
}
try { try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("doing T2 analysis on: "+getLabel()); System.err.println("doing T2 analysis on: "+getLabel());
block.dumpSource(writer);
checkConsistent(); checkConsistent();
} catch (java.io.IOException ex) {} } catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* Update the in/out-Vectors now */ /* Update the in/out-Vectors now */
updateInOut(this, false); updateInOut(this, false);
@ -796,13 +839,17 @@ public class FlowBlock {
/* T2 analysis succeeded */ /* T2 analysis succeeded */
try { try {
TabbedPrintWriter writer = System.err.println("T2 succeeded:");
new TabbedPrintWriter(System.err, " "); checkConsistent();
} catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab(); writer.tab();
System.err.println("T2 succeded:");
block.dumpSource(writer); block.dumpSource(writer);
checkConsistent(); } catch (java.io.IOException ioex) {
} catch (java.io.IOException ex) {} }
}
return true; return true;
} }
@ -814,6 +861,7 @@ public class FlowBlock {
Enumeration enum = successors.elements(); Enumeration enum = successors.elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement(); Jump jump = (Jump) enum.nextElement();
if (jump != null) {
if (jump.destAddr == -1) if (jump.destAddr == -1)
jump.destination = END_OF_METHOD; jump.destination = END_OF_METHOD;
else else
@ -822,6 +870,14 @@ public class FlowBlock {
jump.destination.predecessors.addElement(this); jump.destination.predecessors.addElement(this);
} }
} }
}
/**
* Mark the flow block as first flow block in a method.
*/
public void makeStartBlock() {
predecessors.addElement(null);
}
public void removeSuccessor(Jump jump) { public void removeSuccessor(Jump jump) {
successors.setElementAt(null, successors.indexOf(jump)); successors.setElementAt(null, successors.indexOf(jump));
@ -837,7 +893,8 @@ public class FlowBlock {
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
if (label != null) { if (predecessors.size() != 1 ||
predecessors.elementAt(0) != null) {
writer.untab(); writer.untab();
writer.println(label+":"); writer.println(label+":");
writer.tab(); writer.tab();
@ -864,7 +921,7 @@ public class FlowBlock {
*/ */
public String getLabel() { public String getLabel() {
if (label == null) if (label == null)
label = "flow_"+(serialno++)+"_"; label = "flow_"+addr+"_"+(serialno++)+"_";
return label; return label;
} }
} }

@ -0,0 +1,30 @@
/*
* SimplifyExpression (c) 1998 Jochen Hoenicke
*
* You may distribute under the terms of the GNU General Public License.
*
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* $Id$
*/
package jode.flow;
public class SimplifyExpression implements Transformation {
public boolean transform(FlowBlock flow) {
if (flow.lastModified instanceof InstructionContainer) {
InstructionContainer ic = (InstructionContainer) flow.lastModified;
ic.setInstruction(ic.getInstruction().simplify());
}
return false;
}
}

@ -284,6 +284,7 @@ public abstract class StructuredBlock {
* @param succs The vector, the successors should be stored to. * @param succs The vector, the successors should be stored to.
*/ */
public void fillSuccessors(java.util.Vector succs) { public void fillSuccessors(java.util.Vector succs) {
if (jump != null)
succs.addElement(jump); succs.addElement(jump);
StructuredBlock[] subs = getSubBlocks(); StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++) { for (int i=0; i<subs.length; i++) {

Loading…
Cancel
Save