git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@72 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 27 years ago
parent 62fa808a9b
commit c9ed2748de
  1. 39
      jode/jode/bytecode/Opcodes.java
  2. 10
      jode/jode/decompiler/ClassAnalyzer.java
  3. 10
      jode/jode/decompiler/LocalInfo.java
  4. 71
      jode/jode/expr/ComplexExpression.java
  5. 16
      jode/jode/expr/ConstOperator.java
  6. 53
      jode/jode/expr/Expression.java
  7. 2
      jode/jode/expr/IIncOperator.java
  8. 2
      jode/jode/expr/MonitorEnterOperator.java
  9. 2
      jode/jode/expr/MonitorExitOperator.java
  10. 29
      jode/jode/expr/NopOperator.java
  11. 4
      jode/jode/expr/PopOperator.java
  12. 20
      jode/jode/flow/CaseBlock.java
  13. 64
      jode/jode/flow/CatchBlock.java
  14. 40
      jode/jode/flow/CatchFinallyBlock.java
  15. 100
      jode/jode/flow/CombineIfGotoExpressions.java
  16. 14
      jode/jode/flow/ConditionalBlock.java
  17. 28
      jode/jode/flow/CreateAssignExpression.java
  18. 26
      jode/jode/flow/CreateConstantArray.java
  19. 123
      jode/jode/flow/CreateExpression.java
  20. 23
      jode/jode/flow/CreateForInitializer.java
  21. 13
      jode/jode/flow/CreateIfThenElseOperator.java
  22. 74
      jode/jode/flow/CreateNewConstructor.java
  23. 25
      jode/jode/flow/CreatePrePostIncExpression.java
  24. 602
      jode/jode/flow/FlowBlock.java
  25. 6
      jode/jode/flow/IfThenElseBlock.java
  26. 24
      jode/jode/flow/InstructionBlock.java
  27. 12
      jode/jode/flow/InstructionContainer.java
  28. 37
      jode/jode/flow/LoopBlock.java
  29. 46
      jode/jode/flow/RemoveEmpty.java
  30. 20
      jode/jode/flow/ReturnBlock.java
  31. 3
      jode/jode/flow/SequentialBlock.java
  32. 9
      jode/jode/flow/StructuredBlock.java
  33. 11
      jode/jode/flow/SwitchBlock.java
  34. 4
      jode/jode/flow/SynchronizedBlock.java
  35. 4
      jode/jode/flow/ThrowBlock.java

