*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@107 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent a421adad08
commit ba05fcd077
  1. 1483
      jode/jode/bytecode/Opcodes.java
  2. 133
      jode/jode/decompiler/CodeAnalyzer.java
  3. 14
      jode/jode/expr/ComplexExpression.java
  4. 50
      jode/jode/expr/ConstantArrayOperator.java
  5. 5
      jode/jode/expr/ConstructorOperator.java
  6. 3
      jode/jode/expr/Expression.java
  7. 22
      jode/jode/flow/CombineIfGotoExpressions.java
  8. 20
      jode/jode/flow/CompleteSynchronized.java
  9. 7
      jode/jode/flow/ConditionalBlock.java
  10. 61
      jode/jode/flow/CreateAssignExpression.java
  11. 180
      jode/jode/flow/CreateConstantArray.java
  12. 156
      jode/jode/flow/CreateExpression.java
  13. 20
      jode/jode/flow/CreateForInitializer.java
  14. 260
      jode/jode/flow/CreateIfThenElseOperator.java
  15. 71
      jode/jode/flow/CreateNewConstructor.java
  16. 215
      jode/jode/flow/CreatePrePostIncExpression.java
  17. 268
      jode/jode/flow/FlowBlock.java
  18. 10
      jode/jode/flow/InstructionContainer.java
  19. 8
      jode/jode/flow/LoopBlock.java
  20. 69
      jode/jode/flow/RemoveEmpty.java
  21. 5
      jode/jode/flow/SpecialBlock.java
  22. 52
      jode/jode/flow/StructuredBlock.java
  23. 4
      jode/jode/flow/SynchronizedBlock.java
  24. 2
      jode/jode/type/ClassInterfacesType.java

File diff suppressed because it is too large Load Diff

@ -36,7 +36,6 @@ import gnu.bytecode.Spy;
public class CodeAnalyzer implements Analyzer { public class CodeAnalyzer implements Analyzer {
TransformExceptionHandlers handler;
FlowBlock methodHeader; FlowBlock methodHeader;
CodeAttr code; CodeAttr code;
MethodAnalyzer method; MethodAnalyzer method;
@ -71,19 +70,78 @@ public class CodeAnalyzer implements Analyzer {
param.addElement(getLocalInfo(0, i)); param.addElement(getLocalInfo(0, i));
} }
void readCode(CodeAttr bincode) private final static int SEQUENTIAL = 1;
private final static int PREDECESSORS = 2;
/**
* @param code The code array.
* @param handlers The exception handlers.
*/
void readCode(byte[] code, short[] handlers)
throws ClassFormatError throws ClassFormatError
{ {
byte[] code = bincode.getCode(); byte[] flags = new byte[code.length];
int[] lengths = new int[code.length];
try {
DataInputStream stream =
new DataInputStream(new ByteArrayInputStream(code));
for (int addr = 0; addr < code.length; ) {
int[] succs = Opcodes.getSizeAndSuccs(addr, stream);
if (succs.length == 2
&& succs[1] == addr + succs[0])
flags[addr] |= SEQUENTIAL;
lengths[addr] = succs[0];
addr += succs[0];
for (int i=1; i<succs.length; i++)
if (succs[i] != addr)
flags[succs[i]] |= PREDECESSORS;
}
} catch (IOException ex) {
throw new ClassFormatError(ex.toString());
}
for (int i=0; i<handlers.length; i += 4) {
int start = handlers[i + 0];
int handler = handlers[i + 2];
if (start < 0) start += 65536;
if (handler < 0) handler += 65536;
flags[start] |= PREDECESSORS;
flags[handler] |= PREDECESSORS;
}
FlowBlock[] instr = new FlowBlock[code.length]; FlowBlock[] instr = new FlowBlock[code.length];
int returnCount; int returnCount;
try { try {
DataInputStream stream = DataInputStream stream =
new DataInputStream(new ByteArrayInputStream(code)); new DataInputStream(new ByteArrayInputStream(code));
/* While we read the opcodes into FlowBlocks
* we try to combine sequential blocks, as soon as we
* find two sequential instructions in a row, where the
* second has no predecessors.
*/
int mark = 1000;
FlowBlock lastBlock = null;
for (int addr = 0; addr < code.length; ) { for (int addr = 0; addr < code.length; ) {
instr[addr] = Opcodes.readOpcode(addr, stream, this); jode.flow.StructuredBlock block
= Opcodes.readOpcode(addr, stream, this);
if (jode.Decompiler.isVerbose && addr > mark) {
System.err.print('.');
mark += 1000;
}
addr = instr[addr].getNextAddr(); if (lastBlock != null && flags[addr] == SEQUENTIAL) {
lastBlock.doSequentialT1(block, lengths[addr]);
} else {
instr[addr] = new FlowBlock(this, addr,
lengths[addr], block);
lastBlock = ((flags[addr] & SEQUENTIAL) == 0)
? null : instr[addr];
}
addr += lengths[addr];
} }
} catch (IOException ex) { } catch (IOException ex) {
throw new ClassFormatError(ex.toString()); throw new ClassFormatError(ex.toString());
@ -94,28 +152,74 @@ public class CodeAnalyzer implements Analyzer {
addr = instr[addr].getNextAddr(); addr = instr[addr].getNextAddr();
} }
handler = new TransformExceptionHandlers(instr); TransformExceptionHandlers excHandlers
short[] handlers = Spy.getExceptionHandlers(bincode); = new TransformExceptionHandlers(instr);
for (int i=0; i<handlers.length; i += 4) { for (int i=0; i<handlers.length; i += 4) {
Type type = null; Type type = null;
int start = handlers[i + 0];
int end = handlers[i + 1];
int handler = handlers[i + 2];
if (start < 0) start += 65536;
if (end < 0) end += 65536;
if (handler < 0) handler += 65536;
if (handlers[i + 3 ] != 0) { if (handlers[i + 3 ] != 0) {
CpoolClass cpcls = (CpoolClass) CpoolClass cpcls = (CpoolClass)
method.classAnalyzer.getConstant(handlers[i + 3]); method.classAnalyzer.getConstant(handlers[i + 3]);
type = Type.tClass(cpcls.getName().getString()); type = Type.tClass(cpcls.getName().getString());
} }
handler.addHandler(handlers[i + 0], handlers[i + 1], excHandlers.addHandler(start, end, handler, type);
handlers[i + 2], type);
} }
if (Decompiler.isVerbose)
System.err.print('-');
excHandlers.analyze();
methodHeader = instr[0]; methodHeader = instr[0];
} methodHeader.analyze();
}
// void readCode(byte[] code, short[] handlers)
// throws ClassFormatError
// {
// FlowBlock[] instr = new FlowBlock[code.length];
// int returnCount;
// try {
// DataInputStream stream =
// new DataInputStream(new ByteArrayInputStream(code));
// for (int addr = 0; addr < code.length; ) {
// instr[addr] = Opcodes.readOpcode(addr, stream, this);
// addr = instr[addr].getNextAddr();
// }
// } catch (IOException ex) {
// throw new ClassFormatError(ex.toString());
// }
// for (int addr=0; addr<instr.length; ) {
// instr[addr].resolveJumps(instr);
// addr = instr[addr].getNextAddr();
// }
// handler = new TransformExceptionHandlers(instr);
// for (int i=0; i<handlers.length; i += 4) {
// Type type = null;
// if (handlers[i + 3 ] != 0) {
// CpoolClass cpcls = (CpoolClass)
// method.classAnalyzer.getConstant(handlers[i + 3]);
// type = Type.tClass(cpcls.getName().getString());
// }
// handler.addHandler(handlers[i + 0], handlers[i + 1],
// handlers[i + 2], type);
// }
// methodHeader = instr[0];
// }
public void analyze() public void analyze()
{ {
readCode(code); byte[] codeArray = code.getCode();
handler.analyze(); short[] handlers = Spy.getExceptionHandlers(code);
methodHeader.analyze(); readCode(codeArray, handlers);
Enumeration enum = allLocals.elements(); Enumeration enum = allLocals.elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
LocalInfo li = (LocalInfo)enum.nextElement(); LocalInfo li = (LocalInfo)enum.nextElement();
@ -157,4 +261,3 @@ public class CodeAnalyzer implements Analyzer {
return method.classAnalyzer.clazz; return method.classAnalyzer.clazz;
} }
} }

@ -132,6 +132,10 @@ public class ComplexExpression extends Expression {
return subExpressions; return subExpressions;
} }
public void setSubExpressions(int i, Expression expr) {
subExpressions[i] = expr;
updateSubTypes();
}
void updateSubTypes() { void updateSubTypes() {
for (int i=0; i < subExpressions.length; i++) { for (int i=0; i < subExpressions.length; i++) {
if (i == 0 && operator instanceof ArrayStoreOperator) { if (i == 0 && operator instanceof ArrayStoreOperator) {
@ -255,7 +259,7 @@ public class ComplexExpression extends Expression {
return new ComplexExpression return new ComplexExpression
(new StringAddOperator(), new Expression[] (new StringAddOperator(), new Expression[]
{ e, subExpressions[1] }); { e, subExpressions[1].simplifyString() });
} }
if (operator instanceof ConstructorOperator if (operator instanceof ConstructorOperator
&& (((ConstructorOperator) operator).getClassType() && (((ConstructorOperator) operator).getClassType()
@ -263,7 +267,7 @@ public class ComplexExpression extends Expression {
if (subExpressions.length == 1 && if (subExpressions.length == 1 &&
subExpressions[0].getType().isOfType(Type.tString)) subExpressions[0].getType().isOfType(Type.tString))
return subExpressions[0]; return subExpressions[0].simplifyString();
} }
return null; return null;
} }
@ -278,6 +282,7 @@ public class ComplexExpression extends Expression {
Expression simple = subExpressions[0].simplifyStringBuffer(); Expression simple = subExpressions[0].simplifyStringBuffer();
if (simple != null) if (simple != null)
return simple; return simple;
} }
else if (invoke.getMethodName().equals("valueOf") else if (invoke.getMethodName().equals("valueOf")
&& invoke.isStatic() && invoke.isStatic()
@ -309,7 +314,7 @@ public class ComplexExpression extends Expression {
{ left, right }); { left, right });
} }
} }
return null; return this;
} }
public Expression simplify() { public Expression simplify() {
@ -382,7 +387,7 @@ public class ComplexExpression extends Expression {
} }
else { else {
Expression stringExpr = simplifyString(); Expression stringExpr = simplifyString();
if (stringExpr != null) if (stringExpr != this)
return stringExpr.simplify(); return stringExpr.simplify();
} }
for (int i=0; i< subExpressions.length; i++) { for (int i=0; i< subExpressions.length; i++) {
@ -392,3 +397,4 @@ public class ComplexExpression extends Expression {
return this; return this;
} }
} }

