git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@72 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 62fa808a9b
commit c9ed2748de
  1. 39
      jode/jode/bytecode/Opcodes.java
  2. 8
      jode/jode/decompiler/ClassAnalyzer.java
  3. 10
      jode/jode/decompiler/LocalInfo.java
  4. 61
      jode/jode/expr/ComplexExpression.java
  5. 16
      jode/jode/expr/ConstOperator.java
  6. 51
      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. 60
      jode/jode/flow/CatchBlock.java
  14. 40
      jode/jode/flow/CatchFinallyBlock.java
  15. 72
      jode/jode/flow/CombineIfGotoExpressions.java
  16. 12
      jode/jode/flow/ConditionalBlock.java
  17. 28
      jode/jode/flow/CreateAssignExpression.java
  18. 26
      jode/jode/flow/CreateConstantArray.java
  19. 109
      jode/jode/flow/CreateExpression.java
  20. 19
      jode/jode/flow/CreateForInitializer.java
  21. 13
      jode/jode/flow/CreateIfThenElseOperator.java
  22. 68
      jode/jode/flow/CreateNewConstructor.java
  23. 25
      jode/jode/flow/CreatePrePostIncExpression.java
  24. 452
      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. 35
      jode/jode/flow/LoopBlock.java
  29. 44
      jode/jode/flow/RemoveEmpty.java
  30. 20
      jode/jode/flow/ReturnBlock.java
  31. 3
      jode/jode/flow/SequentialBlock.java
  32. 7
      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, public static FlowBlock createNormal(CodeAnalyzer ca,
int addr, int length, int addr, int length,
Instruction instr) Expression instr)
{ {
return new FlowBlock(ca, addr, length, return new FlowBlock(ca, addr, length,
new InstructionBlock(instr, new InstructionBlock(instr,
new Jump(addr+length))); new Jump(addr+length)));
} }
public static FlowBlock createGoto(CodeAnalyzer ca, public static FlowBlock createSpecial(CodeAnalyzer ca,
int addr, int length, int addr, int length,
int destAddr) 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)
{ {
return new FlowBlock(ca, addr, length, return new FlowBlock(ca, addr, length,
new EmptyBlock(new Jump(destAddr))); new EmptyBlock(new Jump(destAddr)));
@ -283,7 +291,7 @@ public abstract class Opcodes {
public static FlowBlock createIfGoto(CodeAnalyzer ca, public static FlowBlock createIfGoto(CodeAnalyzer ca,
int addr, int length, int addr, int length,
int destAddr, Instruction instr) int destAddr, Expression instr)
{ {
ConditionalBlock ifBlock = ConditionalBlock ifBlock =
new ConditionalBlock(instr, new ConditionalBlock(instr,
@ -297,7 +305,7 @@ public abstract class Opcodes {
int[] cases, int[] dests) int[] cases, int[] dests)
{ {
return new FlowBlock(ca, addr, length, return new FlowBlock(ca, addr, length,
new SwitchBlock(new NopOperator(Type.tInt), new SwitchBlock(new NopOperator(Type.tUInt),
cases, dests)); cases, dests));
} }
@ -441,11 +449,11 @@ public abstract class Opcodes {
(ca, addr, 1, new PopOperator(opcode - opc_pop + 1)); (ca, addr, 1, new PopOperator(opcode - opc_pop + 1));
case opc_dup: case opc_dup_x1: case opc_dup_x2: case opc_dup: case opc_dup_x1: case opc_dup_x2:
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: case opc_dup2: case opc_dup2_x1: case opc_dup2_x2:
return createNormal return createSpecial
(ca, addr, 1, new DupOperator (ca, addr, 1, SpecialBlock.DUP,
((opcode - opc_dup)%3, (opcode - opc_dup)/3+1)); (opcode - opc_dup)/3+1, (opcode - opc_dup)%3);
case opc_swap: 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_iadd: case opc_ladd: case opc_fadd: case opc_dadd:
case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub:
case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul:
@ -629,8 +637,9 @@ public abstract class Opcodes {
CpoolClass cpcls = (CpoolClass) CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant(stream.readUnsignedShort()); ca.method.classAnalyzer.getConstant(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString()); Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal return createNormal
(ca, addr, 3, new NewOperator(type, type.toString())); (ca, addr, 3, new NewOperator(type));
} }
case opc_newarray: { case opc_newarray: {
Type type; Type type;
@ -646,6 +655,7 @@ public abstract class Opcodes {
default: default:
throw new ClassFormatError("Invalid newarray operand"); throw new ClassFormatError("Invalid newarray operand");
} }
type.useType();
return createNormal return createNormal
(ca, addr, 2, new NewArrayOperator(Type.tArray(type), 1)); (ca, addr, 2, new NewArrayOperator(Type.tArray(type), 1));
} }
@ -654,6 +664,7 @@ public abstract class Opcodes {
ca.method.classAnalyzer.getConstant ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString()); Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal return createNormal
(ca, addr, 3, new NewArrayOperator(Type.tArray(type), 1)); (ca, addr, 3, new NewArrayOperator(Type.tArray(type), 1));
} }
@ -670,18 +681,18 @@ public abstract class Opcodes {
ca.method.classAnalyzer.getConstant ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString()); Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal return createNormal
(ca, addr, 3, new CheckCastOperator (ca, addr, 3, new CheckCastOperator(type));
(type, type.toString()));
} }
case opc_instanceof: { case opc_instanceof: {
CpoolClass cpcls = (CpoolClass) CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString()); Type type = Type.tClassOrArray(cpcls.getName().getString());
type.useType();
return createNormal return createNormal
(ca, addr, 3, (ca, addr, 3, new InstanceOfOperator(type));
new InstanceOfOperator(type, type.toString()));
} }
case opc_monitorenter: case opc_monitorenter:
return createNormal(ca, addr, 1, return createNormal(ca, addr, 1,

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

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

@ -69,34 +69,59 @@ public class ComplexExpression extends Expression {
return new ComplexExpression(negop, new Expression[] { this }); 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 if (e instanceof ComplexExpression
&& e.getOperator() instanceof StoreInstruction) { && e.getOperator() instanceof StoreInstruction) {
ComplexExpression ce = (ComplexExpression) e; ComplexExpression ce = (ComplexExpression) e;
StoreInstruction store = (StoreInstruction) e.getOperator(); StoreInstruction store = (StoreInstruction) e.getOperator();
if (store.matches(operator)) { if (store.matches(operator)) {
int i; for (int i=0; i < ce.subExpressions.length-1; i++) {
for (i=0; i < ce.subExpressions.length-1; i++) {
if (!ce.subExpressions[i].equals(subExpressions[i])) if (!ce.subExpressions[i].equals(subExpressions[i]))
break; return -1;
} }
if (i == ce.subExpressions.length-1) { return 1;
operator =
new AssignOperator(store.getOperatorIndex(), store);
subExpressions = ce.subExpressions;
return this;
} }
for (int i=0; i < subExpressions.length; i++) {
int can = subExpressions[i].canCombine(e);
if (can != 0)
return can;
}
}
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++) { for (int i=0; i < subExpressions.length; i++) {
Expression combined = subExpressions[i].tryToCombine(e); Expression combined = subExpressions[i].combine(e);
if (combined != null) { if (combined != null) {
subExpressions[i] = combined; subExpressions[i] = combined;
subExpressions[i].parent = this; subExpressions[i].parent = this;
return this; return this;
} }
} }
} throw new AssertError("combine didn't succeed");
return null;
} }
public Operator getOperator() { public Operator getOperator() {
@ -234,7 +259,7 @@ public class ComplexExpression extends Expression {
return new ComplexExpression return new ComplexExpression
(new StringAddOperator(), new Expression[] (new StringAddOperator(), new Expression[]
{ e, (Expression)subExpressions[1].simplify() }); { e, subExpressions[1].simplify() });
} }
if (operator instanceof ConstructorOperator && if (operator instanceof ConstructorOperator &&
operator.getType().isOfType(Type.tStringBuffer)) { operator.getType().isOfType(Type.tStringBuffer)) {
@ -243,12 +268,12 @@ public class ComplexExpression extends Expression {
return emptyString; return emptyString;
else if (subExpressions.length == 2 && else if (subExpressions.length == 2 &&
subExpressions[1].getType().isOfType(Type.tString)) subExpressions[1].getType().isOfType(Type.tString))
return (Expression) subExpressions[1].simplify(); return subExpressions[1].simplify();
} }
return null; return null;
} }
public Instruction simplify() { public Expression simplify() {
if (operator instanceof IfThenElseOperator && if (operator instanceof IfThenElseOperator &&
operator.getType().isOfType(Type.tBoolean)) { operator.getType().isOfType(Type.tBoolean)) {
if (subExpressions[1].getOperator() instanceof ConstOperator && if (subExpressions[1].getOperator() instanceof ConstOperator &&
@ -334,7 +359,7 @@ public class ComplexExpression extends Expression {
.replace(java.io.File.separatorChar, '.') .replace(java.io.File.separatorChar, '.')
.equals("java.lang.StringBuffer")) .equals("java.lang.StringBuffer"))
&& subExpressions.length == 1) { && subExpressions.length == 1) {
Instruction simple = subExpressions[0].simplifyStringBuffer(); Expression simple = subExpressions[0].simplifyStringBuffer();
if (simple != null) if (simple != null)
return simple; return simple;
} }
@ -352,10 +377,10 @@ public class ComplexExpression extends Expression {
return new ComplexExpression return new ComplexExpression
(new StringAddOperator(), new Expression[] (new StringAddOperator(), new Expression[]
{ emptyString, (Expression) subExpressions[0].simplify() }); { emptyString, subExpressions[0].simplify() });
} }
for (int i=0; i< subExpressions.length; i++) { for (int i=0; i< subExpressions.length; i++) {
subExpressions[i] = (Expression) subExpressions[i].simplify(); subExpressions[i] = subExpressions[i].simplify();
subExpressions[i].parent = this; subExpressions[i].parent = this;
} }
return this; return this;

@ -46,6 +46,22 @@ public class ConstOperator extends NoArgOperator {
return "false"; return "false";
else if (value.equals("1")) else if (value.equals("1"))
return "true"; 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) { } else if (parent != null) {
int opindex = parent.getOperator().getOperatorIndex(); int opindex = parent.getOperator().getOperatorIndex();
if (opindex >= OPASSIGN_OP + ADD_OP if (opindex >= OPASSIGN_OP + ADD_OP

@ -19,12 +19,21 @@
package jode; package jode;
public abstract class Expression extends Instruction { public abstract class Expression {
protected Type type;
ComplexExpression parent = null; ComplexExpression parent = null;
public Expression(Type type) { 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 }); 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 if (e instanceof ComplexExpression
&& e.getOperator() instanceof StoreInstruction) { && e.getOperator() instanceof StoreInstruction) {
ComplexExpression ce = (ComplexExpression) e;
StoreInstruction store = (StoreInstruction) e.getOperator(); StoreInstruction store = (StoreInstruction) e.getOperator();
if (store.matches(getOperator()) if (store.matches(getOperator()))
&& ce.subExpressions.length == 1) { return 1;
return new ComplexExpression
(new AssignOperator(store.getOperatorIndex(), store),
ce.subExpressions);
} }
return 0;
} }
return null;
/**
* 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() { Expression simplifyStringBuffer() {
@ -60,6 +89,8 @@ public abstract class Expression extends Instruction {
public abstract Operator getOperator(); public abstract Operator getOperator();
public abstract String toString();
String toString(int minPriority) { String toString(int minPriority) {
String result = toString(); String result = toString();
if (getOperator().getPriority() < minPriority) if (getOperator().getPriority() < minPriority)

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

@ -34,6 +34,6 @@ public class MonitorEnterOperator extends SimpleOperator {
} }
public String toString(String[] operands) { 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) { public String toString(String[] operands) {
return "monitorexit "+operands[0]; return "MONITOREXIT "+operands[0];
} }
} }

@ -19,21 +19,38 @@
package jode; 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) { public NopOperator(Type type) {
super(type); super(type, 0, 1);
} }
public NopOperator() { 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) { public boolean equals(Object o) {
return (o instanceof NopOperator); return (o instanceof NopOperator);
} }
public String toString() public String toString(String[] operands) {
{ if (type == Type.tVoid)
return "nop"; return "/* nop */";
return operands[0];
} }
} }

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

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

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

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

