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. 18
      jode/jode/flow/CreateExpression.java
  4. 95
      jode/jode/flow/CreateNewConstructor.java
  5. 165
      jode/jode/flow/FlowBlock.java
  6. 30
      jode/jode/flow/SimplifyExpression.java
  7. 3
      jode/jode/flow/StructuredBlock.java

@ -70,6 +70,7 @@ public class CodeAnalyzer implements Analyzer, Constants {
addr = instr[addr].getNextAddr();
}
methodHeader = instr[0];
methodHeader.makeStartBlock();
/* XXX do something with handlers */
}
@ -101,11 +102,11 @@ public class CodeAnalyzer implements Analyzer, Constants {
new jode.flow.CreateExpression(),
// new CreatePostIncExpression(),
// new CreateAssignExpression(),
// new CreateNewConstructor(),
// new CombineIfGotoExpressions(),
new jode.flow.CreateNewConstructor(),
new jode.flow.CombineIfGotoExpressions(),
// new CreateIfThenElseOperator(),
// new CreateConstantArray(),
// new SimplifyExpression()
new jode.flow.SimplifyExpression()
};
public void analyze()
@ -113,6 +114,7 @@ public class CodeAnalyzer implements Analyzer, Constants {
/* XXX optimize */
Stack todo = new Stack();
FlowBlock flow = methodHeader;
analyzation:
while (true) {
/* First do some non flow transformations. */
@ -134,31 +136,37 @@ public class CodeAnalyzer implements Analyzer, Constants {
}
FlowBlock succ = flow.getSuccessor();
if (succ != null) {
while (succ != null && !flow.doT1(succ)) {
if (!flow.doT1(succ)) {
/* T1 transformation failed, now succeed with
/* T1 transformation failed. */
if (!todo.contains(succ) && succ != flow) {
/* succ wasn't tried before, succeed with
* 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);
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,
* and the program is transformed correctly.
*
* 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;
StructuredBlock block;
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("Transformation on: "+flow.getLabel());
flow.block.dumpSource(writer);
flow.checkConsistent();
System.err.println("; lastModified is: ");
flow.lastModified.dumpSource(writer);
} catch (java.io.IOException ex) {}
} catch (RuntimeException ex) {
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
flow.block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
try {
SequentialBlock sequBlock;
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.
* Only if this vector contains exactly one element, it can be
* moved into the preceding flow block.
*
* If this vectors contains the null element, this is the first
* flow block in a method.
*/
Vector predecessors;
@ -436,10 +439,11 @@ public class FlowBlock {
/**
* Search for an apropriate successor.
* @return the successor with smallest address
* or null if there isn't a successor at all.
* @param prevSucc The successor, that was previously tried.
* @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. */
Enumeration enum = successors.elements();
FlowBlock succ = null;
@ -448,13 +452,25 @@ public class FlowBlock {
if (jump == null)
continue;
FlowBlock fb = jump.destination;
if (prevSucc != null && fb.addr <= prevSucc.addr)
continue;
if (succ == null || fb.addr < succ.addr) {
System.err.println("trying "+fb.getLabel());
succ = fb;
}
}
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() {
if (block.outer != null || block.flowBlock != this) {
throw new RuntimeException("Inconsistency");
@ -500,18 +516,21 @@ public class FlowBlock {
succ.predecessors.elementAt(0) != this))
return false;
try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
try{
System.err.println("doing T1 analysis on: "+getLabel());
block.dumpSource(writer);
checkConsistent();
System.err.println("and "+succ.getLabel());
succ.block.dumpSource(writer);
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
* successor and the last modified block.
@ -599,29 +618,36 @@ public class FlowBlock {
}
try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("before optimizeJump: "+getLabel());
block.dumpSource(writer);
checkConsistent();
} catch (java.io.IOException ex) {}
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.
*/
appendBlock = optimizeJumps(succ, appendBlock);
try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("after optimizeJump: "+getLabel());
block.dumpSource(writer);
checkConsistent();
} catch (java.io.IOException ex) {}
System.err.println("XXX");
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.
*/
if (appendBlock.jump != null &&
@ -687,34 +713,51 @@ public class FlowBlock {
/* T1 transformation succeeded */
try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("T1 succeeded:");
block.dumpSource(writer);
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;
}
public boolean doT2() {
/* If there are no jumps to the beginning of this flow block
* or if this block has other predecessors which weren't
* considered yet, return false. The second condition make
* sure that the while isn't created up to the first continue.
*/
if (!predecessors.contains(this)
/* || complicated second condition XXX */ )
* or if this block has other predecessors with a higher
* address, return false. The second condition make sure that
* the while isn't created up to the first continue. */
if (!predecessors.contains(this))
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 {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("doing T2 analysis on: "+getLabel());
block.dumpSource(writer);
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 */
updateInOut(this, false);
@ -796,13 +839,17 @@ public class FlowBlock {
/* T2 analysis succeeded */
try {
TabbedPrintWriter writer =
new TabbedPrintWriter(System.err, " ");
writer.tab();
System.err.println("T2 succeded:");
block.dumpSource(writer);
System.err.println("T2 succeeded:");
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;
}
@ -814,15 +861,24 @@ public class FlowBlock {
Enumeration enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump.destAddr == -1)
jump.destination = END_OF_METHOD;
else
jump.destination = instr[jump.destAddr];
if (!jump.destination.predecessors.contains(this))
jump.destination.predecessors.addElement(this);
if (jump != null) {
if (jump.destAddr == -1)
jump.destination = END_OF_METHOD;
else
jump.destination = instr[jump.destAddr];
if (!jump.destination.predecessors.contains(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) {
successors.setElementAt(null, successors.indexOf(jump));
}
@ -837,7 +893,8 @@ public class FlowBlock {
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
if (label != null) {
if (predecessors.size() != 1 ||
predecessors.elementAt(0) != null) {
writer.untab();
writer.println(label+":");
writer.tab();
@ -864,7 +921,7 @@ public class FlowBlock {
*/
public String getLabel() {
if (label == null)
label = "flow_"+(serialno++)+"_";
label = "flow_"+addr+"_"+(serialno++)+"_";
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,7 +284,8 @@ public abstract class StructuredBlock {
* @param succs The vector, the successors should be stored to.
*/
public void fillSuccessors(java.util.Vector succs) {
succs.addElement(jump);
if (jump != null)
succs.addElement(jump);
StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++) {
subs[i].fillSuccessors(succs);

Loading…
Cancel
Save