@ -19,30 +19,56 @@
package jode; package jode;
public class ConstantArrayOperator extends SimpleOperator { public class ConstantArrayOperator extends NoArgOperator {
ConstOperator empty;
Expression[] values;
Type argType;
public ConstantArrayOperator(Type type, int size) { public ConstantArrayOperator(Type type, int size) {
super(type, 0, size); super(type);
for (int i=0; i< size; i++) values = new Expression[size];
operandTypes[i] = ((ArrayType)type).getElementType(); argType = (type instanceof ArrayType)
? Type.tSubType(((ArrayType)type).getElementType()) : Type.tError;
empty = new ConstOperator(argType, "0");
} }
public int getPriority() { public void setType(Type newtype) {
return 200; super.setType(newtype);
Type newArgType = (this.type instanceof ArrayType)
? Type.tSubType(((ArrayType)this.type).getElementType())
: Type.tError;
if (!newArgType.equals(argType)) {
argType = newArgType;
empty.setType(argType);
for (int i=0; i< values.length; i++)
if (values[i] != null)
values[i].setType(argType);
}
} }
public int getOperandPriority(int i) { public boolean setValue(int index, Expression value) {
return 0; if (index < 0 || index > values.length || values[index] != null)
return false;
value.setType(argType);
setType(Type.tSuperType(Type.tArray(value.getType())));
values[index] = value;
value.parent = this;
return true;
}
public int getPriority() {
return 200;
} }
public String toString(String[] operands) { public String toString(String[] operands) {
StringBuffer result StringBuffer result
= new StringBuffer("new "+type+" {"); = new StringBuffer("new ").append(type).append(" { ");
for (int i=0; i< getOperandCount(); i++) { for (int i=0; i< values.length; i++) {
if (i>0) if (i>0)
result.append(", "); result.append(", ");
result.append(operands[i]); result.append((values[i] != null) ? values[i] : empty);
} }
return result.append("}").toString(); return result.append(" }").toString();
} }
} }