@ -27,66 +27,74 @@ import jode.BinaryOperator;
public class CombineIfGotoExpressions implements Transformation{ public class CombineIfGotoExpressions implements Transformation{
public boolean transform(FlowBlock flow) { public boolean transform(FlowBlock flow) {
Expression[] e; if (!(flow.lastModified instanceof ConditionalBlock)
ConditionalBlock cb; || !(flow.lastModified.outer instanceof SequentialBlock))
Jump prevJump;
int operator;
try {
cb = (ConditionalBlock) flow.lastModified;
SequentialBlock sequBlock = (SequentialBlock) cb.outer;
if (sequBlock.subBlocks[1] != cb)
return false; return false;
// jode.Assert.assert(sequBlock.jump == null) ConditionalBlock cb = (ConditionalBlock) flow.lastModified;
SequentialBlock sequBlock = (SequentialBlock) cb.outer;
Expression[] e = new Expression[2];
e[1] = cb.getInstruction();
Expression lastCombined = e[1];
e = new Expression[2];
e[1] = (Expression)cb.getInstruction();
while (sequBlock.subBlocks[0] instanceof InstructionBlock) { while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
InstructionBlock ib = InstructionBlock ib =
(InstructionBlock) sequBlock.subBlocks[0]; (InstructionBlock) sequBlock.subBlocks[0];
Expression expr = (Expression) ib.getInstruction();
if (!expr.isVoid()) if (!(sequBlock.outer instanceof SequentialBlock))
return false; return false;
Expression combined = e[1].tryToCombine(expr); Expression expr = ib.getInstruction();
if (combined == null) 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; return false;
cb.replace(sequBlock, cb); lastCombined = expr;
cb.setInstruction(combined);
e[1] = combined; sequBlock = (SequentialBlock) sequBlock.outer;
sequBlock = (SequentialBlock) cb.outer;
} }
if (sequBlock.subBlocks[0] instanceof ConditionalBlock) {
ConditionalBlock cbprev = ConditionalBlock cbprev =
(ConditionalBlock) sequBlock.subBlocks[0]; (ConditionalBlock) sequBlock.subBlocks[0];
if (cbprev.jump != null) Jump prevJump = cbprev.trueBlock.jump;
return false;
prevJump = ((EmptyBlock) cbprev.trueBlock).jump;
int operator;
if (prevJump.destination == cb.jump.destination) { if (prevJump.destination == cb.jump.destination) {
operator = BinaryOperator.LOG_AND_OP; operator = BinaryOperator.LOG_AND_OP;
e[0] = ((Expression)cbprev.getInstruction()).negate(); e[0] = cbprev.getInstruction().negate();
} else if (prevJump.destination } else if (prevJump.destination == cb.trueBlock.jump.destination) {
== ((EmptyBlock) cb.trueBlock).jump.destination) {
operator = BinaryOperator.LOG_OR_OP; operator = BinaryOperator.LOG_OR_OP;
e[0] = (Expression)cbprev.getInstruction(); e[0] = cbprev.getInstruction();
} else } else
return false; return false;
} catch (ClassCastException ex) {
return false; sequBlock = (SequentialBlock) cb.outer;
} catch (NullPointerException ex) { while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
return false; /* 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); flow.removeSuccessor(prevJump);
prevJump.prev.removeJump(); prevJump.prev.removeJump();
Expression cond = Expression cond =
new ComplexExpression new ComplexExpression
(new BinaryOperator(Type.tBoolean, operator), e); (new BinaryOperator(Type.tBoolean, operator), e);
cb.setInstruction(cond); cb.setInstruction(cond);
cb.replace(cb.outer, cb); cb.replace(sequBlock, cb);
return true; return true;
} }
return false;
}
} }

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

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

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

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

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

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

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

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

@ -71,7 +71,9 @@ public class FlowBlock {
StructuredBlock block; 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; StructuredBlock lastModified;
@ -132,36 +134,6 @@ public class FlowBlock {
FlowBlock successor = jump.destination; 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 the jump is the jump of the appendBlock, skip it.
*/ */
if (jump.prev == appendBlock) { if (jump.prev == appendBlock) {
@ -169,24 +141,9 @@ public class FlowBlock {
continue; continue;
} }
/* Now move the jump as far to the outer as possible, /* jump.prev.outer is not null since appendBlock is an
* without leaving appendBlock. * outer block.
*
* 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);
}
/* remove this jump if it jumps to the getNextFlowBlock(). /* remove this jump if it jumps to the getNextFlowBlock().
*/ */
@ -196,123 +153,102 @@ public class FlowBlock {
continue; continue;
} }
if (jump.prev instanceof EmptyBlock && if (jump.prev.outer instanceof ConditionalBlock) {
jump.prev.outer instanceof ConditionalBlock) {
if (jump.prev.outer.jump != null) {
StructuredBlock prev = jump.prev; StructuredBlock prev = jump.prev;
ConditionalBlock cb = (ConditionalBlock) prev.outer; ConditionalBlock cb = (ConditionalBlock) prev.outer;
Instruction instr = cb.getInstruction(); 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.jump is null (see above), so cb must have a cb.setInstruction(instr.negate());
* successor in this block, that means cb.outer is not cb.swapJump(jump.prev);
* null.
/* 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 /* If this is the first instruction of a while and the
* condition of the while is true, use the condition * condition of the while is true, use the condition
* as while 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 */ LoopBlock loopBlock = (cb.outer instanceof LoopBlock) ?
if (cb.outer instanceof SequentialBlock && (LoopBlock) cb.outer : (LoopBlock) cb.outer.outer;
cb.outer.getSubBlocks()[0] == cb &&
cb.outer.outer instanceof LoopBlock) {
LoopBlock loopBlock = (LoopBlock) cb.outer.outer;
if (loopBlock.getCondition() == LoopBlock.TRUE && if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() != LoopBlock.DOWHILE && loopBlock.getType() != LoopBlock.DOWHILE &&
loopBlock.getNextFlowBlock() == successor && loopBlock.getNextFlowBlock() == successor) {
/*XXX remove following after expression cleanup */
instr instanceof Expression) {
prev.removeJump(); jump.prev.removeJump();
loopBlock.setCondition(((Expression)instr).negate()); loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); loopBlock.moveDefinitions(cb, null);
/* Now remove the whole ConditionalBlock including cb.removeBlock();
* 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]);
/* Note that cb.outer != appendBlock because /* Note that cb.outer != appendBlock because
* appendBlock contains loopBlock. This is * appendBlock contains loopBlock. This is
* because lastModified can't be an * because lastModified is in the outermost
* instruction inside a loop block. * block.
*
* XXX I have to make a clear precondition for this.
*/ */
continue; 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 } else if (cb.outer instanceof SequentialBlock
&& cb.outer.getSubBlocks()[1] == cb) { && cb.outer.getSubBlocks()[1] == cb) {
/* And a third time for do/while loops, where the jump /* And now for do/while loops, where the jump is
* is at the end of the loop. Note that all ifs are * at the end of the loop.
* disjunct.
*/ */
/* First find the beginning of the loop */ /* First find the beginning of the loop */
StructuredBlock sb = cb.outer; StructuredBlock sb = cb.outer.outer;
while (sb.outer instanceof SequentialBlock) { while (sb instanceof SequentialBlock) {
sb = sb.outer; sb = sb.outer;
} }
/* sb is now the first and cb is the last /* sb is now the first and cb is the last
* instruction in the current block. * instruction in the current block.
*/ */
if (sb.outer instanceof LoopBlock) { if (sb instanceof LoopBlock) {
LoopBlock loopBlock = (LoopBlock) sb.outer; LoopBlock loopBlock = (LoopBlock) sb;
if (loopBlock.getCondition() == LoopBlock.TRUE && if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() == LoopBlock.WHILE && loopBlock.getType() == LoopBlock.WHILE &&
loopBlock.getNextFlowBlock() == successor && loopBlock.getNextFlowBlock() == successor) {
instr instanceof Expression) {
prev.removeJump(); jump.prev.removeJump();
loopBlock.setType(LoopBlock.DOWHILE); loopBlock.setType(LoopBlock.DOWHILE);
loopBlock.setCondition(((Expression)instr).negate()); loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); loopBlock.moveDefinitions(cb, null);
/* We pretend here that cb.outer has no jump. cb.removeBlock();
* (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 */
continue; continue;
} }
} }
@ -325,33 +261,48 @@ public class FlowBlock {
if (cb.outer instanceof SequentialBlock && if (cb.outer instanceof SequentialBlock &&
cb.outer.getSubBlocks()[0] == cb && cb.outer.getSubBlocks()[0] == cb &&
(cb.outer.getNextFlowBlock() == successor || (cb.outer.getNextFlowBlock() == successor ||
cb.outer.jumpMayBeChanged()) && cb.outer.jumpMayBeChanged())) {
instr instanceof Expression) {
SequentialBlock sequBlock = SequentialBlock sequBlock =
(SequentialBlock) cb.outer; (SequentialBlock) cb.outer;
IfThenElseBlock newIfBlock = IfThenElseBlock newIfBlock =
new IfThenElseBlock(((Expression)instr).negate()); new IfThenElseBlock(instr.negate());
newIfBlock.replace(sequBlock, sequBlock.getSubBlocks()[1]); newIfBlock.replace(sequBlock, sequBlock.getSubBlocks()[1]);
newIfBlock.setThenBlock(sequBlock.getSubBlocks()[1]); newIfBlock.setThenBlock(sequBlock.getSubBlocks()[1]);
newIfBlock.moveJump(sequBlock.jump);
if (appendBlock == sequBlock)
appendBlock = newIfBlock;
if (newIfBlock.getNextFlowBlock() != successor && if (appendBlock == sequBlock) {
newIfBlock != appendBlock) { newIfBlock.moveJump(appendBlock.jump);
appendBlock = newIfBlock;
jump.prev.removeJump();
} else {
newIfBlock.moveJump(jump); newIfBlock.moveJump(jump);
/* consider this jump again */ /* consider this jump again */
jumps.push(jump); jumps.push(jump);
continue;
} else {
prev.removeJump();
continue;
}
} }
continue;
} }
} else {
/* 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 /* if this is a jumps at the end of a then block belonging
@ -360,44 +311,30 @@ public class FlowBlock {
* if-then block with a if-then-else block and remove the * if-then block with a if-then-else block and remove the
* unconditional jump. * unconditional jump.
*/ */
else if (jump.prev.outer instanceof IfThenElseBlock) { if (sb instanceof IfThenElseBlock
&& sb.outer instanceof SequentialBlock
IfThenElseBlock ifBlock = && sb.outer.getSubBlocks()[0] == sb) {
(IfThenElseBlock)jump.prev.outer;
if (ifBlock.elseBlock == null
&& ifBlock.outer instanceof SequentialBlock
&& ifBlock.outer.getSubBlocks()[0] == ifBlock) {
StructuredBlock elseBlock =
ifBlock.outer.getSubBlocks()[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 (appendBlock == elseBlock.outer) IfThenElseBlock ifBlock = (IfThenElseBlock) sb;
appendBlock = ifBlock; SequentialBlock sequBlock = (SequentialBlock) sb.outer;
StructuredBlock elseBlock = sequBlock.subBlocks[1];
ifBlock.replace(ifBlock.outer, elseBlock); if (ifBlock.elseBlock == null
if (elseBlock.jump != null) && (elseBlock.getNextFlowBlock() == successor
ifBlock.moveJump(elseBlock.jump); || elseBlock.jumpMayBeChanged())) {
ifBlock.replace(sequBlock, elseBlock);
ifBlock.setElseBlock(elseBlock); ifBlock.setElseBlock(elseBlock);
if (ifBlock.getNextFlowBlock() != successor) { if (appendBlock == sequBlock) {
ifBlock.moveJump(jump); ifBlock.moveJump(appendBlock.jump);
appendBlock = ifBlock;
jump.prev.removeJump();
} else {
/* consider this jump again */ /* consider this jump again */
ifBlock.moveJump(jump);
jumps.push(jump); jumps.push(jump);
} else }
jump.prev.removeJump();
continue; continue;
} }
} }
@ -586,14 +523,21 @@ 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() { public void checkConsistent() {
if (!Decompiler.doChecks) if (!Decompiler.doChecks)
return; return;
// try {
if (block.outer != null || block.flowBlock != this) { if (block.outer != null || block.flowBlock != this) {
throw new AssertError("Inconsistency"); throw new AssertError("Inconsistency");
} }
block.checkConsistent(); block.checkConsistent();
Enumeration preds = predecessors.elements(); Enumeration preds = predecessors.elements();
while (preds.hasMoreElements()) { while (preds.hasMoreElements()) {
FlowBlock pred = (FlowBlock)preds.nextElement(); FlowBlock pred = (FlowBlock)preds.nextElement();
@ -604,6 +548,12 @@ public class FlowBlock {
throw new AssertError("Inconsistency"); throw new AssertError("Inconsistency");
} }
StructuredBlock last = lastModified;
while (last.outer instanceof SequentialBlock)
last = last.outer;
if (last.outer != null)
throw new AssertError("Inconsistency");
Enumeration keys = successors.keys(); Enumeration keys = successors.keys();
Enumeration stacks = successors.elements(); Enumeration stacks = successors.elements();
while (keys.hasMoreElements()) { while (keys.hasMoreElements()) {
@ -636,10 +586,14 @@ public class FlowBlock {
if (blocks[i] == prev) if (blocks[i] == prev)
continue prev_loop; continue prev_loop;
throw new RuntimeException("Inconsistency"); 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) { public boolean doT2(int start, int end) {
/* If there are no jumps to the beginning of this flow block /* If there are no jumps to the beginning of this flow block
* or if this block has other predecessors with a higher * or if this block has other predecessors with a not yet
* address, return false. The second condition make sure that * considered address, return false. The second condition
* the while isn't created up to the first continue. */ * make sure that not for each continue a while is created.
*/
if (!predecessors.contains(this)) if (!predecessors.contains(this))
return false; return false;
Enumeration preds = predecessors.elements(); Enumeration preds = predecessors.elements();
while (preds.hasMoreElements()) { while (preds.hasMoreElements()) {
FlowBlock predFlow = (FlowBlock) preds.nextElement(); FlowBlock predFlow = (FlowBlock) preds.nextElement();
@ -765,39 +719,30 @@ public class FlowBlock {
/* Update the in/out-Vectors now */ /* Update the in/out-Vectors now */
updateInOut(this, false, jumps); updateInOut(this, false, jumps);
StructuredBlock bodyBlock = block;
while (lastModified != block) /* If there is only one jump to the beginning and it is
lastModified = lastModified.outer; * the last jump (lastModified) and (there is a
* do/while(0) block surrounding everything but the last
transformation: * instruction, or the last instruction is a
do { * increase/decrease statement), replace the do/while(0)
/* If there is only one jump to the beginning and it is the * with a for(;;last_instr) resp. create a new one and
* last jump and (there is a do/while(0) block surrounding * replace breaks to do/while with continue to for. */
* 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 && boolean createdForBlock = false;
((Jump)jumps.peek()).prev instanceof InstructionBlock) {
InstructionBlock prev = if (jumps.size() == 1
(InstructionBlock) ((Jump)jumps.peek()).prev; && ((Jump)jumps.peek()).prev == lastModified
&& lastModified instanceof InstructionBlock) {
/* Now check if the jump is the last block in a chain Expression instr =
* of SequentialBlocks that have no surrounding blocks. ((InstructionBlock)lastModified).getInstruction();
*/ if (lastModified.outer instanceof SequentialBlock
StructuredBlock sb = prev; && lastModified.outer.getSubBlocks()[0]
while (sb.outer != null instanceof LoopBlock) {
&& sb.outer instanceof SequentialBlock
&& sb.outer.getSubBlocks()[1] == sb)
sb = sb.outer;
if (sb.outer == null && prev.outer != null LoopBlock lb =
&& prev.outer instanceof SequentialBlock (LoopBlock) lastModified.outer.getSubBlocks()[0];
&& prev.outer.getSubBlocks()[0] instanceof LoopBlock) {
LoopBlock lb = (LoopBlock) prev.outer.getSubBlocks()[0];
if (lb.cond == lb.FALSE && lb.type == lb.DOWHILE) { if (lb.cond == lb.FALSE && lb.type == lb.DOWHILE) {
/* The jump is directly following a /* The jump is directly following a
@ -810,51 +755,45 @@ public class FlowBlock {
LoopBlock forBlock = LoopBlock forBlock =
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE); new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE);
forBlock.replace(sb, sb); forBlock.replace(bodyBlock, bodyBlock);
forBlock.setBody(sb); forBlock.setBody(bodyBlock);
forBlock.incr = instr;
prev.outer.getSubBlocks()[0].replace(prev.outer, null); lastModified.removeJump();
forBlock.incr = prev.getInstruction();
forBlock.replaceBreakContinue(lb); forBlock.replaceBreakContinue(lb);
lb.bodyBlock.replace(lb, null); lb.bodyBlock.replace(lastModified.outer, null);
createdForBlock = true;
prev.removeJump();
lastModified = lb;
break transformation;
} }
} }
Instruction instr = prev.getInstruction(); if (!createdForBlock &&
Operator op; (instr.getOperator() instanceof StoreInstruction
if (sb.outer == null || instr.getOperator() instanceof IIncOperator)) {
&& instr instanceof Expression
&& ((op = ((Expression)instr).getOperator())
instanceof StoreInstruction
|| op instanceof IIncOperator)) {
/* The only jump is the jump of the last /* The only jump is the jump of the last
* instruction prev */ * instruction lastModified */
LoopBlock forBlock = LoopBlock forBlock =
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE); new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE);
forBlock.replace(sb, sb); forBlock.replace(bodyBlock, bodyBlock);
forBlock.setBody(sb); forBlock.setBody(bodyBlock);
prev.outer.getSubBlocks()[0].replace(prev.outer, null);
forBlock.incr = instr; forBlock.incr = instr;
prev.removeJump();
lastModified = forBlock; lastModified.removeJump();
break transformation; lastModified.outer.getSubBlocks()[0]
.replace(lastModified.outer, null);
createdForBlock = true;
} }
} }
if (!createdForBlock) {
/* Creating a for block didn't succeed; create a /* Creating a for block didn't succeed; create a
* while block instead. */ * while block instead. */
StructuredBlock bodyBlock = block;
/* Prepare the unification of the blocks: Make sure that /* Prepare the unification of the blocks: Make sure that
* bodyBlock has a jump. */ * bodyBlock has a jump.
*/
if (bodyBlock.jump == null) { if (bodyBlock.jump == null) {
Jump jump = new Jump(this); Jump jump = new Jump(this);
bodyBlock.setJump(jump); bodyBlock.setJump(jump);
@ -911,13 +850,12 @@ public class FlowBlock {
if (bodyBlock.jump != null if (bodyBlock.jump != null
&& bodyBlock.jump.destination == this) && bodyBlock.jump.destination == this)
bodyBlock.removeJump(); bodyBlock.removeJump();
}
lastModified = whileBlock;
} while (false);
/* remove ourself from the predecessor list. /* remove ourself from the predecessor list.
*/ */
predecessors.removeElement(this); predecessors.removeElement(this);
lastModified = block;
/* T2 analysis succeeded */ /* T2 analysis succeeded */
checkConsistent(); checkConsistent();
@ -1322,7 +1260,7 @@ public class FlowBlock {
removeJSR(subRoutine); removeJSR(subRoutine);
} }
public boolean isMonitorExit(Instruction instr, LocalInfo local) { public boolean isMonitorExit(Expression instr, LocalInfo local) {
if (instr instanceof ComplexExpression) { if (instr instanceof ComplexExpression) {
ComplexExpression expr = (ComplexExpression)instr; ComplexExpression expr = (ComplexExpression)instr;
if (expr.getOperator() instanceof MonitorExitOperator if (expr.getOperator() instanceof MonitorExitOperator
@ -1353,7 +1291,7 @@ public class FlowBlock {
subRoutine.analyzeSubRoutine(addr+length, end); subRoutine.analyzeSubRoutine(addr+length, end);
if (subRoutine.block instanceof InstructionBlock) { if (subRoutine.block instanceof InstructionBlock) {
Instruction instr = Expression instr =
((InstructionBlock)subRoutine.block) ((InstructionBlock)subRoutine.block)
.getInstruction(); .getInstruction();
if (isMonitorExit(instr, local)) { if (isMonitorExit(instr, local)) {
@ -1403,7 +1341,7 @@ public class FlowBlock {
continue; continue;
if (pred instanceof InstructionBlock) { if (pred instanceof InstructionBlock) {
Instruction instr = Expression instr =
((InstructionBlock)pred).getInstruction(); ((InstructionBlock)pred).getInstruction();
if (instr instanceof ComplexExpression if (instr instanceof ComplexExpression
&& ((ComplexExpression)instr) && ((ComplexExpression)instr)
@ -1502,8 +1440,8 @@ public class FlowBlock {
SequentialBlock catchBlock = (SequentialBlock) catchFlow.block; SequentialBlock catchBlock = (SequentialBlock) catchFlow.block;
int type = 0; int type = 0;
Instruction instr = Expression instr =
((InstructionBlock)catchBlock.subBlocks[0]).instr; ((InstructionBlock)catchBlock.subBlocks[0]).getInstruction();
if (instr instanceof ComplexExpression if (instr instanceof ComplexExpression
&& ((ComplexExpression)instr).getOperator() && ((ComplexExpression)instr).getOperator()
@ -1621,8 +1559,10 @@ public class FlowBlock {
changed = true; changed = true;
} }
} else if (catchFlow.block instanceof InstructionBlock } else if (catchFlow.block instanceof InstructionBlock
&& ((InstructionBlock) catchFlow.block).instr && ((InstructionBlock) catchFlow.block).getInstruction()
instanceof PopOperator instanceof PopOperator
&& ((PopOperator) ((InstructionBlock) catchFlow.block)
.getInstruction()).getCount() == 1
&& successors.size() == 1) { && successors.size() == 1) {
/* This is a special try/finally-block, where /* This is a special try/finally-block, where
@ -1630,12 +1570,14 @@ public class FlowBlock {
* similar. * similar.
*/ */
FlowBlock succ = catchFlow.block.jump.destination; FlowBlock succ = catchFlow.block.jump.destination;
Stack jumps = (Stack) successors.get(succ); Stack jumps = (Stack) successors.remove(succ);
Stack newJumps = new Stack(); updateInOut(succ, true, jumps);
newJumps.push(catchFlow.block.jump);
successors.put(succ, newJumps); Stack stack = new Stack();
jumps.removeElement(catchFlow.block.jump); stack.push(catchFlow.block.jump);
successors.put(succ, stack);
jumps.removeElement(catchFlow.block.jump);
if (rawBlock.tryBlock.jump == null) { if (rawBlock.tryBlock.jump == null) {
Jump jump = new Jump(succ); Jump jump = new Jump(succ);
rawBlock.tryBlock.setJump(jump); rawBlock.tryBlock.setJump(jump);
@ -1648,10 +1590,20 @@ public class FlowBlock {
CatchFinallyBlock newBlock = new CatchFinallyBlock(); CatchFinallyBlock newBlock = new CatchFinallyBlock();
newBlock.replace(rawBlock, rawBlock); newBlock.replace(rawBlock, rawBlock);
newBlock.setTryBlock(rawBlock.tryBlock); newBlock.setTryBlock(rawBlock.tryBlock);
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.setFinallyBlock(new EmptyBlock());
newBlock.moveJump(rawBlock.jump); newBlock.finallyBlock.moveJump(catchFlow.block.jump);
lastModified = newBlock.finallyBlock; }
lastModified.moveJump(catchFlow.block.jump); lastModified = newBlock;
changed = true; changed = true;
} }
checkConsistent(); checkConsistent();
@ -1667,8 +1619,7 @@ public class FlowBlock {
/* throws ClassCastException if something isn't as exspected. */ /* throws ClassCastException if something isn't as exspected. */
SequentialBlock sequBlock = (SequentialBlock) block; SequentialBlock sequBlock = (SequentialBlock) block;
LocalStoreOperator store = (LocalStoreOperator) LocalStoreOperator store = (LocalStoreOperator)
((Expression)((InstructionBlock)sequBlock.subBlocks[0]).instr) ((InstructionBlock)sequBlock.subBlocks[0]).instr.getOperator();
.getOperator();
while (sequBlock.subBlocks[1] instanceof SequentialBlock) while (sequBlock.subBlocks[1] instanceof SequentialBlock)
sequBlock = (SequentialBlock) sequBlock.subBlocks[1]; sequBlock = (SequentialBlock) sequBlock.subBlocks[1];
@ -1699,8 +1650,6 @@ public class FlowBlock {
SwitchBlock switchBlock = (SwitchBlock) block; SwitchBlock switchBlock = (SwitchBlock) block;
boolean changed = false; boolean changed = false;
StructuredBlock lastBlock = null; StructuredBlock lastBlock = null;
lastModified = block;
/* XXX - move to switchBlock??? */
for (int i=0; i < switchBlock.caseBlocks.length; i++) { for (int i=0; i < switchBlock.caseBlocks.length; i++) {
if (switchBlock.caseBlocks[i].subBlock != null if (switchBlock.caseBlocks[i].subBlock != null
&& switchBlock.caseBlocks[i].subBlock.jump != null) { && switchBlock.caseBlocks[i].subBlock.jump != null) {
@ -1878,8 +1827,7 @@ public class FlowBlock {
public String toString() { public String toString() {
try { try {
java.io.StringWriter strw = new java.io.StringWriter(); java.io.StringWriter strw = new java.io.StringWriter();
TabbedPrintWriter writer = TabbedPrintWriter writer = new TabbedPrintWriter(strw, " ");
new TabbedPrintWriter(strw, " ");
writer.println(super.toString()); writer.println(super.toString());
writer.tab(); writer.tab();
dumpSource(writer); dumpSource(writer);

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

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

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

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

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

@ -19,7 +19,7 @@
package jode.flow; package jode.flow;
import jode.TabbedPrintWriter; import jode.TabbedPrintWriter;
import jode.Instruction; import jode.Expression;
/** /**
* This is the structured block for an Return block. * This is the structured block for an Return block.
@ -30,7 +30,7 @@ public class ReturnBlock extends InstructionContainer {
super(null); super(null);
} }
public ReturnBlock(Instruction instr, Jump jump) { public ReturnBlock(Expression instr, Jump jump) {
super(instr, jump); super(instr, jump);
} }
@ -42,22 +42,6 @@ public class ReturnBlock extends InstructionContainer {
return declare != null && !declare.isEmpty(); 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) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {

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

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

@ -27,7 +27,7 @@ public class SwitchBlock extends InstructionContainer
implements BreakableBlock { implements BreakableBlock {
CaseBlock[] caseBlocks; CaseBlock[] caseBlocks;
public SwitchBlock(jode.Instruction instr, public SwitchBlock(jode.Expression instr,
int[] cases, int[] dests) { int[] cases, int[] dests) {
super(instr); super(instr);
this.caseBlocks = new CaseBlock[dests.length]; this.caseBlocks = new CaseBlock[dests.length];
@ -139,15 +139,6 @@ implements BreakableBlock {
writer.println("}"); 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. * Returns all sub block of this structured block.
*/ */

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

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

Loading…
Cancel
Save