@ -257,16 +257,24 @@ public abstract class Opcodes {
public static FlowBlock createNormal(CodeAnalyzer ca,
int addr, int length,
Instruction instr)
Expression instr)
{
return new FlowBlock(ca, addr, length,
new InstructionBlock(instr,
new Jump(addr+length)));
}
public static FlowBlock createSpecial(CodeAnalyzer ca,
int addr, int length,
int type, int stackcount, int param)
{
return new FlowBlock(ca, addr, length,
new SpecialBlock(type, stackcount, param,
new Jump(addr+length)));
}
public static FlowBlock createGoto(CodeAnalyzer ca,
int addr, int length,
int destAddr)
int addr, int length, int destAddr)
{
return new FlowBlock(ca, addr, length,
new EmptyBlock(new Jump(destAddr)));
@ -283,7 +291,7 @@ public abstract class Opcodes {
public static FlowBlock createIfGoto(CodeAnalyzer ca,
int addr, int length,
int destAddr, Instruction instr)
int destAddr, Expression instr)
{
ConditionalBlock ifBlock =
new ConditionalBlock(instr,
@ -297,7 +305,7 @@ public abstract class Opcodes {
int[] cases, int[] dests)
{
return new FlowBlock(ca, addr, length,
new SwitchBlock(new NopOperator(Type.tInt),
new SwitchBlock(new NopOperator(Type.tUInt),
cases, dests));
}
@ -441,11 +449,11 @@ public abstract class Opcodes {
(ca, addr, 1, new PopOperator(opcode - opc_pop + 1));
case opc_dup: case opc_dup_x1: case opc_dup_x2:
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2:
return createNormal
(ca, addr, 1, new DupOperator
((opcode - opc_dup)%3, (opcode - opc_dup)/3+1));
return createSpecial
(ca, addr, 1, SpecialBlock.DUP,
(opcode - opc_dup)/3+1, (opcode - opc_dup)%3);
case opc_swap:
return createNormal(ca, addr, 1, new SwapOperator());
return createSpecial(ca, addr, 1, SpecialBlock.SWAP, 1, 0);
case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd:
case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub:
case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul:
@ -629,8 +637,9 @@ public abstract class Opcodes {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal
(ca, addr, 3, new NewOperator(type, type.toString()));
(ca, addr, 3, new NewOperator(type));
}
case opc_newarray: {
Type type;
@ -646,6 +655,7 @@ public abstract class Opcodes {
default:
throw new ClassFormatError("Invalid newarray operand");
}
type.useType();
return createNormal
(ca, addr, 2, new NewArrayOperator(Type.tArray(type), 1));
}
@ -654,6 +664,7 @@ public abstract class Opcodes {
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal
(ca, addr, 3, new NewArrayOperator(Type.tArray(type), 1));
}
@ -670,18 +681,18 @@ public abstract class Opcodes {
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal
(ca, addr, 3, new CheckCastOperator
(type, type.toString()));
(ca, addr, 3, new CheckCastOperator(type));
}
case opc_instanceof: {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal
(ca, addr, 3,
new InstanceOfOperator(type, type.toString()));
(ca, addr, 3, new InstanceOfOperator(type));
}
case opc_monitorenter:
return createNormal(ca, addr, 1,

@ -54,15 +54,9 @@ public class ClassAnalyzer implements Analyzer {
Field[] fields = clazz.getDeclaredFields();
Method[] methods = clazz.getDeclaredMethods();
Constructor[] constrs = clazz.getDeclaredConstructors();
Class[] clazzes = clazz.getDeclaredClasses();
analyzers = new Analyzer[fields.length + methods.length
+ constrs.length + clazzes.length];
for (int j=0; j< clazzes.length; j++) {
analyzers[i] = new ClassAnalyzer(this, clazzes[j], env);
analyzers[i++].analyze();
}
analyzers = new Analyzer[fields.length + methods.length
+ constrs.length];
for (int j=0; j< fields.length; j++) {
analyzers[i] = new FieldAnalyzer(this, fields[j], env);

@ -85,7 +85,7 @@ public class LocalInfo {
LocalVarOperator lvo =
(LocalVarOperator) enum.nextElement();
if (needTypeUpdate) {
// System.err.println("updating "+lvo+" in "+((Expression)lvo).parent);
// System.err.println("updating "+lvo+" in "+lvo.parent);
lvo.updateType();
}
shadow.operators.addElement(lvo);
@ -163,13 +163,17 @@ public class LocalInfo {
public Type setType(Type newType) {
LocalInfo li = getLocalInfo();
newType = li.type.intersection(newType);
// System.err.println(getName()+" setType, new: "+newType+" old: "+li.type);
if (Decompiler.isTypeDebugging)
System.err.println(getName()+" setType, new: "+newType
+ " old: "+li.type);
if (!li.type.equals(newType)) {
li.type = newType;
java.util.Enumeration enum = li.operators.elements();
while (enum.hasMoreElements()) {
LocalVarOperator lvo = (LocalVarOperator) enum.nextElement();
// System.err.println("updating "+lvo+" in "+((Expression)lvo).parent);
if (Decompiler.isTypeDebugging)
System.err.println("updating "+lvo+" in "
+ ((Expression)lvo).parent);
lvo.updateType();
}
}

@ -69,34 +69,59 @@ public class ComplexExpression extends Expression {
return new ComplexExpression(negop, new Expression[] { this });
}
public Expression tryToCombine(Expression e) {
/**
* Checks if the given Expression (which should be a StoreInstruction)
* can be combined into this expression.
* @param e The store expression.
* @return 1, if it can, 0, if no match was found and -1, if a
* conflict was found. You may wish to check for >0.
*/
public int canCombine(Expression e) {
if (e instanceof ComplexExpression
&& e.getOperator() instanceof StoreInstruction) {
ComplexExpression ce = (ComplexExpression) e;
StoreInstruction store = (StoreInstruction) e.getOperator();
if (store.matches(operator)) {
int i;
for (i=0; i < ce.subExpressions.length-1; i++) {
for (int i=0; i < ce.subExpressions.length-1; i++) {
if (!ce.subExpressions[i].equals(subExpressions[i]))
break;
}
if (i == ce.subExpressions.length-1) {
operator =
new AssignOperator(store.getOperatorIndex(), store);
subExpressions = ce.subExpressions;
return this;
return -1;
}
return 1;
}
for (int i=0; i < subExpressions.length; i++) {
Expression combined = subExpressions[i].tryToCombine(e);
if (combined != null) {
subExpressions[i] = combined;
subExpressions[i].parent = this;
return this;
}
int can = subExpressions[i].canCombine(e);
if (can != 0)
return can;
}
}
return null;
return 0;
}
/**
* Combines the given Expression (which should be a StoreInstruction)
* into this expression. You must only call this if
* canCombine returns the value 1.
* @param e The store expression.
* @return The combined expression.
*/
public Expression combine(Expression e) {
StoreInstruction store = (StoreInstruction) e.getOperator();
if (store.matches(operator)) {
((ComplexExpression) e).operator =
new AssignOperator(store.getOperatorIndex(), store);
this.subExpressions = ((ComplexExpression) e).subExpressions;
return e;
}
for (int i=0; i < subExpressions.length; i++) {
Expression combined = subExpressions[i].combine(e);
if (combined != null) {
subExpressions[i] = combined;
subExpressions[i].parent = this;
return this;
}
}
throw new AssertError("combine didn't succeed");
}
public Operator getOperator() {
@ -234,7 +259,7 @@ public class ComplexExpression extends Expression {
return new ComplexExpression
(new StringAddOperator(), new Expression[]
{ e, (Expression)subExpressions[1].simplify() });
{ e, subExpressions[1].simplify() });
}
if (operator instanceof ConstructorOperator &&
operator.getType().isOfType(Type.tStringBuffer)) {
@ -243,12 +268,12 @@ public class ComplexExpression extends Expression {
return emptyString;
else if (subExpressions.length == 2 &&
subExpressions[1].getType().isOfType(Type.tString))
return (Expression) subExpressions[1].simplify();
return subExpressions[1].simplify();
}
return null;
}
public Instruction simplify() {
public Expression simplify() {
if (operator instanceof IfThenElseOperator &&
operator.getType().isOfType(Type.tBoolean)) {
if (subExpressions[1].getOperator() instanceof ConstOperator &&
@ -334,7 +359,7 @@ public class ComplexExpression extends Expression {
.replace(java.io.File.separatorChar, '.')
.equals("java.lang.StringBuffer"))
&& subExpressions.length == 1) {
Instruction simple = subExpressions[0].simplifyStringBuffer();
Expression simple = subExpressions[0].simplifyStringBuffer();
if (simple != null)
return simple;
}
@ -352,10 +377,10 @@ public class ComplexExpression extends Expression {
return new ComplexExpression
(new StringAddOperator(), new Expression[]
{ emptyString, (Expression) subExpressions[0].simplify() });
{ emptyString, subExpressions[0].simplify() });
}
for (int i=0; i< subExpressions.length; i++) {
subExpressions[i] = (Expression) subExpressions[i].simplify();
subExpressions[i] = subExpressions[i].simplify();
subExpressions[i].parent = this;
}
return this;

@ -46,6 +46,22 @@ public class ConstOperator extends NoArgOperator {
return "false";
else if (value.equals("1"))
return "true";
} if (type == Type.tChar) {
char i = (char) Integer.parseInt(value);
switch (i) {
case '\t':
return "\'\\t\'";
case '\n':
return "\'\\n\'";
case '\\':
return "\'\\\\\'";
case '\"':
return "\'\\\"\'";
case '\'':
return "\'\\\'\'";
}
if (i >= 32 && i <128)
return "\'"+i+"\'";
} else if (parent != null) {
int opindex = parent.getOperator().getOperatorIndex();
if (opindex >= OPASSIGN_OP + ADD_OP

@ -19,12 +19,21 @@
package jode;
public abstract class Expression extends Instruction {
public abstract class Expression {
protected Type type;
ComplexExpression parent = null;
public Expression(Type type) {
super (type);
this.type = type;
}
public Type getType() {
return type;
}
public void setType(Type newType) {
this.type = newType;
}
/**
@ -39,19 +48,39 @@ public abstract class Expression extends Instruction {
return new ComplexExpression(negop, new Expression[] { this });
}
public Expression tryToCombine(Expression e) {
/**
* Checks if the given Expression (which should be a StoreInstruction)
* can be combined into this expression.
* @param e The store expression.
* @return 1, if it can, 0, if no match was found and -1, if a
* conflict was found. You may wish to check for >0.
*/
public int canCombine(Expression e) {
if (e instanceof ComplexExpression
&& e.getOperator() instanceof StoreInstruction) {
ComplexExpression ce = (ComplexExpression) e;
StoreInstruction store = (StoreInstruction) e.getOperator();
if (store.matches(getOperator())
&& ce.subExpressions.length == 1) {
return new ComplexExpression
(new AssignOperator(store.getOperatorIndex(), store),
ce.subExpressions);
}
if (store.matches(getOperator()))
return 1;
}
return null;
return 0;
}
/**
* Combines the given Expression (which should be a StoreInstruction)
* into this expression. You must only call this if
* canCombine returns the value 1.
* @param e The store expression.
* @return The combined expression.
*/
public Expression combine(Expression e) {
StoreInstruction store = (StoreInstruction) e.getOperator();
((ComplexExpression)e).operator
= new AssignOperator(store.getOperatorIndex(), store);
return e;
}
public Expression simplify() {
return this;
}
Expression simplifyStringBuffer() {
@ -60,6 +89,8 @@ public abstract class Expression extends Instruction {
public abstract Operator getOperator();
public abstract String toString();
String toString(int minPriority) {
String result = toString();
if (getOperator().getPriority() < minPriority)

@ -63,7 +63,7 @@ implements LocalVarOperator {
== local.getLocalInfo();
}
public Instruction simplify() {
public Expression simplify() {
if (value.equals("1")) {
int op = (getOperatorIndex() == OPASSIGN_OP+ADD_OP)
? INC_OP : DEC_OP;

@ -34,6 +34,6 @@ public class MonitorEnterOperator extends SimpleOperator {
}
public String toString(String[] operands) {
return "monitorenter "+operands[0];
return "MONITORENTER "+operands[0];
}
}

@ -38,6 +38,6 @@ public class MonitorExitOperator extends SimpleOperator {
}
public String toString(String[] operands) {
return "monitorexit "+operands[0];
return "MONITOREXIT "+operands[0];
}
}

@ -19,21 +19,38 @@
package jode;
public class NopOperator extends Instruction {
/**
* A NopOperator takes one or zero arguments and returns it again. It
* is mainly used as placeholder when the real operator is not yet
* known (e.g. in SwitchBlock). But there also exists a nop opcode in
* the java virtual machine (The compiler can't create such a opcode,
* though).
*
* @author Jochen Hoenicke */
public class NopOperator extends SimpleOperator {
public NopOperator(Type type) {
super(type);
super(type, 0, 1);
}
public NopOperator() {
this(Type.tVoid);
super(Type.tVoid, 0, 0);
}
public int getPriority() {
return 0;
}
public int getOperandPriority(int i) {
return 0;
}
public boolean equals(Object o) {
return (o instanceof NopOperator);
}
public String toString()
{
return "nop";
public String toString(String[] operands) {
if (type == Type.tVoid)
return "/* nop */";
return operands[0];
}
}

@ -36,6 +36,10 @@ public class PopOperator extends SimpleOperator {
return 0;
}
public int getCount() {
return count;
}
public String toString(String[] operands) {
return operands[0];
}

@ -17,6 +17,7 @@
* $Id$
*/
package jode.flow;
import jode.ConstOperator;
/**
* This block represents a case instruction. A case instruction is a
@ -46,11 +47,6 @@ public class CaseBlock extends StructuredBlock {
*/
boolean isLastBlock;
/**
* The type of the switch value.
*/
jode.Type type;
public CaseBlock(int value) {
this.value = value;
subBlock = null;
@ -62,6 +58,12 @@ public class CaseBlock extends StructuredBlock {
subBlock.outer = this;
}
public void checkConsistent() {
if (!(outer instanceof SwitchBlock))
throw new jode.AssertError("Inconsistency");
super.checkConsistent();
}
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
@ -95,8 +97,12 @@ public class CaseBlock extends StructuredBlock {
&& subBlock.jump == null)
return;
writer.println("default:");
} else
writer.println("case " + value /*XXX-type*/ + ":");
} else {
ConstOperator constOp = new ConstOperator
(((SwitchBlock)outer).getInstruction().getType(),
Integer.toString(value));
writer.println("case " + constOp.toString()+":");
}
if (subBlock != null) {
writer.tab();
subBlock.dumpSource(writer);

@ -19,6 +19,8 @@
package jode.flow;
import jode.Type;
import jode.LocalInfo;
import jode.Expression;
import jode.PopOperator;
/**
*
@ -63,45 +65,38 @@ public class CatchBlock extends StructuredBlock {
* @param catchBlock the catch block.
*/
public void setCatchBlock(StructuredBlock catchBlock) {
if ((catchBlock instanceof SequentialBlock
&& catchBlock.getSubBlocks()[0] instanceof InstructionBlock)
|| catchBlock instanceof InstructionBlock) {
jode.Instruction instr =
((InstructionBlock) (catchBlock instanceof InstructionBlock
? catchBlock
: catchBlock.getSubBlocks()[0])
).getInstruction();
if (instr instanceof jode.PopOperator) {
this.catchBlock = catchBlock;
catchBlock.outer = this;
catchBlock.setFlowBlock(flowBlock);
StructuredBlock firstInstr = (catchBlock instanceof SequentialBlock)
? catchBlock.getSubBlocks()[0] : catchBlock;
if (firstInstr instanceof InstructionBlock) {
Expression instr =
((InstructionBlock) firstInstr).getInstruction();
if (instr instanceof PopOperator
&& ((PopOperator) instr).getCount() == 1) {
/* The exception is ignored. Create a dummy local for it */
exceptionLocal = new LocalInfo(-1);
exceptionLocal.setName("exception_"+(serialno++)+"_");
exceptionLocal.setType(exceptionType);
} else if (instr instanceof jode.LocalStoreOperator) {
/* The exception is stored in a local variable */
exceptionLocal =
((jode.LocalStoreOperator) instr).getLocalInfo();
}
if (exceptionLocal != null) {
StructuredBlock newCatchBlock =
(catchBlock instanceof InstructionBlock
? new EmptyBlock()
: catchBlock.getSubBlocks()[1]);
if (catchBlock.jump != null)
newCatchBlock.moveJump(catchBlock.jump);
catchBlock = newCatchBlock;
}
}
if (exceptionLocal == null) {
if (exceptionLocal != null)
firstInstr.removeBlock();
else {
exceptionLocal = new LocalInfo(-1);
exceptionLocal.setName("ERROR!!!");
exceptionLocal.setType(exceptionType);
}
exceptionLocal.setType(exceptionType);
used.addElement(exceptionLocal);
this.catchBlock = catchBlock;
catchBlock.outer = this;
catchBlock.setFlowBlock(flowBlock);
}
/* The implementation of getNext[Flow]Block is the standard
@ -152,8 +147,6 @@ public class CatchBlock extends StructuredBlock {
if (local != exceptionLocal) {
/* exceptionLocal will be automatically declared in
* dumpInstruction.
*
* This is currently broken for nested tries... XXX
*/
super.dumpDeclaration(writer, local);
}
@ -162,24 +155,19 @@ public class CatchBlock extends StructuredBlock {
public void dumpInstruction(jode.TabbedPrintWriter writer)
throws java.io.IOException {
/* avoid ugly nested tries */
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
if (!(outer instanceof CatchBlock)) {
writer.println("try {");
writer.tab();
}
tryBlock.dumpSource(writer);
writer.untab();
writer.println("} catch ("+/*XXX*/exceptionType.toString() + " "
writer.println("} catch ("+exceptionType.toString() + " "
+ exceptionLocal.getName().toString()+ ") {");
writer.tab();
catchBlock.dumpSource(writer);
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
if (!(outer instanceof CatchBlock)) {
writer.untab();
writer.println("}");
}
}
}

@ -36,22 +36,23 @@ public class CatchFinallyBlock extends CatchBlock {
fin.setFlowBlock(flowBlock);
}
// /**
// * Returns the block where the control will normally flow to, when
// * the given sub block is finished (<em>not</em> ignoring the jump
// * after this block). FinallyBlock have a special behaviour, since
// * the try block has the finallyblock as successor and the
// * finallyblock has no default successor at all!!
// *
// * @return null, if the control flows to another FlowBlock.
// */
// public StructuredBlock getNextBlock(StructuredBlock subBlock) {
// return subBlock == tryBlock ? finallyBlock : null;
// }
/**
* Returns the block where the control will normally flow to, when
* the given sub block is finished (<em>not</em> ignoring the jump
* after this block). FinallyBlock have a special behaviour, since
* the finally block has no default successor at all (it is more a
* subroutine) that will be called by try or any exception.
* The try block has the normal successor.
*
* @return null, if the control flows to another FlowBlock.
*/
public StructuredBlock getNextBlock(StructuredBlock subBlock) {
return subBlock == tryBlock ? getNextBlock() : null;
}
// public FlowBlock getNextFlowBlock(StructuredBlock subBlock) {
// return null;
// }
public FlowBlock getNextFlowBlock(StructuredBlock subBlock) {
return subBlock == tryBlock ? getNextFlowBlock() : null;
}
/**
* Replaces the given sub block with a new block.
@ -90,8 +91,7 @@ public class CatchFinallyBlock extends CatchBlock {
public void dumpInstruction(jode.TabbedPrintWriter writer)
throws java.io.IOException {
/* avoid ugly nested tries */
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
if (!(outer instanceof CatchBlock)) {
writer.println("try {");
writer.tab();
}
@ -100,13 +100,9 @@ public class CatchFinallyBlock extends CatchBlock {
writer.println("} finally {");
writer.tab();
finallyBlock.dumpSource(writer);
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
if (!(outer instanceof CatchBlock)) {
writer.untab();
writer.println("}");
}
}
}

@ -27,66 +27,74 @@ 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)
if (!(flow.lastModified instanceof ConditionalBlock)
|| !(flow.lastModified.outer instanceof SequentialBlock))
return false;
ConditionalBlock cb = (ConditionalBlock) flow.lastModified;
SequentialBlock sequBlock = (SequentialBlock) cb.outer;
Expression[] e = new Expression[2];
e[1] = cb.getInstruction();
Expression lastCombined = e[1];
while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
InstructionBlock ib =
(InstructionBlock) sequBlock.subBlocks[0];
if (!(sequBlock.outer instanceof SequentialBlock))
return false;
// jode.Assert.assert(sequBlock.jump == null)
Expression expr = ib.getInstruction();
if (lastCombined.canCombine(expr) + e[1].canCombine(expr) <= 0)
/* Tricky, the above is true, iff one of the two
* Expressions conflict, or both fail. */
return false;
e = new Expression[2];
e[1] = (Expression)cb.getInstruction();
while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
InstructionBlock ib =
(InstructionBlock) sequBlock.subBlocks[0];
Expression expr = (Expression) ib.getInstruction();
if (!expr.isVoid())
return false;
lastCombined = expr;
Expression combined = e[1].tryToCombine(expr);
if (combined == null)
return false;
cb.replace(sequBlock, cb);
cb.setInstruction(combined);
e[1] = combined;
sequBlock = (SequentialBlock) cb.outer;
}
sequBlock = (SequentialBlock) sequBlock.outer;
}
if (sequBlock.subBlocks[0] instanceof ConditionalBlock) {
ConditionalBlock cbprev =
(ConditionalBlock) sequBlock.subBlocks[0];
if (cbprev.jump != null)
return false;
prevJump = ((EmptyBlock) cbprev.trueBlock).jump;
Jump prevJump = cbprev.trueBlock.jump;
int operator;
if (prevJump.destination == cb.jump.destination) {
operator = BinaryOperator.LOG_AND_OP;
e[0] = ((Expression)cbprev.getInstruction()).negate();
} else if (prevJump.destination
== ((EmptyBlock) cb.trueBlock).jump.destination) {
e[0] = cbprev.getInstruction().negate();
} else if (prevJump.destination == cb.trueBlock.jump.destination) {
operator = BinaryOperator.LOG_OR_OP;
e[0] = (Expression)cbprev.getInstruction();
e[0] = cbprev.getInstruction();
} else
return false;
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
sequBlock = (SequentialBlock) cb.outer;
while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
/* Now combine the expression. Everything should
* succeed, because we have checked above. */
InstructionBlock ib =
(InstructionBlock) sequBlock.subBlocks[0];
Expression expr = ib.getInstruction();
e[1] = e[1].combine(expr);
sequBlock = (SequentialBlock) sequBlock.outer;
}
flow.removeSuccessor(prevJump);
prevJump.prev.removeJump();
Expression cond =
new ComplexExpression
(new BinaryOperator(Type.tBoolean, operator), e);
cb.setInstruction(cond);
cb.replace(sequBlock, cb);
return true;
}
flow.removeSuccessor(prevJump);
prevJump.prev.removeJump();
Expression cond =
new ComplexExpression
(new BinaryOperator(Type.tBoolean, operator), e);
cb.setInstruction(cond);
cb.replace(cb.outer, cb);
return true;
return false;
}
}

@ -16,7 +16,7 @@
* $Id$
*/
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.LocalVarOperator;
import jode.TabbedPrintWriter;
@ -26,13 +26,13 @@ import jode.TabbedPrintWriter;
*/
public class ConditionalBlock extends InstructionContainer {
StructuredBlock trueBlock;
EmptyBlock trueBlock;
/**
* Creates a new if then else block. The method setThenBlock must
* be called shortly after the creation.
*/
public ConditionalBlock(Instruction cond, Jump condJump, Jump elseJump) {
public ConditionalBlock(Expression cond, Jump condJump, Jump elseJump) {
super(cond, elseJump);
/* cond is a CompareBinary or CompareUnary operator, so no
* check for LocalVarOperator (for condJump) is needed here.
@ -59,12 +59,8 @@ public class ConditionalBlock extends InstructionContainer {
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (trueBlock == oldBlock)
trueBlock = newBlock;
else
return false;
return true;
StructuredBlock newBlock) {
throw new jode.AssertError("replaceSubBlock on ConditionalBlock");
}
/**

@ -42,18 +42,18 @@ public class CreateAssignExpression implements Transformation{
opBlock = (SequentialBlock) lastBlock.outer;
if (opBlock.subBlocks[1] != lastBlock)
return false;
ib = (InstructionBlock) opBlock.subBlocks[0];
if (ib.getInstruction() instanceof DupOperator) {
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != store.getLValueOperandCount() &&
dup.getCount() != store.getLValueType().stackSize())
if (opBlock.subBlocks[0] instanceof SpecialBlock) {
SpecialBlock dup = (SpecialBlock) opBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != store.getLValueOperandCount()
|| dup.count != store.getLValueType().stackSize())
return false;
opBlock = (SequentialBlock) lastBlock.outer;
ib = (InstructionBlock) opBlock.subBlocks[0];
isExpression = true;
}
ib = (InstructionBlock) opBlock.subBlocks[0];
ComplexExpression binopExpr =
(ComplexExpression) ib.getInstruction();
binop = (BinaryOperator) binopExpr.getOperator();
@ -70,11 +70,11 @@ public class CreateAssignExpression implements Transformation{
return false;
sequBlock = (SequentialBlock) opBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != 0 &&
dup.getCount() != store.getLValueOperandCount())
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != 0
|| dup.count != store.getLValueOperandCount())
return false;
} catch (ClassCastException ex) {
return false;
@ -107,11 +107,11 @@ public class CreateAssignExpression implements Transformation{
store = (StoreInstruction) lastBlock.getInstruction();
sequBlock = (SequentialBlock) lastBlock.outer;
InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != store.getLValueOperandCount() &&
dup.getCount() != store.getLValueType().stackSize())
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != store.getLValueOperandCount()
|| dup.count != store.getLValueType().stackSize())
return false;
} catch (NullPointerException ex) {
return false;

@ -20,7 +20,6 @@
package jode.flow;
import jode.Expression;
import jode.ComplexExpression;
import jode.DupOperator;
import jode.ArrayStoreOperator;
import jode.NewArrayOperator;
import jode.ConstantArrayOperator;
@ -37,9 +36,6 @@ public class CreateConstantArray implements Transformation {
Type type;
try {
InstructionBlock ib = (InstructionBlock) flow.lastModified;
if (ib.getInstruction() instanceof DupOperator)
/* this is not the end of the array assign */
return false;
sequBlock = (SequentialBlock) ib.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
@ -52,11 +48,11 @@ public class CreateConstantArray implements Transformation {
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
Expression lastconst = (Expression) ib.getInstruction();
Expression lastconst = ib.getInstruction();
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
Expression indexexpr = (Expression) ib.getInstruction();
Expression indexexpr = ib.getInstruction();
ConstOperator indexop =
(ConstOperator) indexexpr.getOperator();
if (!indexop.getType().isOfType(Type.tUInt))
@ -75,10 +71,11 @@ public class CreateConstantArray implements Transformation {
}
consts[lastindex--] = lastconst;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != 0 ||
dup.getCount() != store.getLValueType().stackSize())
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != 0
|| dup.count != store.getLValueType().stackSize())
return false;
count++;
sequBlock = (SequentialBlock) sequBlock.outer;
@ -86,10 +83,8 @@ public class CreateConstantArray implements Transformation {
}
if (count == 0)
return false;
while (lastindex >= 0) {
consts[lastindex--] =
new ConstOperator(Type.tUnknown, "0");
}
while (lastindex >= 0)
consts[lastindex--] = new ConstOperator(Type.tUnknown, "0");
ComplexExpression newArrayExpr =
(ComplexExpression) ib.getInstruction();
NewArrayOperator newArrayOp =
@ -97,8 +92,7 @@ public class CreateConstantArray implements Transformation {
type = newArrayOp.getType();
if (newArrayOp.getOperandCount() != 1)
return false;
Expression countexpr =
(Expression) newArrayExpr.getSubExpressions()[0];
Expression countexpr = newArrayExpr.getSubExpressions()[0];
ConstOperator countop =
(ConstOperator) countexpr.getOperator();
if (!countop.getType().isOfType(Type.tUInt))

@ -40,78 +40,79 @@ public class CreateExpression implements Transformation {
* @return true if flow block was simplified.
*/
public boolean transform(FlowBlock flow) {
Operator op;
Expression exprs[];
int params;
StructuredBlock sequBlock;
// try {
// System.err.println("Transformation on: "+flow.getLabel());
// flow.checkConsistent();
// } catch (RuntimeException ex) {
// try {
// jode.TabbedPrintWriter writer =
// new jode.TabbedPrintWriter(System.err, " ");
// writer.tab();
// flow.block.dumpSource(writer);
// } catch (java.io.IOException ioex) {
// }
// }
try {
op = (Operator)
((InstructionContainer)flow.lastModified).getInstruction();
params = op.getOperandCount();
if (!(flow.lastModified instanceof InstructionContainer)
|| !(flow.lastModified.outer instanceof SequentialBlock))
return false;
InstructionContainer ic = (InstructionContainer) flow.lastModified;
if (ic.getInstruction() instanceof Operator) {
Operator op = (Operator) ic.getInstruction();
int params = op.getOperandCount();
if (params == 0)
return false;
exprs = new Expression[params];
sequBlock = flow.lastModified.outer;
if (sequBlock.getSubBlocks()[1] != flow.lastModified)
return false;
for (int i = params-1; i>=0; i--) {
Expression[] exprs = new Expression[params];
SequentialBlock sequBlock = (SequentialBlock) ic.outer;
Expression lastExpression = null;
/* First check if Expression can be created, but do nothing yet.
*/
for (int i=params; ;) {
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false;
InstructionBlock block =
(InstructionBlock) sequBlock.getSubBlocks()[0];
if (block.jump != null)
(InstructionBlock) sequBlock.subBlocks[0];
Expression expr = block.getInstruction();
if (!expr.isVoid()) {
if (--i == 0)
break;
} else if (lastExpression != null
&& lastExpression.canCombine(expr) <= 0)
return false;
exprs[i] = (Expression) block.getInstruction();
if (i > 0 && exprs[i].getOperandCount() > 0)
if (expr.getOperandCount() > 0)
/* This is a not fully resolved expression in the
* middle, we must not touch it. */
return false;
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, subExprBlock);
sequBlock = subExprBlock;
((InstructionContainer)subExprBlock.getSubBlocks()[0]).
setInstruction(e);
exprs[i] = e;
}
if (i > 0)
sequBlock = (SequentialBlock)sequBlock.outer;
lastExpression = expr;
if (!(sequBlock.outer instanceof SequentialBlock))
return false;
sequBlock = (SequentialBlock)sequBlock.outer;
}
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {
return false;
}
if(jode.Decompiler.isVerbose)
System.err.print('x');
((InstructionContainer) flow.lastModified).setInstruction
(new ComplexExpression(op, exprs));
flow.lastModified.replace(sequBlock, flow.lastModified);
return true;
/* Now, do the combination. Everything must succeed now.
*/
sequBlock = (SequentialBlock) ic.outer;
for (int i=params; ;) {
InstructionBlock block =
(InstructionBlock) sequBlock.subBlocks[0];
Expression expr = block.getInstruction();
if (!expr.isVoid()) {
exprs[--i] = expr;
if (i == 0)
break;
} else
exprs[i] = exprs[i].combine(expr);
sequBlock = (SequentialBlock)sequBlock.outer;
}
if(jode.Decompiler.isVerbose)
System.err.print('x');
ic.setInstruction(new ComplexExpression(op, exprs));
ic.replace(sequBlock, ic);
return true;
}
return false;
}
}

@ -18,7 +18,6 @@
*/
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.StoreInstruction;
@ -31,29 +30,23 @@ public class CreateForInitializer implements Transformation {
public boolean transform(FlowBlock flow) {
if (!(flow.lastModified instanceof LoopBlock)
|| flow.lastModified.outer == null)
|| !(flow.lastModified.outer instanceof SequentialBlock))
return false;
LoopBlock forBlock = (LoopBlock) flow.lastModified;
if (forBlock.type != forBlock.FOR || forBlock.init != null)
return false;
/* The following succeed, with high probability */
Instruction initializer;
try {
SequentialBlock sequBlock =
(SequentialBlock) forBlock.outer;
SequentialBlock sequBlock = (SequentialBlock) forBlock.outer;
initializer =
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction();
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false;
Expression initializer =
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction();
if (!( ((Expression)initializer).getOperator()
instanceof StoreInstruction))
return false;
} catch (ClassCastException ex) {
if (!(initializer.getOperator() instanceof StoreInstruction))
return false;
}
if (jode.Decompiler.isVerbose)
System.err.print('f');

@ -100,7 +100,7 @@ public class CreateIfThenElseOperator implements Transformation {
break;
}
e[0] = (Expression) ifBlock.cond;
e[0] = ifBlock.cond;
StructuredBlock[] subBlocks = ifBlock.getSubBlocks();
if (subBlocks.length != 2)
@ -108,8 +108,7 @@ public class CreateIfThenElseOperator implements Transformation {
for (int i=0; i< 2; i++) {
if (subBlocks[i] instanceof InstructionBlock) {
e[i+1] = (Expression)
((InstructionBlock)subBlocks[i]).getInstruction();
e[i+1] = ((InstructionBlock)subBlocks[i]).getInstruction();
continue;
}
@ -131,7 +130,7 @@ public class CreateIfThenElseOperator implements Transformation {
!= trueDestination)
return false;
Expression cond = (Expression) condBlock.getInstruction();
Expression cond = condBlock.getInstruction();
flow.removeSuccessor(condBlock.trueBlock.jump);
condBlock.trueBlock.removeJump();
pushBlock.setInstruction(cond);
@ -192,13 +191,13 @@ public class CreateIfThenElseOperator implements Transformation {
if (thenBlock.jump.destination != elseBlock.jump.destination)
return false;
e[1] = (Expression) thenBlock.getInstruction();
e[1] = thenBlock.getInstruction();
if (e[1].isVoid())
return false;
e[2] = (Expression) elseBlock.getInstruction();
e[2] = elseBlock.getInstruction();
if (e[2].isVoid())
return false;
e[0] = (Expression) ifBlock.cond;
e[0] = ifBlock.cond;
} catch (ClassCastException ex) {
return false;

@ -22,59 +22,61 @@ import jode.InvokeOperator;
import jode.Expression;
import jode.ComplexExpression;
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[];
if (!(flow.lastModified instanceof InstructionBlock)
|| !(flow.lastModified.outer instanceof SequentialBlock))
return false;
InstructionBlock block = (InstructionBlock) flow.lastModified;
if (!(block.getInstruction() instanceof InvokeOperator))
return false;
InvokeOperator constrCall = (InvokeOperator) block.getInstruction();
if (!constrCall.isConstructor())
return false;
/* The rest should probably succeed */
int params = constrCall.getOperandCount();
Expression[] exprs = new Expression[params];
SequentialBlock sequBlock = (SequentialBlock) block.outer;
try {
InstructionBlock block;
block = (InstructionBlock) flow.lastModified;
constrCall = (InvokeOperator) block.getInstruction();
if (!constrCall.isConstructor())
return false;
int params = constrCall.getOperandCount();
exprs = new Expression[params];
for_loop:
for (int i = params-1; i>0; i--) {
sequBlock = (SequentialBlock) block.outer;
if (sequBlock.getSubBlocks()[1] != block)
return false;
block = (InstructionBlock) sequBlock.subBlocks[0];
exprs[i] = block.getInstruction();
sequBlock = (SequentialBlock) sequBlock.outer;
for (int i = params-1; i>0; i--) {
while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
Expression expr =
((InstructionBlock) sequBlock.subBlocks[0])
.getInstruction();
block = (InstructionBlock) sequBlock.getSubBlocks()[0];
if (block.jump != null)
return false;
if (!expr.isVoid())
continue for_loop;
if (exprs[i].canCombine(expr) <= 0)
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++;
exprs[i] = exprs[i].combine(expr);
SequentialBlock subExprBlock =
(SequentialBlock) sequBlock.getSubBlocks()[1];
(SequentialBlock) sequBlock.subBlocks[1];
subExprBlock.replace(sequBlock, subExprBlock);
sequBlock = subExprBlock;
((InstructionContainer)subExprBlock.getSubBlocks()[0]).
setInstruction(e);
exprs[i] = e;
((InstructionContainer)subExprBlock.subBlocks[0]).
setInstruction(exprs[i]);
sequBlock = (SequentialBlock)sequBlock.outer;
}
sequBlock = (SequentialBlock)sequBlock.outer;
}
block = (InstructionBlock) sequBlock.getSubBlocks()[0];
DupOperator dup = (DupOperator) block.getInstruction();
if (dup.getCount() != 1 && dup.getDepth() != 0)
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.count != 1 || dup.depth != 0)
return false;
sequBlock = (SequentialBlock)sequBlock.outer;
block = (InstructionBlock) sequBlock.getSubBlocks()[0];
exprs[0] = (Expression) block.getInstruction();
block = (InstructionBlock) sequBlock.subBlocks[0];
exprs[0] = block.getInstruction();
if (exprs[0].isVoid())
return false;
NewOperator op = (NewOperator) exprs[0].getOperator();

@ -36,12 +36,12 @@ public class CreatePrePostIncExpression implements Transformation {
try {
lastBlock = (InstructionContainer) flow.lastModified;
Instruction instr2 = lastBlock.getInstruction();
Expression instr2 = lastBlock.getInstruction();
SequentialBlock sequBlock = (SequentialBlock)lastBlock.outer;
if (sequBlock.subBlocks[1] != lastBlock)
return false;
InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
Instruction instr1 = ib.getInstruction();
Expression instr1 = ib.getInstruction();
LocalLoadOperator load;
if (instr1 instanceof IIncOperator
@ -93,7 +93,7 @@ public class CreatePrePostIncExpression implements Transformation {
try {
lastBlock = (InstructionBlock) flow.lastModified;
Expression storeExpr = (Expression) lastBlock.getInstruction();
Expression storeExpr = lastBlock.getInstruction();
store = (StoreInstruction) storeExpr.getOperator();
sequBlock = (SequentialBlock) lastBlock.outer;
@ -127,27 +127,24 @@ public class CreatePrePostIncExpression implements Transformation {
op ^= 1;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getCount() != store.getLValueType().stackSize() ||
dup.getDepth() != store.getLValueOperandCount())
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.count != store.getLValueType().stackSize()
|| dup.depth != store.getLValueOperandCount())
return false;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
Operator load = (Operator) ib.getInstruction();
if (!store.matches(load))
return false;
if (store.getLValueOperandCount() > 0) {
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup2 = (DupOperator) ib.getInstruction();
if (dup2.getCount() != store.getLValueOperandCount() ||
dup2.getDepth() != 0)
SpecialBlock dup2 = (SpecialBlock) sequBlock.subBlocks[0];
if (dup2.type != SpecialBlock.DUP
|| dup2.count != store.getLValueOperandCount()
|| dup2.depth != 0)
return false;
}
type = load.getType().intersection(store.getLValueType());

@ -71,7 +71,9 @@ public class FlowBlock {
StructuredBlock block;
/**
* The last modified structured block.
* The last modified structured block. This is probably the
* last instruction in the outermost block, that is in the
* outermost chain of SequentialBlock.
*/
StructuredBlock lastModified;
@ -132,36 +134,6 @@ public class FlowBlock {
FlowBlock successor = jump.destination;
if (jump.prev instanceof EmptyBlock
&& jump.prev.outer != null
&& jump.prev.outer instanceof ConditionalBlock
&& jump.prev.outer.jump != null) {
if (jump.prev.outer.jump.destination == jump.destination) {
/* This is a weired "if (cond) empty"-block. We
* transform it by hand.
*/
jump.prev.removeJump();
continue;
}
/* Swap conditional blocks, that have two jumps, and where
* this jump is the inner jump.
*/
StructuredBlock prev = jump.prev;
ConditionalBlock cb = (ConditionalBlock) prev.outer;
Instruction instr = cb.getInstruction();
/* XXX Expression clean up is necessary. Otherwise
* this may lead to a ClassCastException.
*
* Our code below _depends_ on the fact that this
* transformation is done.
*/
cb.setInstruction(((Expression)instr).negate());
cb.swapJump(jump.prev);
}
/* if the jump is the jump of the appendBlock, skip it.
*/
if (jump.prev == appendBlock) {
@ -169,24 +141,9 @@ public class FlowBlock {
continue;
}
/* Now move the jump as far to the outer as possible,
* without leaving appendBlock.
*
* Note: jump.prev != appendblock implies
* jump.prev.outer != null, since appendBlock is an outer
* block of jump.prev
*/
while (jump.prev.outer.isSingleExit(jump.prev)) {
if (jump.prev.outer == appendBlock) {
/* Okay we have reached the top.
* appendBlock should already have the right jump.
*/
jump.prev.removeJump();
continue next_jump;
}
/* this changed jump.prev */
jump.prev.outer.moveJump(jump);
}
/* jump.prev.outer is not null since appendBlock is an
* outer block.
*/
/* remove this jump if it jumps to the getNextFlowBlock().
*/
@ -196,123 +153,102 @@ public class FlowBlock {
continue;
}
if (jump.prev instanceof EmptyBlock &&
jump.prev.outer instanceof ConditionalBlock) {
if (jump.prev.outer instanceof ConditionalBlock) {
StructuredBlock prev = jump.prev;
ConditionalBlock cb = (ConditionalBlock) prev.outer;
Instruction instr = cb.getInstruction();
if (jump.prev.outer.jump != null) {
/* cb.jump is null (see above), so cb must have a
* successor in this block, that means cb.outer is not
* null.
*/
StructuredBlock prev = jump.prev;
ConditionalBlock cb = (ConditionalBlock) prev.outer;
Expression instr = cb.getInstruction();
if (cb.jump.destination == jump.destination) {
/* This is a weired "if (cond) empty"-block. We
* transform it by hand.
*/
prev.removeJump();
IfThenElseBlock ifBlock =
new IfThenElseBlock(cb.getInstruction());
ifBlock.replace(cb, prev);
ifBlock.setThenBlock(prev);
continue;
}
/* Swap conditional blocks, that have two jumps, and where
* this jump is the inner jump.
*/
cb.setInstruction(instr.negate());
cb.swapJump(jump.prev);
/* Consider this jump again
*/
jumps.push(jump);
continue;
}
/* Now cb.jump is null and cb.outer is not null,
* since appendBlock is around it. */
ConditionalBlock cb = (ConditionalBlock) jump.prev.outer;
Expression instr = cb.getInstruction();
/* If this is the first instruction of a while and the
* condition of the while is true, use the condition
* as while condition.
*/
if (cb.outer instanceof LoopBlock
|| (cb.outer instanceof SequentialBlock
&& cb.outer.getSubBlocks()[0] == cb
&& cb.outer.outer instanceof LoopBlock)) {
/* This is the first instruction in a while block */
if (cb.outer instanceof SequentialBlock &&
cb.outer.getSubBlocks()[0] == cb &&
cb.outer.outer instanceof LoopBlock) {
LoopBlock loopBlock = (cb.outer instanceof LoopBlock) ?
(LoopBlock) cb.outer : (LoopBlock) cb.outer.outer;
LoopBlock loopBlock = (LoopBlock) cb.outer.outer;
if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() != LoopBlock.DOWHILE &&
loopBlock.getNextFlowBlock() == successor &&
/*XXX remove following after expression cleanup */
instr instanceof Expression) {
loopBlock.getNextFlowBlock() == successor) {
prev.removeJump();
loopBlock.setCondition(((Expression)instr).negate());
jump.prev.removeJump();
loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null);
/* Now remove the whole ConditionalBlock including
* the surrounding SequentialBlock.
*/
if (cb.outer.jump != null) {
/* Well can this happen???
*
* Currently a sequential block can only
* temporarily have a jump (assigned in
* this method, see above).
*
* But in any case we know, that the
* second sub block can't have a jump, so
* it takes the jump of its parent.
*/
cb.outer.getSubBlocks()[1].
moveJump(cb.outer.jump);
}
cb.outer.getSubBlocks()[1].replace
(cb.outer, cb.outer.getSubBlocks()[1]);
cb.removeBlock();
/* Note that cb.outer != appendBlock because
* appendBlock contains loopBlock. This is
* because lastModified can't be an
* instruction inside a loop block.
*
* XXX I have to make a clear precondition for this.
* because lastModified is in the outermost
* block.
*/
continue;
}
}
/* Now the same for the empty loop. In this case there is
* no sequential block, which simplifies the situation.
*/
else if (cb.outer instanceof LoopBlock) {
LoopBlock loopBlock = (LoopBlock) cb.outer;
if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() != LoopBlock.DOWHILE &&
loopBlock.getNextFlowBlock() == successor &&
instr instanceof Expression) {
prev.removeJump();
loopBlock.setCondition(((Expression)instr).negate());
loopBlock.moveDefinitions(cb, null);
EmptyBlock empty = new EmptyBlock();
empty.replace(cb, null);
/* cb is not used any more */
continue;
}
} else if (cb.outer instanceof SequentialBlock
&& cb.outer.getSubBlocks()[1] == cb) {
/* And a third time for do/while loops, where the jump
* is at the end of the loop. Note that all ifs are
* disjunct.
/* And now for do/while loops, where the jump is
* at the end of the loop.
*/
/* First find the beginning of the loop */
StructuredBlock sb = cb.outer;
while (sb.outer instanceof SequentialBlock) {
StructuredBlock sb = cb.outer.outer;
while (sb instanceof SequentialBlock) {
sb = sb.outer;
}
/* sb is now the first and cb is the last
* instruction in the current block.
*/
if (sb.outer instanceof LoopBlock) {
LoopBlock loopBlock = (LoopBlock) sb.outer;
if (sb instanceof LoopBlock) {
LoopBlock loopBlock = (LoopBlock) sb;
if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() == LoopBlock.WHILE &&
loopBlock.getNextFlowBlock() == successor &&
instr instanceof Expression) {
loopBlock.getNextFlowBlock() == successor) {
prev.removeJump();
jump.prev.removeJump();
loopBlock.setType(LoopBlock.DOWHILE);
loopBlock.setCondition(((Expression)instr).negate());
loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null);
/* We pretend here that cb.outer has no jump.
* (Note that cb.outer is a sequential block)
*/
cb.outer.getSubBlocks()[0].replace(cb.outer,
cb.outer);
/* cb and cb.outer are not used any more */
cb.removeBlock();
continue;
}
}
@ -325,79 +261,80 @@ public class FlowBlock {
if (cb.outer instanceof SequentialBlock &&
cb.outer.getSubBlocks()[0] == cb &&
(cb.outer.getNextFlowBlock() == successor ||
cb.outer.jumpMayBeChanged()) &&
instr instanceof Expression) {
cb.outer.jumpMayBeChanged())) {
SequentialBlock sequBlock =
(SequentialBlock) cb.outer;
IfThenElseBlock newIfBlock =
new IfThenElseBlock(((Expression)instr).negate());
new IfThenElseBlock(instr.negate());
newIfBlock.replace(sequBlock, sequBlock.getSubBlocks()[1]);
newIfBlock.setThenBlock(sequBlock.getSubBlocks()[1]);
newIfBlock.moveJump(sequBlock.jump);
if (appendBlock == sequBlock)
appendBlock = newIfBlock;
if (newIfBlock.getNextFlowBlock() != successor &&
newIfBlock != appendBlock) {
if (appendBlock == sequBlock) {
newIfBlock.moveJump(appendBlock.jump);
appendBlock = newIfBlock;
jump.prev.removeJump();
} else {
newIfBlock.moveJump(jump);
/* consider this jump again */
jumps.push(jump);
continue;
} else {
prev.removeJump();
continue;
}
continue;
}
}
/* if this is a jumps at the end of a then block belonging
* to a if-then block without else part, and the if-then
* block is followed by a single block, then replace the
* if-then block with a if-then-else block and remove the
* unconditional jump.
*/
else if (jump.prev.outer instanceof IfThenElseBlock) {
} else {
IfThenElseBlock ifBlock =
(IfThenElseBlock)jump.prev.outer;
if (ifBlock.elseBlock == null
&& ifBlock.outer instanceof SequentialBlock
&& ifBlock.outer.getSubBlocks()[0] == ifBlock) {
/* Now find the real outer block, that is ascend the chain
* of SequentialBlocks. But don't leave appendBlock.
*
* Note that only the last instr in a SequentialBlock chain
* can have a jump.
*
* Note further, that jump.prev must be a inner block, since
* otherwise its normal flow block is that of appendBlock,
* and appendblocks successor must be the destination, since
* it is then a sequential block.
*
* Yes, I know this data structure is quite subtile. But
* that's why the function checkConsistent exists.
*/
StructuredBlock sb = jump.prev.outer;
while (sb instanceof SequentialBlock)
sb = sb.outer;
/* if this is a jumps at the end of a then block belonging
* to a if-then block without else part, and the if-then
* block is followed by a single block, then replace the
* if-then block with a if-then-else block and remove the
* unconditional jump.
*/
if (sb instanceof IfThenElseBlock
&& sb.outer instanceof SequentialBlock
&& sb.outer.getSubBlocks()[0] == sb) {
StructuredBlock elseBlock =
ifBlock.outer.getSubBlocks()[1];
IfThenElseBlock ifBlock = (IfThenElseBlock) sb;
SequentialBlock sequBlock = (SequentialBlock) sb.outer;
StructuredBlock elseBlock = sequBlock.subBlocks[1];
if (ifBlock.outer.jump != null)
/* If the sequential block has a jump, we
* move it to the else block.
* Note that only one of these blocks can
* have a jump.
*/
elseBlock.moveJump(ifBlock.outer.jump);
if (elseBlock.getNextFlowBlock() == successor
|| elseBlock.jumpMayBeChanged()) {
if (ifBlock.elseBlock == null
&& (elseBlock.getNextFlowBlock() == successor
|| elseBlock.jumpMayBeChanged())) {
if (appendBlock == elseBlock.outer)
appendBlock = ifBlock;
ifBlock.replace(ifBlock.outer, elseBlock);
if (elseBlock.jump != null)
ifBlock.moveJump(elseBlock.jump);
ifBlock.replace(sequBlock, elseBlock);
ifBlock.setElseBlock(elseBlock);
if (ifBlock.getNextFlowBlock() != successor) {
ifBlock.moveJump(jump);
if (appendBlock == sequBlock) {
ifBlock.moveJump(appendBlock.jump);
appendBlock = ifBlock;
jump.prev.removeJump();
} else {
/* consider this jump again */
ifBlock.moveJump(jump);
jumps.push(jump);
} else
jump.prev.removeJump();
}
continue;
}
}
@ -586,60 +523,77 @@ public class FlowBlock {
}
}
/**
* Checks if the FlowBlock and its StructuredBlocks are
* consistent. There are to many conditions to list them
* here, the best way is to read this function and all other
* checkConsistent functions.
*/
public void checkConsistent() {
if (!Decompiler.doChecks)
return;
if (block.outer != null || block.flowBlock != this) {
throw new AssertError("Inconsistency");
}
block.checkConsistent();
Enumeration preds = predecessors.elements();
while (preds.hasMoreElements()) {
FlowBlock pred = (FlowBlock)preds.nextElement();
if (pred == null)
/* The special start marker */
continue;
if (pred.successors.get(this) == null)
// try {
if (block.outer != null || block.flowBlock != this) {
throw new AssertError("Inconsistency");
}
}
block.checkConsistent();
Enumeration keys = successors.keys();
Enumeration stacks = successors.elements();
while (keys.hasMoreElements()) {
FlowBlock dest = (FlowBlock) keys.nextElement();
if (!dest.predecessors.contains(this))
throw new AssertError("Inconsistency");
Enumeration enum = ((Stack)stacks.nextElement()).elements();
if (!enum.hasMoreElements())
Enumeration preds = predecessors.elements();
while (preds.hasMoreElements()) {
FlowBlock pred = (FlowBlock)preds.nextElement();
if (pred == null)
/* The special start marker */
continue;
if (pred.successors.get(this) == null)
throw new AssertError("Inconsistency");
}
StructuredBlock last = lastModified;
while (last.outer instanceof SequentialBlock)
last = last.outer;
if (last.outer != null)
throw new AssertError("Inconsistency");
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump.destination != dest)
Enumeration keys = successors.keys();
Enumeration stacks = successors.elements();
while (keys.hasMoreElements()) {
FlowBlock dest = (FlowBlock) keys.nextElement();
if (!dest.predecessors.contains(this))
throw new AssertError("Inconsistency");
if (jump.prev.flowBlock != this ||
jump.prev.jump != jump)
Enumeration enum = ((Stack)stacks.nextElement()).elements();
if (!enum.hasMoreElements())
throw new AssertError("Inconsistency");
prev_loop:
for (StructuredBlock prev = jump.prev; prev != block;
prev = prev.outer) {
if (prev.outer == null)
throw new RuntimeException("Inconsistency");
StructuredBlock[] blocks = prev.outer.getSubBlocks();
int i;
for (i=0; i<blocks.length; i++)
if (blocks[i] == prev)
continue prev_loop;
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump.destination != dest)
throw new AssertError("Inconsistency");
if (jump.prev.flowBlock != this ||
jump.prev.jump != jump)
throw new AssertError("Inconsistency");
throw new RuntimeException("Inconsistency");
prev_loop:
for (StructuredBlock prev = jump.prev; prev != block;
prev = prev.outer) {
if (prev.outer == null)
throw new RuntimeException("Inconsistency");
StructuredBlock[] blocks = prev.outer.getSubBlocks();
int i;
for (i=0; i<blocks.length; i++)
if (blocks[i] == prev)
continue prev_loop;
throw new AssertError("Inconsistency");
}
}
}
}
// } catch (AssertError ex) {
// System.err.println("in: "+this);
// throw ex;
// }
}
/**
@ -743,12 +697,12 @@ public class FlowBlock {
public boolean doT2(int start, int end) {
/* If there are no jumps to the beginning of this flow block
* 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. */
* or if this block has other predecessors with a not yet
* considered address, return false. The second condition
* make sure that not for each continue a while is created.
*/
if (!predecessors.contains(this))
return false;
Enumeration preds = predecessors.elements();
while (preds.hasMoreElements()) {
FlowBlock predFlow = (FlowBlock) preds.nextElement();
@ -765,102 +719,87 @@ public class FlowBlock {
/* Update the in/out-Vectors now */
updateInOut(this, false, jumps);
while (lastModified != block)
lastModified = lastModified.outer;
transformation:
do {
/* If there is only one jump to the beginning and it is the
* last jump and (there is a do/while(0) block surrounding
* everything but the last instruction, or the last
* instruction is a increase/decrease statement), replace the
* do/while(0) with a for(;;last_instr) resp. create a new one
* and replace breaks to do/while with continue to for.
*/
if (jumps.size() == 1 &&
((Jump)jumps.peek()).prev instanceof InstructionBlock) {
InstructionBlock prev =
(InstructionBlock) ((Jump)jumps.peek()).prev;
/* Now check if the jump is the last block in a chain
* of SequentialBlocks that have no surrounding blocks.
*/
StructuredBlock sb = prev;
while (sb.outer != null
&& sb.outer instanceof SequentialBlock
&& sb.outer.getSubBlocks()[1] == sb)
sb = sb.outer;
if (sb.outer == null && prev.outer != null
&& prev.outer instanceof SequentialBlock
&& prev.outer.getSubBlocks()[0] instanceof LoopBlock) {
LoopBlock lb = (LoopBlock) prev.outer.getSubBlocks()[0];
if (lb.cond == lb.FALSE && lb.type == lb.DOWHILE) {
/* The jump is directly following a
* do-while(false) block
*
* Remove do/while, create a for(;;last_instr)
* and replace break to that block with
* continue to for.
*/
LoopBlock forBlock =
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE);
forBlock.replace(sb, sb);
forBlock.setBody(sb);
prev.outer.getSubBlocks()[0].replace(prev.outer, null);
forBlock.incr = prev.getInstruction();
forBlock.replaceBreakContinue(lb);
lb.bodyBlock.replace(lb, null);
prev.removeJump();
lastModified = lb;
break transformation;
}
}
StructuredBlock bodyBlock = block;
Instruction instr = prev.getInstruction();
Operator op;
if (sb.outer == null
&& instr instanceof Expression
&& ((op = ((Expression)instr).getOperator())
instanceof StoreInstruction
|| op instanceof IIncOperator)) {
/* If there is only one jump to the beginning and it is
* the last jump (lastModified) and (there is a
* do/while(0) block surrounding everything but the last
* instruction, or the last instruction is a
* increase/decrease statement), replace the do/while(0)
* with a for(;;last_instr) resp. create a new one and
* replace breaks to do/while with continue to for. */
/* The only jump is the jump of the last
* instruction prev */
boolean createdForBlock = false;
if (jumps.size() == 1
&& ((Jump)jumps.peek()).prev == lastModified
&& lastModified instanceof InstructionBlock) {
Expression instr =
((InstructionBlock)lastModified).getInstruction();
if (lastModified.outer instanceof SequentialBlock
&& lastModified.outer.getSubBlocks()[0]
instanceof LoopBlock) {
LoopBlock lb =
(LoopBlock) lastModified.outer.getSubBlocks()[0];
if (lb.cond == lb.FALSE && lb.type == lb.DOWHILE) {
/* The jump is directly following a
* do-while(false) block
*
* Remove do/while, create a for(;;last_instr)
* and replace break to that block with
* continue to for.
*/
LoopBlock forBlock =
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE);
forBlock.replace(sb, sb);
forBlock.setBody(sb);
prev.outer.getSubBlocks()[0].replace(prev.outer, null);
forBlock.replace(bodyBlock, bodyBlock);
forBlock.setBody(bodyBlock);
forBlock.incr = instr;
prev.removeJump();
lastModified = forBlock;
break transformation;
lastModified.removeJump();
forBlock.replaceBreakContinue(lb);
lb.bodyBlock.replace(lastModified.outer, null);
createdForBlock = true;
}
}
if (!createdForBlock &&
(instr.getOperator() instanceof StoreInstruction
|| instr.getOperator() instanceof IIncOperator)) {
/* The only jump is the jump of the last
* instruction lastModified */
LoopBlock forBlock =
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE);
forBlock.replace(bodyBlock, bodyBlock);
forBlock.setBody(bodyBlock);
forBlock.incr = instr;
lastModified.removeJump();
lastModified.outer.getSubBlocks()[0]
.replace(lastModified.outer, null);
createdForBlock = true;
}
}
if (!createdForBlock) {
/* Creating a for block didn't succeed; create a
* while block instead. */
StructuredBlock bodyBlock = block;
/* Prepare the unification of the blocks: Make sure that
* bodyBlock has a jump. */
* bodyBlock has a jump.
*/
if (bodyBlock.jump == null) {
Jump jump = new Jump(this);
bodyBlock.setJump(jump);
jumps.push(jump);
}
LoopBlock whileBlock =
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE);
@ -911,13 +850,12 @@ public class FlowBlock {
if (bodyBlock.jump != null
&& bodyBlock.jump.destination == this)
bodyBlock.removeJump();
lastModified = whileBlock;
} while (false);
}
/* remove ourself from the predecessor list.
*/
predecessors.removeElement(this);
lastModified = block;
/* T2 analysis succeeded */
checkConsistent();
@ -1322,7 +1260,7 @@ public class FlowBlock {
removeJSR(subRoutine);
}
public boolean isMonitorExit(Instruction instr, LocalInfo local) {
public boolean isMonitorExit(Expression instr, LocalInfo local) {
if (instr instanceof ComplexExpression) {
ComplexExpression expr = (ComplexExpression)instr;
if (expr.getOperator() instanceof MonitorExitOperator
@ -1353,7 +1291,7 @@ public class FlowBlock {
subRoutine.analyzeSubRoutine(addr+length, end);
if (subRoutine.block instanceof InstructionBlock) {
Instruction instr =
Expression instr =
((InstructionBlock)subRoutine.block)
.getInstruction();
if (isMonitorExit(instr, local)) {
@ -1403,7 +1341,7 @@ public class FlowBlock {
continue;
if (pred instanceof InstructionBlock) {
Instruction instr =
Expression instr =
((InstructionBlock)pred).getInstruction();
if (instr instanceof ComplexExpression
&& ((ComplexExpression)instr)
@ -1502,8 +1440,8 @@ public class FlowBlock {
SequentialBlock catchBlock = (SequentialBlock) catchFlow.block;
int type = 0;
Instruction instr =
((InstructionBlock)catchBlock.subBlocks[0]).instr;
Expression instr =
((InstructionBlock)catchBlock.subBlocks[0]).getInstruction();
if (instr instanceof ComplexExpression
&& ((ComplexExpression)instr).getOperator()
@ -1621,8 +1559,10 @@ public class FlowBlock {
changed = true;
}
} else if (catchFlow.block instanceof InstructionBlock
&& ((InstructionBlock) catchFlow.block).instr
&& ((InstructionBlock) catchFlow.block).getInstruction()
instanceof PopOperator
&& ((PopOperator) ((InstructionBlock) catchFlow.block)
.getInstruction()).getCount() == 1
&& successors.size() == 1) {
/* This is a special try/finally-block, where
@ -1630,28 +1570,40 @@ public class FlowBlock {
* similar.
*/
FlowBlock succ = catchFlow.block.jump.destination;
Stack jumps = (Stack) successors.get(succ);
Stack newJumps = new Stack();
newJumps.push(catchFlow.block.jump);
successors.put(succ, newJumps);
jumps.removeElement(catchFlow.block.jump);
Stack jumps = (Stack) successors.remove(succ);
updateInOut(succ, true, jumps);
Stack stack = new Stack();
stack.push(catchFlow.block.jump);
successors.put(succ, stack);
jumps.removeElement(catchFlow.block.jump);
if (rawBlock.tryBlock.jump == null) {
Jump jump = new Jump(succ);
rawBlock.tryBlock.setJump(jump);
jumps.push(jump);
}
optimizeJumps(rawBlock.tryBlock, jumps);
resolveRemaining(rawBlock.tryBlock, jumps);
CatchFinallyBlock newBlock = new CatchFinallyBlock();
newBlock.replace(rawBlock, rawBlock);
newBlock.setTryBlock(rawBlock.tryBlock);
newBlock.setFinallyBlock(new EmptyBlock());
newBlock.moveJump(rawBlock.jump);
lastModified = newBlock.finallyBlock;
lastModified.moveJump(catchFlow.block.jump);
if (succ.predecessors.size() == 1) {
succ.analyze(addr+length, end);
length += succ.length;
successors.remove(succ);
newBlock.setFinallyBlock(succ.block);
mergeSuccessors(succ);
} else {
/* The finally block is empty, put the jump back
* into the finally block.
*/
newBlock.setFinallyBlock(new EmptyBlock());
newBlock.finallyBlock.moveJump(catchFlow.block.jump);
}
lastModified = newBlock;
changed = true;
}
checkConsistent();
@ -1667,8 +1619,7 @@ public class FlowBlock {
/* throws ClassCastException if something isn't as exspected. */
SequentialBlock sequBlock = (SequentialBlock) block;
LocalStoreOperator store = (LocalStoreOperator)
((Expression)((InstructionBlock)sequBlock.subBlocks[0]).instr)
.getOperator();
((InstructionBlock)sequBlock.subBlocks[0]).instr.getOperator();
while (sequBlock.subBlocks[1] instanceof SequentialBlock)
sequBlock = (SequentialBlock) sequBlock.subBlocks[1];
@ -1699,8 +1650,6 @@ public class FlowBlock {
SwitchBlock switchBlock = (SwitchBlock) block;
boolean changed = false;
StructuredBlock lastBlock = null;
lastModified = block;
/* XXX - move to switchBlock??? */
for (int i=0; i < switchBlock.caseBlocks.length; i++) {
if (switchBlock.caseBlocks[i].subBlock != null
&& switchBlock.caseBlocks[i].subBlock.jump != null) {
@ -1878,8 +1827,7 @@ public class FlowBlock {
public String toString() {
try {
java.io.StringWriter strw = new java.io.StringWriter();
TabbedPrintWriter writer =
new TabbedPrintWriter(strw, " ");
TabbedPrintWriter writer = new TabbedPrintWriter(strw, " ");
writer.println(super.toString());
writer.tab();
dumpSource(writer);

@ -16,7 +16,7 @@
* $Id$
*/
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.TabbedPrintWriter;
/**
@ -28,7 +28,7 @@ public class IfThenElseBlock extends StructuredBlock {
/**
* The condition. Must be of boolean type.
*/
Instruction cond;
Expression cond;
/**
* The then part. This is always a valid block and not null
@ -44,7 +44,7 @@ public class IfThenElseBlock extends StructuredBlock {
* Creates a new if then else block. The method setThenBlock must
* be called shortly after the creation.
*/
public IfThenElseBlock(Instruction cond) {
public IfThenElseBlock(Expression cond) {
this.cond = cond;
}

@ -16,18 +16,21 @@
* $Id$
*/
package jode.flow;
import jode.*;
import jode.Expression;
import jode.TabbedPrintWriter;
import jode.LocalInfo;
import jode.LocalStoreOperator;
/**
* This is the structured block for atomic instructions.
*/
public class InstructionBlock extends InstructionContainer {
public InstructionBlock(Instruction instr) {
public InstructionBlock(Expression instr) {
super(instr);
}
public InstructionBlock(Instruction instr, Jump jump) {
public InstructionBlock(Expression instr, Jump jump) {
super(instr, jump);
}
@ -47,10 +50,9 @@ public class InstructionBlock extends InstructionContainer {
public void dumpDeclaration(TabbedPrintWriter writer, LocalInfo local)
throws java.io.IOException
{
if (instr instanceof Expression
&& ((Expression)instr).getOperator() instanceof LocalStoreOperator
&& ((LocalStoreOperator) ((Expression)instr).getOperator())
.getLocalInfo() == local.getLocalInfo()) {
if (instr.getOperator() instanceof LocalStoreOperator
&& ((LocalStoreOperator) instr.getOperator()).getLocalInfo()
== local.getLocalInfo()) {
isDeclaration = true;
} else
super.dumpDeclaration(writer, local);
@ -68,12 +70,12 @@ public class InstructionBlock extends InstructionContainer {
{
if (isDeclaration) {
writer.println
(((LocalStoreOperator) ((Expression)instr).getOperator())
.getLocalInfo().getType().toString()/*XXX*/
(((LocalStoreOperator) instr.getOperator())
.getLocalInfo().getType().toString()
+ " " + instr.simplify().toString() + ";");
} else {
if (instr.getType() != Type.tVoid)
writer.print("push ");
if (instr.getType() != jode.Type.tVoid)
writer.print("PUSH ");
writer.println(instr.simplify().toString()+";");
}
}

@ -16,22 +16,22 @@
* $Id$
*/
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.LocalVarOperator;
/**
* This is a method for block containing a single instruction.
*/
public abstract class InstructionContainer extends StructuredBlock {
Instruction instr;
Expression instr;
public InstructionContainer(Instruction instr) {
public InstructionContainer(Expression instr) {
this.instr = instr;
if (instr instanceof LocalVarOperator)
used.addElement(((LocalVarOperator)instr).getLocalInfo());
}
public InstructionContainer(Instruction instr, Jump jump) {
public InstructionContainer(Expression instr, Jump jump) {
this.instr = instr;
if (instr instanceof LocalVarOperator) {
LocalVarOperator varOp = (LocalVarOperator) instr;
@ -59,7 +59,7 @@ public abstract class InstructionContainer extends StructuredBlock {
* Get the contained instruction.
* @return the contained instruction.
*/
public Instruction getInstruction() {
public Expression getInstruction() {
return instr;
}
@ -67,7 +67,7 @@ public abstract class InstructionContainer extends StructuredBlock {
* Set the contained instruction.
* @param instr the new instruction.
*/
public void setInstruction(Instruction instr) {
public void setInstruction(Expression instr) {
this.instr = instr;
}
}

@ -18,7 +18,12 @@
*/
package jode.flow;
import jode.*;
import jode.TabbedPrintWriter;
import jode.Expression;
import jode.ConstOperator;
import jode.Type;
import jode.LocalInfo;
import jode.LocalStoreOperator;
/**
* This is the structured block for an Loop block.
@ -29,23 +34,23 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
public static final int DOWHILE = 1;
public static final int FOR = 2;
public static final Instruction TRUE =
public static final Expression TRUE =
new ConstOperator(Type.tBoolean, "1");
public static final Instruction FALSE =
public static final Expression FALSE =
new ConstOperator(Type.tBoolean, "0");
/**
* The condition. Must be of boolean type.
*/
Instruction cond;
Expression cond;
/**
* The init instruction, only valid if type == FOR.
*/
Instruction init;
Expression init;
/**
* The increase instruction, only valid if type == FOR.
*/
Instruction incr;
Expression incr;
/**
* True, if the initializer is a declaration.
@ -77,7 +82,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
return null;
}
public LoopBlock(int type, Instruction cond) {
public LoopBlock(int type, Expression cond) {
this.type = type;
this.cond = cond;
this.mayChangeJump = (cond == TRUE);
@ -89,11 +94,11 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
body.setFlowBlock(flowBlock);
}
public Instruction getCondition() {
public Expression getCondition() {
return cond;
}
public void setCondition(Instruction cond) {
public void setCondition(Expression cond) {
this.cond = cond;
mayChangeJump = false;
}
@ -113,7 +118,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
StructuredBlock newBlock) {
if (bodyBlock == oldBlock)
bodyBlock = newBlock;
else
@ -133,12 +138,11 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
{
if (type == FOR && init != null
&& (outer == null || !outer.used.contains(local))
&& init instanceof Expression
&& ((Expression)init).getOperator() instanceof LocalStoreOperator
&& ((LocalStoreOperator) ((Expression)init).getOperator())
.getLocalInfo() == local.getLocalInfo()) {
&& init.getOperator() instanceof LocalStoreOperator
&& ((LocalStoreOperator) init.getOperator()).getLocalInfo()
== local.getLocalInfo())
isDeclaration = true;
} else
else
super.dumpDeclaration(writer, local);
}
@ -168,8 +172,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
case FOR:
writer.print("for (");
if (isDeclaration)
writer.print(((LocalStoreOperator)
((Expression)init).getOperator())
writer.print(((LocalStoreOperator) init.getOperator())
.getLocalInfo().getType().toString()
+ " " + init.simplify().toString());
else if (init != null)

@ -18,7 +18,7 @@
*/
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.NopOperator;
public class RemoveEmpty implements Transformation {
@ -28,37 +28,31 @@ public class RemoveEmpty implements Transformation {
}
public boolean removeNop(FlowBlock flow) {
StructuredBlock block;
SequentialBlock sequBlock;
Instruction instr;
try {
block = flow.lastModified;
Instruction prevInstr =
((InstructionContainer)block).getInstruction();
if (!(prevInstr instanceof NopOperator))
return false;
StructuredBlock block = flow.lastModified;
if (block instanceof InstructionContainer
&& block.outer instanceof SequentialBlock
&& block.outer.getSubBlocks()[0] instanceof InstructionBlock) {
sequBlock = (SequentialBlock)block.outer;
if (sequBlock.getSubBlocks()[1] != block)
return false;
InstructionContainer ic = (InstructionContainer) block;
InstructionBlock prev =
(InstructionBlock) sequBlock.getSubBlocks()[0];
if (prev.jump != null)
Expression nopInstr = ic.getInstruction();
if (!(nopInstr instanceof NopOperator)
|| nopInstr.getType() == jode.Type.tVoid)
return false;
instr = (Instruction) prev.getInstruction();
InstructionBlock prev =
(InstructionBlock) ic.outer.getSubBlocks()[0];
Expression instr = prev.getInstruction();
if (instr.getType() == jode.Type.tVoid)
return false;
instr.setType(prevInstr.getType());
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {
return false;
instr.setType(nopInstr.getType());
ic.setInstruction(instr);
ic.replace(ic.outer, ic);
return true;
}
((InstructionContainer)block).setInstruction(instr);
block.replace(sequBlock, block);
flow.lastModified = block;
return true;
return false;
}
public boolean removeEmpty(FlowBlock flow) {

@ -19,7 +19,7 @@
package jode.flow;
import jode.TabbedPrintWriter;
import jode.Instruction;
import jode.Expression;
/**
* This is the structured block for an Return block.
@ -30,7 +30,7 @@ public class ReturnBlock extends InstructionContainer {
super(null);
}
public ReturnBlock(Instruction instr, Jump jump) {
public ReturnBlock(Expression instr, Jump jump) {
super(instr, jump);
}
@ -42,22 +42,6 @@ public class ReturnBlock extends InstructionContainer {
return declare != null && !declare.isEmpty();
}
/**
* Get the underlying instruction.
* @return the underlying instruction.
*/
public Instruction getInstruction() {
return instr;
}
/**
* Change the underlying instruction.
* @param instr the new underlying instruction.
*/
public void setInstruction(Instruction instr) {
this.instr = instr;
}
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException
{

@ -47,7 +47,8 @@ public class SequentialBlock extends StructuredBlock {
public void checkConsistent() {
super.checkConsistent();
if (subBlocks[0].jump != null
|| (jump != null && subBlocks[1].jump != null))
|| subBlocks[0] instanceof SequentialBlock
|| jump != null)
throw new jode.AssertError("Inconsistency");
}

@ -289,18 +289,13 @@ public abstract class StructuredBlock {
public void removeBlock() {
if (outer instanceof SequentialBlock) {
if (outer.getSubBlocks()[1] == this) {
if (jump != null)
outer.getSubBlocks()[0].moveJump(jump);
outer.getSubBlocks()[0].replace(outer, null);
return;
} else if (outer.outer instanceof SequentialBlock) {
if (jump != null)
outer.outer.getSubBlocks()[0].moveJump(jump);
} else
outer.getSubBlocks()[1].replace(outer, null);
return;
}
return;
}
EmptyBlock eb = new EmptyBlock();

@ -27,7 +27,7 @@ public class SwitchBlock extends InstructionContainer
implements BreakableBlock {
CaseBlock[] caseBlocks;
public SwitchBlock(jode.Instruction instr,
public SwitchBlock(jode.Expression instr,
int[] cases, int[] dests) {
super(instr);
this.caseBlocks = new CaseBlock[dests.length];
@ -139,15 +139,6 @@ implements BreakableBlock {
writer.println("}");
}
public void setInstruction(jode.Instruction instr) {
super.setInstruction(instr);
jode.Type type = instr.getType();
if (type != caseBlocks[0].type) {
for (int i=0; i < caseBlocks.length; i++)
caseBlocks[i].type = type;
}
}
/**
* Returns all sub block of this structured block.
*/

@ -17,7 +17,7 @@
* $Id$
*/
package jode.flow;
import jode.Instruction;
import jode.Expression;
import jode.LocalInfo;
import jode.TabbedPrintWriter;
@ -28,7 +28,7 @@ import jode.TabbedPrintWriter;
*/
public class SynchronizedBlock extends StructuredBlock {
Instruction object;
Expression object;
LocalInfo local;
boolean isEntered;

@ -19,13 +19,13 @@
package jode.flow;
import jode.TabbedPrintWriter;
import jode.Instruction;
import jode.Expression;
/**
* This is the structured block for an Throw block.
*/
public class ThrowBlock extends ReturnBlock {
public ThrowBlock(Instruction instr, Jump jump) {
public ThrowBlock(Expression instr, Jump jump) {
super(instr, jump);
}

Loading…
Cancel
Save