@ -24,8 +24,9 @@ public class ConstructorOperator extends Operator {
MethodType methodType; MethodType methodType;
Type classType; Type classType;
public ConstructorOperator(Type type, MethodType methodType) { public ConstructorOperator(Type type, MethodType methodType,
super(type, 0); boolean isVoid) {
super(isVoid ? Type.tVoid : type, 0);
this.classType = type; this.classType = type;
this.methodType = methodType; this.methodType = methodType;
} }

@ -107,6 +107,9 @@ public abstract class Expression {
public Expression simplify() { public Expression simplify() {
return this; return this;
} }
public Expression simplifyString() {
return this;
}
static Expression EMPTYSTRING = new ConstOperator(Type.tString, "\"\""); static Expression EMPTYSTRING = new ConstOperator(Type.tString, "\"\"");

@ -24,14 +24,14 @@ import jode.ComplexExpression;
import jode.Type; import jode.Type;
import jode.BinaryOperator; import jode.BinaryOperator;
public class CombineIfGotoExpressions implements Transformation{ public class CombineIfGotoExpressions {
public boolean transform(FlowBlock flow) { public static boolean transform(ConditionalBlock cb,
if (!(flow.lastModified instanceof ConditionalBlock) StructuredBlock last) {
|| !(flow.lastModified.outer instanceof SequentialBlock)) if (cb.jump == null
|| !(last.outer instanceof SequentialBlock))
return false; return false;
ConditionalBlock cb = (ConditionalBlock) flow.lastModified;
SequentialBlock sequBlock = (SequentialBlock) cb.outer; SequentialBlock sequBlock = (SequentialBlock) cb.outer;
Expression[] e = new Expression[2]; Expression[] e = new Expression[2];
@ -77,6 +77,10 @@ public class CombineIfGotoExpressions implements Transformation{
} else } else
return false; return false;
/* We have changed some instructions above. We may never
* return with a failure now.
*/
sequBlock = (SequentialBlock) cb.outer; sequBlock = (SequentialBlock) cb.outer;
while (sequBlock.subBlocks[0] instanceof InstructionBlock) { while (sequBlock.subBlocks[0] instanceof InstructionBlock) {
/* Now combine the expression. Everything should /* Now combine the expression. Everything should
@ -90,14 +94,14 @@ public class CombineIfGotoExpressions implements Transformation{
sequBlock = (SequentialBlock) sequBlock.outer; sequBlock = (SequentialBlock) sequBlock.outer;
} }
flow.removeSuccessor(prevJump); cb.flowBlock.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.moveDefinitions(sequBlock, cb); cb.moveDefinitions(sequBlock, last);
cb.replace(sequBlock); last.replace(sequBlock);
return true; return true;
} }
return false; return false;

@ -24,22 +24,20 @@ import jode.LocalLoadOperator;
import jode.LocalStoreOperator; import jode.LocalStoreOperator;
import jode.Expression; import jode.Expression;
public class CompleteSynchronized implements Transformation { public class CompleteSynchronized {
/** /**
* This combines the monitorenter and the initial expression * This combines the monitorenter and the initial expression
* into a synchronized statement * into a synchronized statement
* @param flow The FlowBlock that is transformed * @param flow The FlowBlock that is transformed
*/ */
public boolean transform(FlowBlock flow) { public static boolean transform(SynchronizedBlock synBlock,
StructuredBlock last) {
if (!(flow.lastModified instanceof SynchronizedBlock) if (!(last.outer instanceof SequentialBlock))
|| flow.lastModified.outer == null)
return false; return false;
/* If the program is well formed, the following succeed */ /* If the program is well formed, the following succeed */
SynchronizedBlock synBlock = (SynchronizedBlock) flow.lastModified;
try { try {
SequentialBlock sequBlock = (SequentialBlock) synBlock.outer; SequentialBlock sequBlock = (SequentialBlock) synBlock.outer;
@ -59,11 +57,11 @@ public class CompleteSynchronized implements Transformation {
System.err.print('s'); System.err.print('s');
synBlock.isEntered = true; synBlock.isEntered = true;
synBlock.moveDefinitions(synBlock.outer,synBlock); synBlock.moveDefinitions(last.outer,last);
synBlock.replace(synBlock.outer); last.replace(last.outer);
/* Is there another expression? */ /* Is there another expression? */
if (synBlock.outer == null) if (!(last.outer instanceof SynchronizedBlock))
return false; return false;
Expression object; Expression object;
@ -85,8 +83,8 @@ public class CompleteSynchronized implements Transformation {
} }
synBlock.object = object; synBlock.object = object;
synBlock.moveDefinitions(synBlock.outer,synBlock); synBlock.moveDefinitions(last.outer,last);
synBlock.replace(synBlock.outer); last.replace(last.outer);
return true; return true;
} }
} }

@ -76,4 +76,11 @@ public class ConditionalBlock extends InstructionContainer {
trueBlock.dumpSource(writer); trueBlock.dumpSource(writer);
writer.untab(); writer.untab();
} }
public boolean doTransformations() {
StructuredBlock last = flowBlock.lastModified;
return super.doTransformations()
|| CombineIfGotoExpressions.transform(this, last)
|| CreateIfThenElseOperator.createFunny(this, last);
}
} }

@ -20,21 +20,20 @@
package jode.flow; package jode.flow;
import jode.*; import jode.*;
public class CreateAssignExpression implements Transformation{ public class CreateAssignExpression {
public boolean transform(FlowBlock flow) { public static boolean transform(InstructionContainer ic,
if (!(flow.lastModified instanceof InstructionContainer) StructuredBlock last) {
|| !(flow.lastModified.outer instanceof SequentialBlock) if (!(last.outer instanceof SequentialBlock)
|| !(((InstructionContainer)flow.lastModified).getInstruction() || !(ic.getInstruction() instanceof StoreInstruction)
instanceof StoreInstruction) || !(ic.getInstruction().isVoid()))
|| !(((InstructionContainer)flow.lastModified).getInstruction()
.isVoid()))
return false; return false;
return (createAssignOp(flow) || createAssignExpression(flow)); return (createAssignOp(ic, last) || createAssignExpression(ic, last));
} }
public boolean createAssignOp(FlowBlock flow) { public static boolean createAssignOp(InstructionContainer ic,
StructuredBlock last) {
/* Situation: /* Situation:
* *
@ -53,11 +52,8 @@ public class CreateAssignExpression implements Transformation{
* *
* If the optional dup is present the store*= becomes non void. * If the optional dup is present the store*= becomes non void.
*/ */
InstructionContainer lastBlock SequentialBlock opBlock = (SequentialBlock) last.outer;
= (InstructionContainer) flow.lastModified; StoreInstruction store = (StoreInstruction) ic.getInstruction();
SequentialBlock opBlock = (SequentialBlock) lastBlock.outer;
StoreInstruction store
= (StoreInstruction) lastBlock.getInstruction();
boolean isAssignOp = false; boolean isAssignOp = false;
if (opBlock.subBlocks[0] instanceof SpecialBlock) { if (opBlock.subBlocks[0] instanceof SpecialBlock) {
@ -93,7 +89,13 @@ public class CreateAssignExpression implements Transformation{
int opIndex; int opIndex;
Expression rightHandSide; Expression rightHandSide;
if (expr.getOperator() instanceof ConvertOperator
&& expr.getSubExpressions()[0] instanceof ComplexExpression
&& expr.getOperator().getType().isOfType(store.getLValueType())) {
expr = (ComplexExpression) expr.getSubExpressions()[0];
}
if (expr.getOperator() instanceof BinaryOperator) { if (expr.getOperator() instanceof BinaryOperator) {
BinaryOperator binop = (BinaryOperator) expr.getOperator(); BinaryOperator binop = (BinaryOperator) expr.getOperator();
@ -109,24 +111,24 @@ public class CreateAssignExpression implements Transformation{
Expression simple = expr.simplifyString(); Expression simple = expr.simplifyString();
rightHandSide = simple; rightHandSide = simple;
/* Now search for the leftmost operand ... */ /* Now search for the leftmost operand ... */
ComplexExpression last = null; ComplexExpression lastExpr = null;
while (simple instanceof ComplexExpression while (simple instanceof ComplexExpression
&& simple.getOperator() instanceof StringAddOperator) { && simple.getOperator() instanceof StringAddOperator) {
last = (ComplexExpression) simple; lastExpr = (ComplexExpression) simple;
simple = last.getSubExpressions()[0]; simple = lastExpr.getSubExpressions()[0];
} }
/* ... check it ... */ /* ... check it ... */
if (last == null || !(simple instanceof Operator) if (lastExpr == null || !(simple instanceof Operator)
|| !store.matches((Operator) simple)) || !store.matches((Operator) simple))
return false; return false;
/* ... and remove it. */ /* ... and remove it. */
if (last.getParent() != null) { if (lastExpr.getParent() != null) {
((ComplexExpression)last.getParent()).getSubExpressions()[0] ((ComplexExpression)lastExpr.getParent())
= last.getSubExpressions()[1]; .setSubExpressions(0,lastExpr.getSubExpressions()[1]);
} else } else
rightHandSide = last.getSubExpressions()[1]; rightHandSide = lastExpr.getSubExpressions()[1];
opIndex = Operator.ADD_OP; opIndex = Operator.ADD_OP;
} }
@ -137,20 +139,19 @@ public class CreateAssignExpression implements Transformation{
if (isAssignOp) if (isAssignOp)
store.makeNonVoid(); store.makeNonVoid();
lastBlock.replace(opBlock.subBlocks[1]); last.replace(opBlock.subBlocks[1]);
return true; return true;
} }
public boolean createAssignExpression(FlowBlock flow) { public static boolean createAssignExpression(InstructionContainer ic,
StructuredBlock last) {
/* Situation: /* Situation:
* sequBlock: * sequBlock:
* dup_X(lvalue_count) * dup_X(lvalue_count)
* store instruction * store instruction
*/ */
InstructionContainer lastBlock SequentialBlock sequBlock = (SequentialBlock) last.outer;
= (InstructionContainer) flow.lastModified; StoreInstruction store = (StoreInstruction) ic.getInstruction();
SequentialBlock sequBlock = (SequentialBlock) lastBlock.outer;
StoreInstruction store = (StoreInstruction) lastBlock.getInstruction();
if (sequBlock.subBlocks[0] instanceof SpecialBlock) { if (sequBlock.subBlocks[0] instanceof SpecialBlock) {

@ -26,104 +26,106 @@ import jode.ConstantArrayOperator;
import jode.ConstOperator; import jode.ConstOperator;
import jode.Type; import jode.Type;
public class CreateConstantArray implements Transformation { public class CreateConstantArray {
public boolean transform(FlowBlock flow) { public static boolean transform(InstructionContainer ic,
InstructionBlock lastBlock; StructuredBlock last) {
SequentialBlock sequBlock; /* Situation:
Expression[] consts = null; * PUSH new Array[]
int count = 0; * DUP
Type type; * PUSH index
try { * PUSH value
InstructionBlock ib = (InstructionBlock) flow.lastModified; * stack_2[stack_1] = stack_0
* ...
sequBlock = (SequentialBlock) ib.outer; */
ib = (InstructionBlock) sequBlock.subBlocks[0]; if (last.outer instanceof SequentialBlock) {
lastBlock = ib;
int lastindex = -1; SequentialBlock sequBlock = (SequentialBlock) last.outer;
while (ib.getInstruction() instanceof ArrayStoreOperator) {
ArrayStoreOperator store =
(ArrayStoreOperator) ib.getInstruction();
sequBlock = (SequentialBlock) sequBlock.outer; if (!(ic.getInstruction() instanceof ArrayStoreOperator)
ib = (InstructionBlock) sequBlock.subBlocks[0]; || !(sequBlock.subBlocks[0] instanceof InstructionBlock)
Expression lastconst = ib.getInstruction(); || !(sequBlock.outer instanceof SequentialBlock))
return false;
sequBlock = (SequentialBlock) sequBlock.outer; ArrayStoreOperator store
ib = (InstructionBlock) sequBlock.subBlocks[0]; = (ArrayStoreOperator) ic.getInstruction();
Expression indexexpr = ib.getInstruction(); InstructionBlock ib = (InstructionBlock)sequBlock.subBlocks[0];
ConstOperator indexop = sequBlock = (SequentialBlock) sequBlock.outer;
(ConstOperator) indexexpr.getOperator();
if (!indexop.getType().isOfType(Type.tUInt))
return false;
int index = Integer.parseInt(indexop.getValue());
if (index >= 0 && consts == null) {
lastindex = index;
consts = new Expression[lastindex+1];
} else if (index < 0 || index > lastindex)
return false;
else {
while (index < lastindex) {
consts[lastindex--] =
new ConstOperator(Type.tUnknown, "0");
}
}
consts[lastindex--] = lastconst;
sequBlock = (SequentialBlock) sequBlock.outer;
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)
if (dup.type != SpecialBlock.DUP || !(sequBlock.outer instanceof SequentialBlock))
|| dup.depth != 0
|| dup.count != store.getLValueType().stackSize())
return false;
count++;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
}
if (count == 0)
return false; return false;
while (lastindex >= 0)
consts[lastindex--] = new ConstOperator(Type.tUnknown, "0"); Expression expr = ib.getInstruction();
ComplexExpression newArrayExpr = ib = (InstructionBlock)sequBlock.subBlocks[0];
(ComplexExpression) ib.getInstruction(); sequBlock = (SequentialBlock) sequBlock.outer;
NewArrayOperator newArrayOp =
(NewArrayOperator) newArrayExpr.getOperator(); if (expr.getOperandCount() > 0
type = newArrayOp.getType(); || !(ib.getInstruction() instanceof ConstOperator)
if (newArrayOp.getOperandCount() != 1) || !(sequBlock.subBlocks[0] instanceof SpecialBlock)
|| !(sequBlock.outer instanceof SequentialBlock))
return false; return false;
Expression countexpr = newArrayExpr.getSubExpressions()[0];
ConstOperator countop = ConstOperator indexOp = (ConstOperator) ib.getInstruction();
(ConstOperator) countexpr.getOperator(); SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (!countop.getType().isOfType(Type.tUInt)) sequBlock = (SequentialBlock) sequBlock.outer;
if (!indexOp.getType().isOfType(Type.tUInt)
|| dup.type != SpecialBlock.DUP
|| dup.depth != 0
|| dup.count != store.getLValueType().stackSize()
|| !(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false; return false;
int arraylength = Integer.parseInt(countop.getValue());
if (arraylength != consts.length) { int index = Integer.parseInt(indexOp.getValue());
if (arraylength < consts.length) ib = (InstructionBlock)sequBlock.subBlocks[0];
if (ib.getInstruction() instanceof ComplexExpression
&& (ib.getInstruction().getOperator()
instanceof NewArrayOperator)) {
/* This is the first element */
ComplexExpression newArrayExpr =
(ComplexExpression) ib.getInstruction();
NewArrayOperator newArrayOp =
(NewArrayOperator) newArrayExpr.getOperator();
if (newArrayOp.getOperandCount() != 1
|| !(newArrayExpr.getSubExpressions()[0]
instanceof ConstOperator))
return false;
ConstOperator countop =
(ConstOperator) newArrayExpr.getSubExpressions()[0];
if (!countop.getType().isOfType(Type.tUInt))
return false;
int arraylength = Integer.parseInt(countop.getValue());
if (arraylength <= index)
return false; return false;
Expression[] newConsts = new Expression[arraylength];
System.arraycopy(consts, 0, newConsts, 0, consts.length); if (jode.Decompiler.isVerbose)
for (int i=consts.length; i<arraylength; i++) System.err.print('a');
newConsts[i] = new ConstOperator(Type.tUnknown, "0");
consts = newConsts; ConstantArrayOperator cao
= new ConstantArrayOperator(newArrayOp.getType(),
arraylength);
cao.setValue(index, expr);
ic.setInstruction(cao);
ic.moveDefinitions(sequBlock, last);
last.replace(sequBlock);
return true;
} else if (ib.getInstruction() instanceof ConstantArrayOperator) {
ConstantArrayOperator cao
= (ConstantArrayOperator) ib.getInstruction();
if (cao.setValue(index, expr)) {
/* adding Element succeeded */
ic.setInstruction(cao);
ic.moveDefinitions(sequBlock, last);
last.replace(sequBlock);
return true;
}
} }
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {
return false;
} }
if (jode.Decompiler.isVerbose) return false;
System.err.print("a");
lastBlock.setInstruction
(new ComplexExpression
(new ConstantArrayOperator(type, consts.length),
consts));
lastBlock.moveDefinitions(sequBlock.subBlocks[0], lastBlock);
lastBlock.replace(sequBlock.subBlocks[0]);
flow.lastModified.moveDefinitions(sequBlock.subBlocks[1],
flow.lastModified);
flow.lastModified.replace(sequBlock.subBlocks[1]);
return true;
} }
} }

@ -19,6 +19,7 @@
package jode.flow; package jode.flow;
import jode.Operator; import jode.Operator;
import jode.NopOperator;
import jode.Expression; import jode.Expression;
import jode.ComplexExpression; import jode.ComplexExpression;
@ -32,88 +33,103 @@ import jode.ComplexExpression;
* expr(op, [ expr_1, ..., expr_n ]) * expr(op, [ expr_1, ..., expr_n ])
* </pre> * </pre>
*/ */
public class CreateExpression implements Transformation { public class CreateExpression {
/** /**
* This does the transformation. * This does the transformation.
* @param FlowBlock the flow block to transform. * @param FlowBlock the flow block to transform.
* @return true if flow block was simplified. * @return true if flow block was simplified.
*/ */
public boolean transform(FlowBlock flow) { public static boolean transform(InstructionContainer ic,
if (!(flow.lastModified instanceof InstructionContainer) StructuredBlock last) {
|| !(flow.lastModified.outer instanceof SequentialBlock))
int params = ic.getInstruction().getOperandCount();
if (params == 0)
return false;
ComplexExpression parent = null;
Expression inner = ic.getInstruction();
while (inner instanceof ComplexExpression) {
parent = (ComplexExpression)inner;
inner = parent.getSubExpressions()[0];
}
if (!(inner instanceof Operator))
return false;
Operator op = (Operator)inner;
if (!(last.outer instanceof SequentialBlock))
return false; return false;
SequentialBlock sequBlock = (SequentialBlock)last.outer;
/* First check if Expression can be created, but do nothing yet.
*/
Expression lastExpression = null;
for (int i = params;;) {
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false;
Expression expr =
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction();
if (!expr.isVoid()) {
if (--i == 0)
break;
} else if (lastExpression == null
|| lastExpression.canCombine(expr) <= 0)
return false;
InstructionContainer ic = (InstructionContainer) flow.lastModified; if (expr.getOperandCount() > 0)
if (ic.getInstruction() instanceof Operator) { /* This is a not fully resolved expression in the
* middle, we must not touch it. */
return false;
Operator op = (Operator) ic.getInstruction(); lastExpression = expr;
int params = op.getOperandCount();
if (params == 0) if (!(sequBlock.outer instanceof SequentialBlock))
return false; return false;
sequBlock = (SequentialBlock) sequBlock.outer;
}
Expression[] exprs = new Expression[params]; /* Now, do the combination. Everything must succeed now.
*/
SequentialBlock sequBlock = (SequentialBlock) ic.outer; Expression[] exprs = new Expression[params];
sequBlock = (SequentialBlock) last.outer;
Expression lastExpression = null; for (int i=params; ;) {
/* First check if Expression can be created, but do nothing yet.
*/ Expression expr =
for (int i=params; ;) { ((InstructionBlock) sequBlock.subBlocks[0]).getInstruction();
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false; if (!expr.isVoid()) {
exprs[--i] = expr;
InstructionBlock block = if (i == 0)
(InstructionBlock) sequBlock.subBlocks[0]; break;
} else
Expression expr = block.getInstruction(); exprs[i] = exprs[i].combine(expr);
if (!expr.isVoid()) {
if (--i == 0)
break;
} else if (lastExpression != null
&& lastExpression.canCombine(expr) <= 0)
return false;
if (expr.getOperandCount() > 0)
/* This is a not fully resolved expression in the
* middle, we must not touch it. */
return false;
lastExpression = expr;
if (!(sequBlock.outer instanceof SequentialBlock))
return false;
sequBlock = (SequentialBlock)sequBlock.outer;
}
/* Now, do the combination. Everything must succeed now.
*/
sequBlock = (SequentialBlock) ic.outer;
for (int i=params; ;) {
InstructionBlock block =
(InstructionBlock) sequBlock.subBlocks[0];
Expression expr = block.getInstruction();
if (!expr.isVoid()) {
exprs[--i] = expr;
if (i == 0)
break;
} else
exprs[i] = exprs[i].combine(expr);
sequBlock = (SequentialBlock)sequBlock.outer;
}
if(jode.Decompiler.isVerbose)
System.err.print('x');
ic.setInstruction(new ComplexExpression(op, exprs)); sequBlock = (SequentialBlock)sequBlock.outer;
ic.moveDefinitions(sequBlock, ic);
ic.replace(sequBlock);
return true;
} }
return false;
if(jode.Decompiler.isVerbose)
System.err.print('x');
Expression newExpr;
if (params == 1 && op instanceof NopOperator) {
exprs[0].setType(op.getType());
newExpr = exprs[0];
} else
newExpr = new ComplexExpression(op, exprs);
if (parent != null)
parent.setSubExpressions(0, newExpr);
else
ic.setInstruction(newExpr);
ic.moveDefinitions(sequBlock, last);
last.replace(sequBlock);
return true;
} }
} }

@ -21,23 +21,19 @@ package jode.flow;
import jode.Expression; import jode.Expression;
import jode.StoreInstruction; import jode.StoreInstruction;
public class CreateForInitializer implements Transformation { public class CreateForInitializer {
/** /**
* This combines an variable initializer into a for statement * This combines an variable initializer into a for statement
* @param flow The FlowBlock that is transformed * @param forBlock the for block
* @param last the lastModified of the flow block.
*/ */
public boolean transform(FlowBlock flow) { public static boolean transform(LoopBlock forBlock, StructuredBlock last) {
if (!(flow.lastModified instanceof LoopBlock) if (!(last.outer instanceof SequentialBlock))
|| !(flow.lastModified.outer instanceof SequentialBlock))
return false; return false;
LoopBlock forBlock = (LoopBlock) flow.lastModified; SequentialBlock sequBlock = (SequentialBlock) last.outer;
if (forBlock.type != forBlock.FOR || forBlock.init != null)
return false;
SequentialBlock sequBlock = (SequentialBlock) forBlock.outer;
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false; return false;
@ -53,8 +49,8 @@ public class CreateForInitializer implements Transformation {
System.err.print('f'); System.err.print('f');
forBlock.init = initializer; forBlock.init = initializer;
forBlock.moveDefinitions(forBlock.outer, forBlock); forBlock.moveDefinitions(last.outer, null);
forBlock.replace(forBlock.outer); last.replace(last.outer);
return true; return true;
} }
} }

@ -20,24 +20,109 @@
package jode.flow; package jode.flow;
import jode.Type; import jode.Type;
import jode.Expression; import jode.Expression;
import jode.ConstOperator;
import jode.ComplexExpression; import jode.ComplexExpression;
import jode.IfThenElseOperator; import jode.IfThenElseOperator;
import jode.CompareUnaryOperator; import jode.CompareUnaryOperator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Vector; import java.util.Vector;
public class CreateIfThenElseOperator implements Transformation { public class CreateIfThenElseOperator {
/**
* This handles the body of createFunny. There are three cases:
*
* <pre>
* --------
* IF (c2)
* GOTO trueDest -> PUSH c2
* PUSH false
* --------
* PUSH bool -> PUSH bool
* --------
* if (c2)
* (handled recursively) -> PUSH (c2 ? expr1 : expr2)
* else
* (handled recursively)
* --------
* </pre>
*/
private static boolean createFunnyHelper(FlowBlock trueDest,
FlowBlock falseDest,
StructuredBlock block) {
if (block instanceof InstructionBlock
&& !((InstructionBlock)block).getInstruction().isVoid())
return true;
if (block instanceof IfThenElseBlock) {
IfThenElseBlock ifBlock = (IfThenElseBlock) block;
Expression expr1, expr2;
if (ifBlock.elseBlock == null)
return false;
if (!createFunnyHelper(trueDest, falseDest, ifBlock.thenBlock)
| !createFunnyHelper(trueDest, falseDest, ifBlock.elseBlock))
return false;
if (jode.Decompiler.isVerbose)
System.err.print('?');
IfThenElseOperator iteo = new IfThenElseOperator(Type.tBoolean);
((InstructionBlock)ifBlock.thenBlock).setInstruction
(new ComplexExpression
(iteo, new Expression[] {
ifBlock.cond,
((InstructionBlock) ifBlock.thenBlock).getInstruction(),
((InstructionBlock) ifBlock.elseBlock).getInstruction()
}));
ifBlock.thenBlock.moveDefinitions(ifBlock, null);
ifBlock.thenBlock.replace(ifBlock);
return true;
}
if (block instanceof SequentialBlock
&& block.getSubBlocks()[0] instanceof ConditionalBlock
&& block.getSubBlocks()[1] instanceof InstructionBlock) {
ConditionalBlock condBlock =
(ConditionalBlock) block.getSubBlocks()[0];
InstructionBlock pushBlock =
(InstructionBlock) block.getSubBlocks()[1];
if (!(pushBlock.getInstruction() instanceof ConstOperator))
return false;
ConstOperator constOp =
(ConstOperator) pushBlock.getInstruction();
if (condBlock.trueBlock.jump.destination == trueDest
&& constOp.getValue().equals("0")) {
Expression cond = condBlock.getInstruction();
condBlock.flowBlock.removeSuccessor(condBlock.trueBlock.jump);
condBlock.trueBlock.removeJump();
pushBlock.setInstruction(cond);
pushBlock.moveDefinitions(block, null);
pushBlock.replace(block);
return true;
}
}
return false;
}
/** /**
* This handles the more complicated form of the ?-:-operator used * This handles the more complicated form of the ?-:-operator used
* in a conditional block. The simplest case is: * in a conditional block. The simplest case is:
* <pre> * <pre>
* if (cond) * if (cond)
* push e1 * PUSH e1
* else { * else {
* IF (c2) * IF (c2)
* GOTO flow_2_ * GOTO flow_2_
* push 0 * PUSH false
* } * }
* -&gt;IF (stack_0 == 0) * -&gt;IF (stack_0 == 0)
* GOTO flow_1_ * GOTO flow_1_
@ -60,104 +145,35 @@ public class CreateIfThenElseOperator implements Transformation {
* sometimes be better replaced with a correct jump. * sometimes be better replaced with a correct jump.
* @param flow The FlowBlock that is transformed * @param flow The FlowBlock that is transformed
*/ */
public boolean createFunny(FlowBlock flow) { public static boolean createFunny(ConditionalBlock cb,
StructuredBlock last) {
if (!(flow.lastModified instanceof ConditionalBlock)) if (cb.jump == null
return false; || !(cb.getInstruction() instanceof CompareUnaryOperator)
|| !(last.outer instanceof SequentialBlock)
ConditionalBlock conditional = (ConditionalBlock) flow.lastModified; || !(last.outer.getSubBlocks()[0] instanceof IfThenElseBlock))
if (!(conditional.trueBlock instanceof EmptyBlock)
|| conditional.trueBlock.jump == null
|| conditional.jump == null
|| !(conditional.getInstruction() instanceof CompareUnaryOperator))
return false; return false;
CompareUnaryOperator compare = CompareUnaryOperator compare =
(CompareUnaryOperator) conditional.getInstruction(); (CompareUnaryOperator) cb.getInstruction();
FlowBlock trueDestination; FlowBlock trueDestination;
if (compare.getOperatorIndex() == compare.EQUALS_OP) FlowBlock falseDestination;
trueDestination = conditional.jump.destination; if (compare.getOperatorIndex() == compare.EQUALS_OP) {
else if (compare.getOperatorIndex() == compare.NOTEQUALS_OP) trueDestination = cb.jump.destination;
trueDestination = conditional.trueBlock.jump.destination; falseDestination = cb.trueBlock.jump.destination;
else } else if (compare.getOperatorIndex() == compare.NOTEQUALS_OP) {
falseDestination = cb.jump.destination;
trueDestination = cb.trueBlock.jump.destination;
} else
return false; return false;
Expression[] e = new Expression[3]; Expression[] e = new Expression[3];
IfThenElseBlock ifBlock; IfThenElseBlock ifBlock;
try {
SequentialBlock sequBlock =
(SequentialBlock) conditional.outer;
ifBlock = (IfThenElseBlock) sequBlock.subBlocks[0];
while (true) {
if (ifBlock.thenBlock instanceof IfThenElseBlock)
ifBlock = (IfThenElseBlock) ifBlock.thenBlock;
else if (ifBlock.elseBlock instanceof IfThenElseBlock)
ifBlock = (IfThenElseBlock) ifBlock.elseBlock;
else
break;
}
e[0] = ifBlock.cond;
StructuredBlock[] subBlocks = ifBlock.getSubBlocks();
if (subBlocks.length != 2)
return false;
for (int i=0; i< 2; i++) {
if (subBlocks[i] instanceof InstructionBlock) {
e[i+1] = ((InstructionBlock)subBlocks[i]).getInstruction();
continue;
}
sequBlock = (SequentialBlock) subBlocks[i];
ConditionalBlock condBlock =
(ConditionalBlock) sequBlock.subBlocks[0];
InstructionBlock pushBlock =
(InstructionBlock) sequBlock.subBlocks[1];
jode.ConstOperator zero =
(jode.ConstOperator) pushBlock.getInstruction();
if (!zero.getValue().equals("0"))
return false;
if (!(condBlock.trueBlock instanceof EmptyBlock)
|| condBlock.trueBlock.jump == null
|| condBlock.jump != null
|| condBlock.trueBlock.jump.destination
!= trueDestination)
return false;
Expression cond = condBlock.getInstruction();
flow.removeSuccessor(condBlock.trueBlock.jump);
condBlock.trueBlock.removeJump();
pushBlock.setInstruction(cond);
pushBlock.moveDefinitions(sequBlock, pushBlock);
pushBlock.replace(sequBlock);
e[i+1] = cond;
}
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
if (jode.Decompiler.isVerbose)
System.err.print('?');
IfThenElseOperator iteo = new IfThenElseOperator SequentialBlock sequBlock = (SequentialBlock) last.outer;
(Type.tSuperType(e[1].getType()) return createFunnyHelper(trueDestination, falseDestination,
.intersection(Type.tSuperType(e[2].getType()))); sequBlock.subBlocks[0]);
((InstructionBlock)ifBlock.thenBlock).
setInstruction(new ComplexExpression(iteo, e));
ifBlock.thenBlock.moveDefinitions(ifBlock, ifBlock.thenBlock);
ifBlock.thenBlock.replace(ifBlock);
return true;
} }
/** /**
@ -176,57 +192,47 @@ public class CreateIfThenElseOperator implements Transformation {
* The <code>-&gt;</code> points to the lastModified block. * The <code>-&gt;</code> points to the lastModified block.
* @param flow The FlowBlock that is transformed * @param flow The FlowBlock that is transformed
*/ */
public boolean create(FlowBlock flow) { public static boolean create(InstructionContainer ic,
StructuredBlock last) {
Expression e[] = new Expression[3]; Expression e[] = new Expression[3];
InstructionBlock thenBlock; InstructionBlock thenBlock;
try { if (ic.jump == null
InstructionBlock elseBlock = (InstructionBlock) flow.lastModified; || !(last.outer instanceof SequentialBlock))
SequentialBlock sequBlock = (SequentialBlock)elseBlock.outer;
if (sequBlock.subBlocks[1] != elseBlock)
return false;
IfThenElseBlock ifBlock = (IfThenElseBlock)sequBlock.subBlocks[0];
if (ifBlock.elseBlock != null)
return false;
thenBlock = (InstructionBlock) ifBlock.thenBlock;
if (thenBlock.jump.destination != elseBlock.jump.destination)
return false;
e[1] = thenBlock.getInstruction();
if (e[1].isVoid())
return false;
e[2] = elseBlock.getInstruction();
if (e[2].isVoid())
return false;
e[0] = ifBlock.cond;
} catch (ClassCastException ex) {
return false; return false;
} catch (NullPointerException ex) { SequentialBlock sequBlock = (SequentialBlock)last.outer;
if (!(sequBlock.subBlocks[0] instanceof IfThenElseBlock))
return false; return false;
}
IfThenElseBlock ifBlock = (IfThenElseBlock)sequBlock.subBlocks[0];
if (!(ifBlock.thenBlock instanceof InstructionBlock)
|| ifBlock.thenBlock.jump == null
|| ifBlock.thenBlock.jump.destination != ic.jump.destination
|| ifBlock.elseBlock != null)
return false;
thenBlock = (InstructionBlock) ifBlock.thenBlock;
e[1] = thenBlock.getInstruction();
if (e[1].isVoid())
return false;
e[2] = ic.getInstruction();
if (e[2].isVoid())
return false;
e[0] = ifBlock.cond;
if (jode.Decompiler.isVerbose) if (jode.Decompiler.isVerbose)
System.err.print('?'); System.err.print('?');
flow.removeSuccessor(thenBlock.jump); thenBlock.flowBlock.removeSuccessor(thenBlock.jump);
thenBlock.removeJump(); thenBlock.removeJump();
IfThenElseOperator iteo = new IfThenElseOperator IfThenElseOperator iteo = new IfThenElseOperator
(Type.tSuperType(e[1].getType()) (Type.tSuperType(e[1].getType())
.intersection(Type.tSuperType(e[2].getType()))); .intersection(Type.tSuperType(e[2].getType())));
((InstructionBlock)flow.lastModified). ic.setInstruction(new ComplexExpression(iteo, e));
setInstruction(new ComplexExpression(iteo, e)); ic.moveDefinitions(last.outer, last);
flow.lastModified.moveDefinitions(flow.lastModified.outer, null); last.replace(last.outer);
flow.lastModified.replace(flow.lastModified.outer);
return true; return true;
} }
public boolean transform(FlowBlock flow) {
return createFunny(flow) || create(flow);
}
} }

@ -24,13 +24,14 @@ import jode.ComplexExpression;
import jode.ConstructorOperator; import jode.ConstructorOperator;
import jode.NewOperator; import jode.NewOperator;
public class CreateNewConstructor implements Transformation{ public class CreateNewConstructor {
public boolean transform(FlowBlock flow) { public static boolean transform(InstructionContainer ic,
StructuredBlock last) {
/* Situation: /* Situation:
* *
* new <object> * new <object>
* DUP * (optional DUP)
* PUSH load_ops * PUSH load_ops
* optionally: <= used for "string1 += string2" * optionally: <= used for "string1 += string2"
* DUP_X2 * DUP_X2
@ -43,23 +44,21 @@ public class CreateNewConstructor implements Transformation{
* optionally: * optionally:
* DUP_X1 <= remove the depth * DUP_X1 <= remove the depth
* [ n non void + some void expressions ] * [ n non void + some void expressions ]
* PUSH new <object>(stack_n-1,...,stack_0) * (optional PUSH) new <object>(stack_n-1,...,stack_0)
*/ */
if (!(flow.lastModified instanceof InstructionBlock) if (!(last.outer instanceof SequentialBlock))
|| !(flow.lastModified.outer instanceof SequentialBlock))
return false; return false;
InstructionBlock block = (InstructionBlock) flow.lastModified; if (!(ic.getInstruction() instanceof InvokeOperator))
if (!(block.getInstruction() instanceof InvokeOperator))
return false; return false;
InvokeOperator constrCall = (InvokeOperator) block.getInstruction(); InvokeOperator constrCall = (InvokeOperator) ic.getInstruction();
if (!constrCall.isConstructor()) if (!constrCall.isConstructor())
return false; return false;
/* The rest should probably succeed */ /* The rest should probably succeed */
int params = constrCall.getOperandCount() - 1; int params = constrCall.getOperandCount() - 1;
SpecialBlock optDup = null; SpecialBlock optDupX2 = null;
SequentialBlock sequBlock = (SequentialBlock) block.outer; SequentialBlock sequBlock = (SequentialBlock) last.outer;
while (params > 0) { while (params > 0) {
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false; return false;
@ -74,11 +73,11 @@ public class CreateNewConstructor implements Transformation{
instanceof SpecialBlock) { instanceof SpecialBlock) {
/* handle the optional dup */ /* handle the optional dup */
sequBlock = (SequentialBlock) sequBlock.outer; sequBlock = (SequentialBlock) sequBlock.outer;
optDup = (SpecialBlock) sequBlock.subBlocks[0]; optDupX2 = (SpecialBlock) sequBlock.subBlocks[0];
if (optDup.type != SpecialBlock.DUP if (optDupX2.type != SpecialBlock.DUP
|| optDup.depth != 2) || optDupX2.depth != 2)
return false; return false;
params = optDup.count; params = optDupX2.count;
} else } else
return false; return false;
} }
@ -93,34 +92,36 @@ public class CreateNewConstructor implements Transformation{
&& sequBlock.outer instanceof SequentialBlock) && sequBlock.outer instanceof SequentialBlock)
sequBlock = (SequentialBlock) sequBlock.outer; sequBlock = (SequentialBlock) sequBlock.outer;
SpecialBlock dup = null;
if (sequBlock.outer instanceof SequentialBlock if (sequBlock.outer instanceof SequentialBlock
&& sequBlock.subBlocks[0] instanceof SpecialBlock) { && sequBlock.subBlocks[0] instanceof SpecialBlock) {
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP if (dup.type != SpecialBlock.DUP
|| dup.count != 1 || dup.depth != 0) || dup.count != 1 || dup.depth != 0)
return false; return false;
sequBlock = (SequentialBlock)sequBlock.outer; sequBlock = (SequentialBlock)sequBlock.outer;
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) }
return false;
block = (InstructionBlock) sequBlock.subBlocks[0];
if (!(block.getInstruction() instanceof NewOperator))
return false;
NewOperator op = (NewOperator) block.getInstruction();
if (constrCall.getClassType() != op.getType())
return false;
block.removeBlock(); if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
return false;
InstructionBlock block = (InstructionBlock) sequBlock.subBlocks[0];
if (!(block.getInstruction() instanceof NewOperator))
return false;
NewOperator op = (NewOperator) block.getInstruction();
if (constrCall.getClassType() != op.getType())
return false;
block.removeBlock();
if (dup != null)
dup.removeBlock(); dup.removeBlock();
if (optDup != null) if (optDupX2 != null)
optDup.depth = 0; optDupX2.depth = 0;
((InstructionContainer) flow.lastModified).setInstruction ic.setInstruction(new ConstructorOperator(constrCall.getClassType(),
(new ConstructorOperator(constrCall.getClassType(), constrCall.getMethodType(),
constrCall.getMethodType())); dup == null));
return true; return true;
}
return false;
} }
} }

@ -20,30 +20,28 @@
package jode.flow; package jode.flow;
import jode.*; import jode.*;
public class CreatePrePostIncExpression implements Transformation { public class CreatePrePostIncExpression {
public boolean transform(FlowBlock flow) public static boolean transform(InstructionContainer ic,
StructuredBlock last)
{ {
return (createLocalPrePostInc(flow) || createPostInc(flow)); return (createLocalPrePostInc(ic, last) || createPostInc(ic, last));
} }
public boolean createLocalPrePostInc(FlowBlock flow) { public static boolean createLocalPrePostInc(InstructionContainer ic,
IIncOperator iinc; StructuredBlock last) {
boolean isPost;
int op; if (last.outer instanceof SequentialBlock
InstructionContainer lastBlock; && last.outer.getSubBlocks()[0] instanceof InstructionBlock) {
Type type;
try {
lastBlock = (InstructionContainer) flow.lastModified;
Expression instr2 = lastBlock.getInstruction();
SequentialBlock sequBlock = (SequentialBlock)lastBlock.outer;
if (sequBlock.subBlocks[1] != lastBlock)
return false;
InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
Expression instr1 = ib.getInstruction();
Expression instr1 = ((InstructionBlock)
last.outer.getSubBlocks()[0])
.getInstruction();
Expression instr2 = ic.getInstruction();
IIncOperator iinc;
LocalLoadOperator load; LocalLoadOperator load;
boolean isPost;
if (instr1 instanceof IIncOperator if (instr1 instanceof IIncOperator
&& instr2 instanceof LocalLoadOperator) { && instr2 instanceof LocalLoadOperator) {
iinc = (IIncOperator) instr1; iinc = (IIncOperator) instr1;
@ -57,6 +55,7 @@ public class CreatePrePostIncExpression implements Transformation {
} else } else
return false; return false;
int op;
if (iinc.getOperatorIndex() == iinc.ADD_OP + iinc.OPASSIGN_OP) if (iinc.getOperatorIndex() == iinc.ADD_OP + iinc.OPASSIGN_OP)
op = Operator.INC_OP; op = Operator.INC_OP;
else if (iinc.getOperatorIndex() == iinc.NEG_OP + iinc.OPASSIGN_OP) else if (iinc.getOperatorIndex() == iinc.NEG_OP + iinc.OPASSIGN_OP)
@ -72,94 +71,124 @@ public class CreatePrePostIncExpression implements Transformation {
if (!iinc.matches(load)) if (!iinc.matches(load))
return false; return false;
type = load.getType().intersection(Type.tUInt); Type type = load.getType().intersection(Type.tUInt);
} catch (NullPointerException ex) { Operator ppop =
return false; new LocalPrePostFixOperator(type, op, iinc, isPost);
} catch (ClassCastException ex) {
return false; ic.setInstruction(ppop);
ic.moveDefinitions(last.outer, last);
last.replace(last.outer);
return true;
} }
Operator ppop = new LocalPrePostFixOperator(type, op, iinc, isPost); return false;
lastBlock.setInstruction(ppop);
lastBlock.moveDefinitions(lastBlock.outer, lastBlock);
lastBlock.replace(lastBlock.outer);
return true;
} }
public boolean createPostInc(FlowBlock flow) { public static boolean createPostInc(InstructionContainer ic,
StoreInstruction store; StructuredBlock last) {
int op;
Type type; /* Situation:
InstructionBlock lastBlock; *
SequentialBlock sequBlock; * PUSH load/storeOps PUSH load/storeOps
try { * DUP load/storeOps PUSH store++/--
lastBlock = (InstructionBlock) flow.lastModified; * load (unresolved)
* DUP ->
Expression storeExpr = lastBlock.getInstruction(); * PUSH +/-1
store = (StoreInstruction) storeExpr.getOperator(); * IADD/SUB
if (!store.isVoid()) * store (unresolved)
return false; *
* load (no params) -> PUSH store++/--
* DUP
* PUSH +/-1
* store IADD/SUB
*/
if (!(ic.getInstruction().getOperator() instanceof StoreInstruction)
|| !(ic.getInstruction().isVoid()))
return false;
StoreInstruction store =
(StoreInstruction) ic.getInstruction().getOperator();
sequBlock = (SequentialBlock) lastBlock.outer;
if (sequBlock.subBlocks[1] != lastBlock)
return false;
BinaryOperator binOp; if (!(last.outer instanceof SequentialBlock))
InstructionBlock ib; return false;
if (store.getLValueOperandCount() > 0) { SequentialBlock sb = (SequentialBlock)last.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
binOp = (BinaryOperator) ib.getInstruction();
sequBlock = (SequentialBlock) sequBlock.outer;
} else
binOp = (BinaryOperator)
((ComplexExpression) storeExpr).getSubExpressions()[0];
if (binOp.getOperatorIndex() == store.ADD_OP) Expression binOp;
op = Operator.INC_OP; if (store.getLValueOperandCount() == 0) {
else if (store.getOperatorIndex() == store.NEG_OP) if (!(ic.getInstruction() instanceof ComplexExpression))
op = Operator.DEC_OP;
else
return false; return false;
binOp = ((ComplexExpression) ic.getInstruction())
ib = (InstructionBlock) sequBlock.subBlocks[0]; .getSubExpressions()[0];
} else {
ConstOperator constOp = (ConstOperator) ib.getInstruction(); if (!(sb.subBlocks[0] instanceof InstructionBlock)
if (!constOp.getValue().equals("1") && || !(sb.outer instanceof SequentialBlock))
!constOp.getValue().equals("-1"))
return false;
if (constOp.getValue().equals("-1"))
op ^= 1;
sequBlock = (SequentialBlock) sequBlock.outer;
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.count != store.getLValueType().stackSize()
|| dup.depth != store.getLValueOperandCount())
return false; return false;
binOp = ((InstructionBlock) sb.subBlocks[0])
.getInstruction();
sb = (SequentialBlock) sb.outer;
}
if (!(binOp instanceof BinaryOperator))
return false;
int op;
if (binOp.getOperator().getOperatorIndex() == store.ADD_OP)
op = Operator.INC_OP;
else if (binOp.getOperator().getOperatorIndex() == store.NEG_OP)
op = Operator.DEC_OP;
else
return false;
if (!(sb.subBlocks[0] instanceof InstructionBlock))
return false;
InstructionBlock ib = (InstructionBlock) sb.subBlocks[0];
if (!(ib.getInstruction() instanceof ConstOperator))
return false;
ConstOperator constOp = (ConstOperator) ib.getInstruction();
if (constOp.getValue().equals("-1"))
op ^= 1;
else if (!constOp.getValue().equals("1"))
return false;
sequBlock = (SequentialBlock) sequBlock.outer; if (!(sb.outer instanceof SequentialBlock))
ib = (InstructionBlock) sequBlock.subBlocks[0]; return false;
Operator load = (Operator) ib.getInstruction(); sb = (SequentialBlock) sb.outer;
if (!store.matches(load)) if (!(sb.subBlocks[0] instanceof SpecialBlock))
return false; return false;
SpecialBlock dup = (SpecialBlock) sb.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.count != store.getLValueType().stackSize()
|| dup.depth != store.getLValueOperandCount())
return false;
if (store.getLValueOperandCount() > 0) { if (!(sb.outer instanceof SequentialBlock))
sequBlock = (SequentialBlock) sequBlock.outer;
SpecialBlock dup2 = (SpecialBlock) sequBlock.subBlocks[0];
if (dup2.type != SpecialBlock.DUP
|| dup2.count != store.getLValueOperandCount()
|| dup2.depth != 0)
return false;
}
type = load.getType().intersection(store.getLValueType());
} catch (NullPointerException ex) {
return false; return false;
} catch (ClassCastException ex) { sb = (SequentialBlock) sb.outer;
if (!(sb.subBlocks[0] instanceof InstructionBlock))
return false;
ib = (InstructionBlock) sb.subBlocks[0];
if (!(ib.getInstruction() instanceof Operator)
|| !store.matches((Operator) ib.getInstruction()))
return false; return false;
if (store.getLValueOperandCount() > 0) {
if (!(sb.outer instanceof SequentialBlock))
return false;
sb = (SequentialBlock) sb.outer;
if (!(sb.subBlocks[0] instanceof SpecialBlock))
return false;
SpecialBlock dup2 = (SpecialBlock) sb.subBlocks[0];
if (dup2.type != SpecialBlock.DUP
|| dup2.count != store.getLValueOperandCount()
|| dup2.depth != 0)
return false;
} }
Operator postop = new PrePostFixOperator(type, op, store, true); ic.setInstruction
lastBlock.setInstruction(postop); (new PrePostFixOperator(store.getLValueType(), op, store, true));
lastBlock.moveDefinitions(sequBlock, lastBlock); ic.moveDefinitions(sb, last);
lastBlock.replace(sequBlock); last.replace(sb);
return true; return true;
} }
} }

@ -199,73 +199,69 @@ public class FlowBlock {
ConditionalBlock cb = (ConditionalBlock) jump.prev.outer; ConditionalBlock cb = (ConditionalBlock) jump.prev.outer;
Expression instr = cb.getInstruction(); Expression instr = cb.getInstruction();
/* If this is the first instruction of a while and the // if (cb.outer instanceof LoopBlock
* condition of the while is true, use the condition // || (cb.outer instanceof SequentialBlock
* as while condition. // && cb.outer.getSubBlocks()[0] == cb
*/ // && cb.outer.outer instanceof LoopBlock)) {
if (cb.outer instanceof LoopBlock
|| (cb.outer instanceof SequentialBlock // LoopBlock loopBlock = (cb.outer instanceof LoopBlock) ?
&& cb.outer.getSubBlocks()[0] == cb // (LoopBlock) cb.outer : (LoopBlock) cb.outer.outer;
&& cb.outer.outer instanceof LoopBlock)) {
LoopBlock loopBlock = (cb.outer instanceof LoopBlock) ?
(LoopBlock) cb.outer : (LoopBlock) cb.outer.outer;
if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() != LoopBlock.DOWHILE &&
(loopBlock.jumpMayBeChanged()
|| loopBlock.getNextFlowBlock() == succ)) {
if (loopBlock.jump == null) {
/* consider this jump again */
loopBlock.moveJump(jump);
jumps = jump;
} else
jump.prev.removeJump();
loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null);
cb.removeBlock();
continue;
}
} else if (cb.outer instanceof SequentialBlock
&& cb.outer.getSubBlocks()[1] == cb) {
/* And now for do/while loops, where the jump is // if (loopBlock.getCondition() == LoopBlock.TRUE &&
* at the end of the loop. // loopBlock.getType() != LoopBlock.DOWHILE &&
*/ // (loopBlock.jumpMayBeChanged()
// || loopBlock.getNextFlowBlock() == succ)) {
// if (loopBlock.jump == null) {
// /* consider this jump again */
// loopBlock.moveJump(jump);
// jumps = jump;
// } else
// jump.prev.removeJump();
// loopBlock.setCondition(instr.negate());
// loopBlock.moveDefinitions(cb, null);
// cb.removeBlock();
// continue;
// }
// } else if (cb.outer instanceof SequentialBlock
// && cb.outer.getSubBlocks()[1] == cb) {
// /* And now for do/while loops, where the jump is
// * at the end of the loop.
// */
/* First find the beginning of the loop */ // /* First find the beginning of the loop */
StructuredBlock sb = cb.outer.outer; // StructuredBlock sb = cb.outer.outer;
while (sb 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 instanceof LoopBlock) { // if (sb instanceof LoopBlock) {
LoopBlock loopBlock = (LoopBlock) sb; // LoopBlock loopBlock = (LoopBlock) sb;
if (loopBlock.getCondition() == LoopBlock.TRUE && // if (loopBlock.getCondition() == LoopBlock.TRUE &&
loopBlock.getType() == LoopBlock.WHILE && // loopBlock.getType() == LoopBlock.WHILE &&
(loopBlock.jumpMayBeChanged() // (loopBlock.jumpMayBeChanged()
|| loopBlock.getNextFlowBlock() == succ)) { // || loopBlock.getNextFlowBlock() == succ)) {
if (loopBlock.jump == null) { // if (loopBlock.jump == null) {
/* consider this jump again */ // /* consider this jump again */
loopBlock.moveJump(jump); // loopBlock.moveJump(jump);
jumps = jump; // jumps = jump;
} else // } else
jump.prev.removeJump(); // jump.prev.removeJump();
loopBlock.setType(LoopBlock.DOWHILE); // loopBlock.setType(LoopBlock.DOWHILE);
loopBlock.setCondition(instr.negate()); // loopBlock.setCondition(instr.negate());
loopBlock.moveDefinitions(cb, null); // loopBlock.moveDefinitions(cb, null);
cb.removeBlock(); // cb.removeBlock();
continue; // continue;
} // }
} // }
} // }
/* replace all conditional jumps to the successor, which /* replace all conditional jumps to the successor, which
* are followed by a block which has the end of the block * are followed by a block which has the end of the block
@ -599,6 +595,30 @@ public class FlowBlock {
} }
} }
/**
* This is a special T1 transformation, that does also succeed, if
* the jumps in the flow block are not yet resolved. But it has
* a special precondition: The succ must be a simple instruction block,
* mustn't have another predecessor and all structured blocks in this
* flow block must be simple instruction blocks.
*/
public void doSequentialT1(StructuredBlock succ, int length) {
VariableSet succIn = new VariableSet();
succ.fillInGenSet(succIn, this.gen);
succIn.merge(lastModified.jump.gen);
succIn.subtract(lastModified.jump.kill);
succ.jump.gen.mergeGenKill(lastModified.jump.gen, succ.jump.kill);
succ.jump.kill.add(lastModified.jump.kill);
this.in.unionExact(succIn);
lastModified.removeJump();
lastModified = lastModified.appendBlock(succ);
this.length += length;
doTransformations();
}
/** /**
* Do a T1 transformation with succ if possible. It is possible, * Do a T1 transformation with succ if possible. It is possible,
* iff succ has exactly this block as predecessor. * iff succ has exactly this block as predecessor.
@ -619,19 +639,25 @@ public class FlowBlock {
/* Update the in/out-Vectors now */ /* Update the in/out-Vectors now */
updateInOut(succ, jumps); updateInOut(succ, jumps);
if (Decompiler.isFlowDebugging)
System.err.println("before Optimize: "+this);
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
jumps = optimizeJumps(jumps, succ); jumps = optimizeJumps(jumps, succ);
if (Decompiler.isFlowDebugging)
System.err.println("before Remaining: "+this);
resolveRemaining(jumps); resolveRemaining(jumps);
if (Decompiler.isFlowDebugging)
System.err.println("after Optimize: "+this);
/* Now unify the blocks. /* Now unify the blocks.
*/ */
lastModified.appendBlock(succ.block); lastModified = lastModified.appendBlock(succ.block);
mergeSuccessors(succ); mergeSuccessors(succ);
/* Set last modified to the new correct value. */ /* This will also set last modified to the new correct value. */
lastModified = succ.lastModified; doTransformations();
/* Set addr+length to correct value. */ /* Set addr+length to correct value. */
if (succ.addr < addr) if (succ.addr < addr)
@ -643,6 +669,44 @@ public class FlowBlock {
return true; return true;
} }
/**
* Find the exit condition of a for/while block. The loop block
* mustn't have an exit condition yet.
*/
public void mergeCondition() {
/* If the first instruction of a while is a conditional
* block, which jumps to the next address use the condition
* as while condition.
*/
LoopBlock loopBlock = (LoopBlock) lastModified;
int loopType = loopBlock.getType();
ConditionalBlock cb = null;
if (loopBlock.bodyBlock instanceof ConditionalBlock)
cb = (ConditionalBlock) loopBlock.bodyBlock;
else if (loopBlock.bodyBlock instanceof SequentialBlock
&& loopBlock.bodyBlock.getSubBlocks()[0]
instanceof ConditionalBlock)
cb = (ConditionalBlock) loopBlock.bodyBlock.getSubBlocks()[0];
else if (loopBlock.bodyBlock instanceof SequentialBlock
&& loopType == LoopBlock.WHILE) {
loopType = LoopBlock.DOWHILE;
SequentialBlock sequBlock = (SequentialBlock) loopBlock.bodyBlock;
while (sequBlock.subBlocks[1] instanceof SequentialBlock)
sequBlock = (SequentialBlock) sequBlock.subBlocks[1];
if (sequBlock.subBlocks[1] instanceof ConditionalBlock)
cb = (ConditionalBlock) sequBlock.subBlocks[1];
}
if (cb != null
&& cb.trueBlock.jump.destination.addr == addr + length) {
loopBlock.moveJump(cb.trueBlock.jump);
loopBlock.setCondition(cb.getInstruction().negate());
loopBlock.setType(loopType);
loopBlock.moveDefinitions(cb, null);
cb.removeBlock();
}
}
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
@ -800,6 +864,7 @@ public class FlowBlock {
*/ */
predecessors.removeElement(this); predecessors.removeElement(this);
lastModified = block; lastModified = block;
mergeCondition();
/* T2 analysis succeeded */ /* T2 analysis succeeded */
checkConsistent(); checkConsistent();
@ -881,20 +946,20 @@ public class FlowBlock {
checkConsistent(); checkConsistent();
} }
public void doTransformations() {
if (Decompiler.isFlowDebugging)
System.err.println("before Transformation: "+this);
static Transformation[] exprTrafos = { while (lastModified instanceof SequentialBlock) {
new RemoveEmpty(), if (!lastModified.getSubBlocks()[0].doTransformations())
new CreateExpression(), lastModified = lastModified.getSubBlocks()[1];
new CreatePrePostIncExpression(), }
new CreateAssignExpression(), while (lastModified.doTransformations())
new CreateNewConstructor(), /* empty */;
new CombineIfGotoExpressions(),
new CreateIfThenElseOperator(),
new CreateConstantArray(),
new CreateForInitializer(),
new CompleteSynchronized(),
};
if (Decompiler.isFlowDebugging)
System.err.println("after Transformation: "+this);
}
/** /**
* Search for an apropriate successor. * Search for an apropriate successor.
@ -944,21 +1009,12 @@ public class FlowBlock {
while (true) { while (true) {
if (Decompiler.isFlowDebugging) if (lastModified instanceof SwitchBlock) {
System.err.println("before Transformation: "+this); /* analyze the switch first.
*/
/* First do some non flow transformations. */ analyzeSwitch(start, end);
int i=0; }
while (i < exprTrafos.length) {
if (exprTrafos[i].transform(this))
i = 0;
else
i++;
checkConsistent();
}
if (Decompiler.isFlowDebugging)
System.err.println("after Transformation: "+this);
if (doT2(start, end)) { if (doT2(start, end)) {
@ -989,20 +1045,6 @@ public class FlowBlock {
+ addr + " - " + (addr+length)); + addr + " - " + (addr+length));
return changed; return changed;
} else { } else {
if (succ.block instanceof SwitchBlock) {
/* analyze succ, the new region is the
* continuous region of
* [start,end) \cap \compl [addr, addr+length)
* where succ.addr lies in.
*/
int newStart = (succ.addr > addr)
? addr+length : start;
int newEnd = (succ.addr > addr)
? end : addr;
if (succ.analyzeSwitch(newStart, newEnd))
break;
}
if ((succ.addr == addr+length if ((succ.addr == addr+length
|| succ.addr+succ.length == addr) || succ.addr+succ.length == addr)
/* Only do T1 transformation if the blocks are /* Only do T1 transformation if the blocks are
@ -1058,14 +1100,14 @@ public class FlowBlock {
* regions. Only blocks whose address lies in the given address * regions. Only blocks whose address lies in the given address
* range are considered and it is taken care of, that the switch * range are considered and it is taken care of, that the switch
* is never leaved. <p> * is never leaved. <p>
* The current flow block must contain the switch block as main * The current flow block must contain the switch block as lastModified
* block.
* @param start the start of the address range. * @param start the start of the address range.
* @param end the end of the address range. * @param end the end of the address range.
*/ */
public boolean analyzeSwitch(int start, int end) { public boolean analyzeSwitch(int start, int end) {
SwitchBlock switchBlock = (SwitchBlock) block; SwitchBlock switchBlock = (SwitchBlock) lastModified;
boolean changed = false; boolean changed = false;
int last = -1; int last = -1;
FlowBlock lastFlow = null; FlowBlock lastFlow = null;
for (int i=0; i < switchBlock.caseBlocks.length; i++) { for (int i=0; i < switchBlock.caseBlocks.length; i++) {
@ -1165,8 +1207,10 @@ public class FlowBlock {
jump.destination = END_OF_METHOD; jump.destination = END_OF_METHOD;
else else
jump.destination = instr[jump.destAddr]; jump.destination = instr[jump.destAddr];
if (jump.destination == null)
throw new AssertError("Missing dest: "+jump.destAddr);
addSuccessor(jump);
} }
addSuccessor(jump);
} }
} }

@ -56,6 +56,16 @@ public abstract class InstructionContainer extends StructuredBlock {
} }
} }
public boolean doTransformations() {
StructuredBlock last = flowBlock.lastModified;
return CreateNewConstructor.transform(this, last)
|| CreateExpression.transform(this, last)
|| CreatePrePostIncExpression.transform(this, last)
|| CreateAssignExpression.transform(this, last)
|| CreateIfThenElseOperator.create(this, last)
|| CreateConstantArray.transform(this, last);
}
/** /**
* Get the contained instruction. * Get the contained instruction.
* @return the contained instruction. * @return the contained instruction.

@ -51,7 +51,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* The increase instruction, only valid if type == FOR. * The increase instruction, only valid if type == FOR.
*/ */
Expression incr; Expression incr;
/** /**
* True, if the initializer is a declaration. * True, if the initializer is a declaration.
*/ */
@ -253,4 +253,10 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
public boolean jumpMayBeChanged() { public boolean jumpMayBeChanged() {
return mayChangeJump; return mayChangeJump;
} }
public boolean doTransformations() {
return type == FOR && init == null
&& CreateForInitializer.transform(this, flowBlock.lastModified);
}
} }

@ -21,41 +21,10 @@ package jode.flow;
import jode.Expression; import jode.Expression;
import jode.NopOperator; import jode.NopOperator;
public class RemoveEmpty implements Transformation { public class RemoveEmpty {
public boolean transform (FlowBlock fb) { public static boolean removeSwap(SpecialBlock swapBlock,
return (removeNop(fb) || removeSwap(fb) || removeEmpty(fb)); StructuredBlock last) {
}
public boolean removeNop(FlowBlock flow) {
StructuredBlock block = flow.lastModified;
if (block instanceof InstructionContainer
&& block.outer instanceof SequentialBlock
&& block.outer.getSubBlocks()[0] instanceof InstructionBlock) {
InstructionContainer ic = (InstructionContainer) block;
Expression nopInstr = ic.getInstruction();
if (!(nopInstr instanceof NopOperator)
|| nopInstr.getType() == jode.Type.tVoid)
return false;
InstructionBlock prev =
(InstructionBlock) ic.outer.getSubBlocks()[0];
Expression instr = prev.getInstruction();
if (instr.getType() == jode.Type.tVoid)
return false;
instr.setType(nopInstr.getType());
ic.setInstruction(instr);
ic.replace(ic.outer);
return true;
}
return false;
}
public boolean removeSwap(FlowBlock flow) {
/* Remove non needed swaps; convert: /* Remove non needed swaps; convert:
* *
* PUSH expr1 * PUSH expr1
@ -67,37 +36,43 @@ public class RemoveEmpty implements Transformation {
* PUSH expr2 * PUSH expr2
* PUSH expr1 * PUSH expr1
*/ */
StructuredBlock block = flow.lastModified; if (last.outer instanceof SequentialBlock
if (block instanceof SpecialBlock && last.outer.outer instanceof SequentialBlock
&& ((SpecialBlock)block).type == SpecialBlock.SWAP && last.outer.getSubBlocks()[0] instanceof InstructionBlock
&& block.outer instanceof SequentialBlock && last.outer.outer.getSubBlocks()[0]
&& block.outer.outer instanceof SequentialBlock
&& block.outer.getSubBlocks()[0] instanceof InstructionBlock
&& block.outer.outer.getSubBlocks()[0]
instanceof InstructionBlock) { instanceof InstructionBlock) {
InstructionBlock block1 InstructionBlock block1
= (InstructionBlock) block.outer.outer.getSubBlocks()[0]; = (InstructionBlock) last.outer.outer.getSubBlocks()[0];
InstructionBlock block2 InstructionBlock block2
= (InstructionBlock) block.outer.getSubBlocks()[0]; = (InstructionBlock) last.outer.getSubBlocks()[0];
/* XXX check if blocks may be swapped
* (there mustn't be side effects in one of them).
*/
System.err.println("WARNING: this program contains a SWAP "
+"opcode and may not be translated correctly.");
if (block1.getInstruction().isVoid() if (block1.getInstruction().isVoid()
|| block2.getInstruction().isVoid()) || block2.getInstruction().isVoid())
return false; return false;
/* PUSH expr1 == block1 /* PUSH expr1 == block1
* PUSH expr2 * PUSH expr2
* SWAP * SWAP
* ...
*/ */
block.outer.replace(block1.outer); last.outer.replace(block1.outer);
/* PUSH expr2 /* PUSH expr2
* SWAP * SWAP
* ...
*/ */
block1.replace(block); block1.replace(swapBlock);
block1.moveJump(block.jump); block1.moveJump(swapBlock.jump);
/* PUSH expr2 /* PUSH expr2
* PUSH expr1 * PUSH expr1
*/ */
flow.lastModified = block1; block1.flowBlock.lastModified = block1.outer;
return true; return true;
} }
return false; return false;

@ -56,4 +56,9 @@ public class SpecialBlock extends StructuredBlock {
+ ((count == 1) ? "" : "2") + ((count == 1) ? "" : "2")
+ ((depth == 0) ? "" : "_X"+depth)); + ((depth == 0) ? "" : "_X"+depth));
} }
public boolean doTransformation() {
return type == SWAP
&& RemoveEmpty.removeSwap(this, flowBlock.lastModified);
}
} }

@ -191,7 +191,7 @@ public abstract class StructuredBlock {
/** /**
* Removes the jump. This does not update the successors vector * Removes the jump. This does not update the successors vector
* of the flow block, you have to do it yourself. */ * of the flow block, you have to do it yourself. */
public void removeJump() { public final void removeJump() {
if (jump != null) { if (jump != null) {
jump.prev = null; jump.prev = null;
jump = null; jump = null;
@ -208,21 +208,15 @@ public abstract class StructuredBlock {
* will be moved to this block (may be this). * will be moved to this block (may be this).
*/ */
void moveDefinitions(StructuredBlock from, StructuredBlock sub) { void moveDefinitions(StructuredBlock from, StructuredBlock sub) {
if (from != sub && from != this) { while (from != sub && from != this) {
/* define(...) will not move from blocks, that are not sub blocks, used.unionExact(from.used);
* so we do it by hand.
*/
java.util.Enumeration enum = from.used.elements();
while (enum.hasMoreElements()) {
LocalInfo var =
((LocalInfo) enum.nextElement()).getLocalInfo();
if (!used.contains(var))
used.addElement(var);
}
from.used.removeAllElements(); from.used.removeAllElements();
StructuredBlock[] subs = from.getSubBlocks(); StructuredBlock[] subs = from.getSubBlocks();
for (int i=0; i<subs.length; i++) if (subs.length == 0)
return;
for (int i=0; i<subs.length - 1; i++)
moveDefinitions(subs[i], sub); moveDefinitions(subs[i], sub);
from = subs[subs.length-1];
} }
} }
@ -282,11 +276,16 @@ public abstract class StructuredBlock {
* @return the new combined block. * @return the new combined block.
*/ */
public StructuredBlock appendBlock(StructuredBlock block) { public StructuredBlock appendBlock(StructuredBlock block) {
SequentialBlock sequBlock = new SequentialBlock(); if (block instanceof EmptyBlock) {
sequBlock.replace(this); moveJump(block.jump);
sequBlock.setFirst(this); return this;
sequBlock.setSecond(block); } else {
return sequBlock; SequentialBlock sequBlock = new SequentialBlock();
sequBlock.replace(this);
sequBlock.setFirst(this);
sequBlock.setSecond(block);
return sequBlock;
}
} }
/** /**
@ -318,14 +317,6 @@ public abstract class StructuredBlock {
return false; return false;
} }
public void define(VariableSet vars) {
java.util.Enumeration enum = vars.elements();
while (enum.hasMoreElements()) {
LocalInfo var = ((LocalInfo) enum.nextElement()).getLocalInfo();
used.addElement(var);
}
}
public VariableSet propagateUsage() { public VariableSet propagateUsage() {
StructuredBlock[] subs = getSubBlocks(); StructuredBlock[] subs = getSubBlocks();
VariableSet allUse = (VariableSet) used.clone(); VariableSet allUse = (VariableSet) used.clone();
@ -371,7 +362,7 @@ public abstract class StructuredBlock {
} }
subs[i].checkConsistent(); subs[i].checkConsistent();
} }
if (jump != null) { if (jump != null && jump.destination != null) {
Jump jumps = (Jump) flowBlock.successors.get(jump.destination); Jump jumps = (Jump) flowBlock.successors.get(jump.destination);
for (; jumps != jump; jumps = jumps.next) { for (; jumps != jump; jumps = jumps.next) {
if (jumps == null) if (jumps == null)
@ -484,5 +475,12 @@ public abstract class StructuredBlock {
return super.toString(); return super.toString();
} }
} }
/**
* Do simple transformation on the structuredBlock.
*/
public boolean doTransformations() {
return false;
}
} }

@ -91,4 +91,8 @@ public class SynchronizedBlock extends StructuredBlock {
writer.untab(); writer.untab();
writer.println("}"); writer.println("}");
} }
public boolean doTransformations() {
return CompleteSynchronized.transform(this, flowBlock.lastModified);
}
} }

@ -192,7 +192,7 @@ public class ClassInterfacesType extends Type {
return tError; return tError;
ClassInterfacesType other = (ClassInterfacesType) type; ClassInterfacesType other = (ClassInterfacesType) type;
Class clazz = null; Class clazz;
Vector ifaces = new Vector(); Vector ifaces = new Vector();
/* First determine the clazz, one of the two classes must be a sub /* First determine the clazz, one of the two classes must be a sub

Loading…
Cancel
Save