diff --git a/jode/jode/flow/CreateAssignExpression.java b/jode/jode/flow/CreateAssignExpression.java index 48bceb3..fa95f63 100644 --- a/jode/jode/flow/CreateAssignExpression.java +++ b/jode/jode/flow/CreateAssignExpression.java @@ -42,9 +42,9 @@ public class CreateAssignExpression { * sequBlock: * dup (may be missing for static / local variables) * opBlock: - * (optional narrow) ((optional wide) load(stack) * rightHandSide) + * PUSH (optional narrow)((optional wide) load(stack) * RHS) * (optional dup_x) - * store(stack) + * store(POP) * * We transform it to: * (push loadstoreOps) @@ -53,15 +53,19 @@ public class CreateAssignExpression { * store(stack) *= (stack) * * If the optional dup is present the store*= becomes non void. */ + SequentialBlock opBlock = (SequentialBlock) last.outer; StoreInstruction store = (StoreInstruction) ic.getInstruction(); + if (!store.isFreeOperator()) + return false; + int lvalueCount = store.getLValue().getFreeOperandCount(); boolean isAssignOp = false; if (opBlock.subBlocks[0] instanceof SpecialBlock) { SpecialBlock dup = (SpecialBlock) opBlock.subBlocks[0]; if (dup.type != SpecialBlock.DUP - || dup.depth != store.getLValueOperandCount() - || dup.count != store.getLValueType().stackSize() + || dup.depth != lvalueCount + || dup.count != store.getLValue().getType().stackSize() || !(opBlock.outer instanceof SequentialBlock)) return false; opBlock = (SequentialBlock) opBlock.outer; @@ -72,13 +76,15 @@ public class CreateAssignExpression { return false; InstructionBlock ib = (InstructionBlock) opBlock.subBlocks[0]; - if (!(ib.getInstruction() instanceof ComplexExpression)) + if (!(ib.getInstruction() instanceof Operator)) return false; - - ComplexExpression expr = (ComplexExpression) ib.getInstruction(); + Operator expr = (Operator) ib.getInstruction(); + if (expr.getFreeOperandCount() != lvalueCount) + return false; + SpecialBlock dup = null; - if (store.getLValueOperandCount() > 0) { + if (lvalueCount > 0) { if (!(opBlock.outer instanceof SequentialBlock) || !(opBlock.outer.getSubBlocks()[0] instanceof SpecialBlock)) return false; @@ -87,48 +93,46 @@ public class CreateAssignExpression { dup = (SpecialBlock) sequBlock.subBlocks[0]; if (dup.type != SpecialBlock.DUP - || dup.depth != 0 - || dup.count != store.getLValueOperandCount()) + || dup.depth != 0 || dup.count != lvalueCount) return false; } int opIndex; Expression rightHandSide; - Type rhsType; - if (expr.getOperator() instanceof ConvertOperator - && expr.getSubExpressions()[0] instanceof ComplexExpression - && expr.getOperator().getType().isOfType(store.getLValueType())) { + if (expr instanceof ConvertOperator + && expr.getSubExpressions()[0] instanceof Operator + && expr.getType().isOfType(store.getLValue().getType())) { /* This gets tricky. We need to allow something like * s = (short) (int) ((double) s / 0.1); */ - expr = (ComplexExpression) expr.getSubExpressions()[0]; - while (expr.getOperator() instanceof ConvertOperator - && expr.getSubExpressions()[0] instanceof ComplexExpression) - expr = (ComplexExpression) expr.getSubExpressions()[0]; + expr = (Operator) expr.getSubExpressions()[0]; + while (expr instanceof ConvertOperator + && expr.getSubExpressions()[0] instanceof Operator) + expr = (Operator) expr.getSubExpressions()[0]; } - if (expr.getOperator() instanceof BinaryOperator) { - BinaryOperator binop = (BinaryOperator) expr.getOperator(); - - opIndex = binop.getOperatorIndex(); - if (opIndex < binop.ADD_OP || opIndex >= binop.ASSIGN_OP) + if (expr instanceof BinaryOperator) { + opIndex = expr.getOperatorIndex(); + if (opIndex < expr.ADD_OP || opIndex >= expr.ASSIGN_OP) + return false; + + if (!(expr.getSubExpressions()[0] instanceof Operator)) return false; - Expression loadExpr = expr.getSubExpressions()[0]; - while (loadExpr instanceof ComplexExpression - && loadExpr.getOperator() instanceof ConvertOperator) - loadExpr = ((ComplexExpression)loadExpr) - .getSubExpressions()[0]; - if (!(loadExpr instanceof Operator) - || !store.matches((Operator) loadExpr)) + Operator loadExpr = (Operator) expr.getSubExpressions()[0]; + while (loadExpr instanceof ConvertOperator + && loadExpr.getSubExpressions()[0] instanceof Operator) + loadExpr = (Operator) loadExpr.getSubExpressions()[0]; + + if (!store.lvalueMatches((Operator) loadExpr) + || !(loadExpr.isFreeOperator(lvalueCount))) return false; - if (store instanceof LocalStoreOperator) + if (store.getLValue() instanceof LocalStoreOperator) ((LocalLoadOperator)loadExpr).getLocalInfo().combineWith - (((LocalStoreOperator)store).getLocalInfo()); + (((LocalStoreOperator)store.getLValue()).getLocalInfo()); rightHandSide = expr.getSubExpressions()[1]; - rhsType = binop.getOperandType(1); } else { /* For String += the situation is more complex. * what is marked as load(stack) * rightHandSide above is @@ -139,31 +143,29 @@ public class CreateAssignExpression { Expression simple = expr.simplifyString(); rightHandSide = simple; /* Now search for the leftmost operand ... */ - ComplexExpression lastExpr = null; - while (simple instanceof ComplexExpression - && simple.getOperator() instanceof StringAddOperator) { - lastExpr = (ComplexExpression) simple; + Operator lastExpr = null; + Operator parent = null; + while (simple instanceof StringAddOperator) { + parent = lastExpr; + lastExpr = (Operator) simple; simple = lastExpr.getSubExpressions()[0]; } /* ... check it ... */ - if (lastExpr == null || !(simple instanceof Operator) - || !store.matches((Operator) simple)) + if (lastExpr == null + || !(simple instanceof Operator) + || !store.lvalueMatches((Operator) simple) + || !(((Operator) simple).isFreeOperator(lvalueCount))) return false; - if (store instanceof LocalStoreOperator) + if (store.getLValue() instanceof LocalStoreOperator) ((LocalLoadOperator)simple).getLocalInfo().combineWith - (((LocalStoreOperator)store).getLocalInfo()); + (((LocalStoreOperator)store.getLValue()).getLocalInfo()); /* ... and remove it. */ - if (lastExpr.getParent() != null) { - ComplexExpression ce = (ComplexExpression)lastExpr.getParent(); - StringAddOperator addOp = (StringAddOperator) ce.getOperator(); - addOp.clearFirstType(); - ce.setSubExpressions(0,lastExpr.getSubExpressions()[1]); - rhsType = Type.tString; + if (parent != null) { + parent.setSubExpressions(0, lastExpr.getSubExpressions()[1]); } else { - rhsType = lastExpr.getOperator().getOperandType(1); rightHandSide = lastExpr.getSubExpressions()[1]; } @@ -174,7 +176,7 @@ public class CreateAssignExpression { dup.removeBlock(); ib.setInstruction(rightHandSide); - store.makeOpAssign(store.OPASSIGN_OP+opIndex, rhsType); + store.makeOpAssign(store.OPASSIGN_OP + opIndex); if (isAssignOp) store.makeNonVoid(); @@ -187,17 +189,18 @@ public class CreateAssignExpression { /* Situation: * sequBlock: * dup_X(lvalue_count) - * store instruction + * store(POP) = POP */ SequentialBlock sequBlock = (SequentialBlock) last.outer; StoreInstruction store = (StoreInstruction) ic.getInstruction(); - if (sequBlock.subBlocks[0] instanceof SpecialBlock) { + if (sequBlock.subBlocks[0] instanceof SpecialBlock + && store.isFreeOperator()) { SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; if (dup.type != SpecialBlock.DUP - || dup.depth != store.getLValueOperandCount() - || dup.count != store.getLValueType().stackSize()) + || dup.depth != store.getLValue().getFreeOperandCount() + || dup.count != store.getLValue().getType().stackSize()) return false; dup.removeBlock(); diff --git a/jode/jode/flow/CreateCheckNull.java b/jode/jode/flow/CreateCheckNull.java index 4822d65..6d81e3b 100644 --- a/jode/jode/flow/CreateCheckNull.java +++ b/jode/jode/flow/CreateCheckNull.java @@ -39,7 +39,7 @@ public class CreateCheckNull { public static boolean transformJavac(InstructionContainer ic, StructuredBlock last) { if (!(last.outer instanceof SequentialBlock) - || !(ic.getInstruction() instanceof ComplexExpression) + || !(ic.getInstruction() instanceof Operator) || !(last.outer.getSubBlocks()[0] instanceof SpecialBlock)) return false; @@ -48,7 +48,7 @@ public class CreateCheckNull { || dup.count != 1 || dup.depth != 0) return false; - ComplexExpression ce = (ComplexExpression) ic.getInstruction(); + Operator ce = (Operator) ic.getInstruction(); if (!(ce.getOperator() instanceof PopOperator) || !(ce.getSubExpressions()[0] instanceof InvokeOperator)) @@ -83,9 +83,12 @@ public class CreateCheckNull { /* negate the instruction back to its original state */ Expression expr = ifBlock.cond.negate(); - if (!(expr instanceof CompareUnaryOperator) - || expr.getOperator().getOperatorIndex() != Operator.NOTEQUALS_OP - || !(expr.getOperator().getOperandType(0).isOfType(Type.tUObject))) + if (!(expr instanceof CompareUnaryOperator)) + return false; + + CompareUnaryOperator cmpOp = (CompareUnaryOperator) expr; + if (cmpOp.getOperatorIndex() != Operator.NOTEQUALS_OP + || !(cmpOp.getCompareType().isOfType(Type.tUObject))) return false; LocalInfo li = new LocalInfo(); diff --git a/jode/jode/flow/CreateConstantArray.java b/jode/jode/flow/CreateConstantArray.java index 0f17028..e8119d0 100644 --- a/jode/jode/flow/CreateConstantArray.java +++ b/jode/jode/flow/CreateConstantArray.java @@ -29,62 +29,56 @@ public class CreateConstantArray { /* Situation: * PUSH new Array[] // or a constant array operator. * DUP // duplicate array reference - * PUSH index - * PUSH value - * stack_2[stack_1] = stack_0 + * POP[index] = value * ... */ if (last.outer instanceof SequentialBlock) { SequentialBlock sequBlock = (SequentialBlock) last.outer; - Operator storeOp = ic.getInstruction().getOperator(); - if (!(ic.getInstruction() instanceof ComplexExpression) - || !(ic.getInstruction().getOperator() - instanceof ArrayStoreOperator) - || ic.getInstruction().getOperandCount() != 1 + if (!(ic.getInstruction() instanceof StoreInstruction) + || ic.getInstruction().getFreeOperandCount() != 1 || !(sequBlock.subBlocks[0] instanceof SpecialBlock) || !(sequBlock.outer instanceof SequentialBlock)) return false; - ComplexExpression storeExpr - = (ComplexExpression) ic.getInstruction(); - ArrayStoreOperator store - = (ArrayStoreOperator) storeExpr.getOperator(); + StoreInstruction store = (StoreInstruction) ic.getInstruction(); - Expression[] storeSub = storeExpr.getSubExpressions(); - if (!(storeSub[0] instanceof NopOperator) - || !(storeSub[1] instanceof ConstOperator)) + if (!(store.getLValue() instanceof ArrayStoreOperator)) return false; - Expression expr = storeSub[2]; - ConstOperator indexOp = (ConstOperator) storeSub[1]; + ArrayStoreOperator lvalue = (ArrayStoreOperator) store.getLValue(); + + if (!(lvalue.getSubExpressions()[0] instanceof NopOperator) + || !(lvalue.getSubExpressions()[1] instanceof ConstOperator)) + return false; + + Expression expr = store.getSubExpressions()[1]; + ConstOperator indexOp + = (ConstOperator) lvalue.getSubExpressions()[1]; SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; sequBlock = (SequentialBlock) sequBlock.outer; if (dup.type != SpecialBlock.DUP || dup.depth != 0 || dup.count != 1 + || !(indexOp.getType().isOfType(Type.tUInt)) || !(sequBlock.subBlocks[0] instanceof InstructionBlock)) return false; int index = Integer.parseInt(indexOp.getValue()); InstructionBlock ib = (InstructionBlock)sequBlock.subBlocks[0]; - if (ib.getInstruction() instanceof ComplexExpression - && (ib.getInstruction().getOperator() - instanceof NewArrayOperator)) { + if (ib.getInstruction() instanceof NewArrayOperator) { /* This is the first element */ - ComplexExpression newArrayExpr = - (ComplexExpression) ib.getInstruction(); - NewArrayOperator newArrayOp = - (NewArrayOperator) newArrayExpr.getOperator(); - if (newArrayOp.getOperandCount() != 1 - || !(newArrayExpr.getSubExpressions()[0] + NewArrayOperator newArray = + (NewArrayOperator) ib.getInstruction(); + if (newArray.getDimensions() != 1 + || !(newArray.getSubExpressions()[0] instanceof ConstOperator)) return false; ConstOperator countop = - (ConstOperator) newArrayExpr.getSubExpressions()[0]; + (ConstOperator) newArray.getSubExpressions()[0]; if (!countop.getType().isOfType(Type.tUInt)) return false; @@ -96,7 +90,7 @@ public class CreateConstantArray { GlobalOptions.err.print('a'); ConstantArrayOperator cao - = new ConstantArrayOperator(newArrayOp.getType(), + = new ConstantArrayOperator(newArray.getType(), arraylength); cao.setValue(index, expr); ic.setInstruction(cao); diff --git a/jode/jode/flow/CreateExpression.java b/jode/jode/flow/CreateExpression.java index 50ebc14..f59bf70 100644 --- a/jode/jode/flow/CreateExpression.java +++ b/jode/jode/flow/CreateExpression.java @@ -40,7 +40,7 @@ public class CreateExpression { */ public static boolean transform(InstructionContainer ic, StructuredBlock last) { - int params = ic.getInstruction().getOperandCount(); + int params = ic.getInstruction().getFreeOperandCount(); if (params == 0) return false; @@ -61,9 +61,9 @@ public class CreateExpression { if (!expr.isVoid()) break; - if (expr.getOperandCount() > 0 - || !(expr.getOperator() instanceof CombineableOperator) - || lastExpression.canCombine(expr) <= 0) + if (expr.getFreeOperandCount() > 0 + || !(expr instanceof CombineableOperator) + || lastExpression.canCombine((CombineableOperator) expr) <= 0) return false; /* Hmm, we should really set lastExpression to @@ -103,12 +103,13 @@ public class CreateExpression { break; } - lastExpression = lastExpression.combine(expr); + lastExpression = lastExpression.combine + ((CombineableOperator) expr); sequBlock = (SequentialBlock)sequBlock.outer; } if (GlobalOptions.verboseLevel > 0 - && lastExpression.getOperandCount() == 0) + && lastExpression.getFreeOperandCount() == 0) GlobalOptions.err.print('x'); ic.setInstruction(lastExpression); diff --git a/jode/jode/flow/CreateForInitializer.java b/jode/jode/flow/CreateForInitializer.java index cada48c..cd60b05 100644 --- a/jode/jode/flow/CreateForInitializer.java +++ b/jode/jode/flow/CreateForInitializer.java @@ -41,9 +41,9 @@ public class CreateForInitializer { InstructionBlock init = (InstructionBlock) sequBlock.subBlocks[0]; if (!init.getInstruction().isVoid() - || !(init.getInstruction().getOperator() - instanceof CombineableOperator) - || !forBlock.conditionMatches(init)) + || !(init.getInstruction() instanceof CombineableOperator) + || !forBlock.conditionMatches((CombineableOperator) + init.getInstruction())) return false; if (GlobalOptions.verboseLevel > 0) diff --git a/jode/jode/flow/CreateIfThenElseOperator.java b/jode/jode/flow/CreateIfThenElseOperator.java index caf3145..24d016e 100644 --- a/jode/jode/flow/CreateIfThenElseOperator.java +++ b/jode/jode/flow/CreateIfThenElseOperator.java @@ -59,6 +59,7 @@ public class CreateIfThenElseOperator { if (ifBlock.elseBlock == null) return false; + /* Next is a non-shortcut "or": simplify both blocks! */ if (!createFunnyHelper(trueDest, falseDest, ifBlock.thenBlock) | !createFunnyHelper(trueDest, falseDest, ifBlock.elseBlock)) return false; @@ -66,14 +67,13 @@ public class CreateIfThenElseOperator { if (GlobalOptions.verboseLevel > 0) GlobalOptions.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() - })); + Expression iteo = new IfThenElseOperator(Type.tBoolean) + .addOperand(((InstructionBlock) ifBlock.elseBlock) + .getInstruction()) + .addOperand(((InstructionBlock) ifBlock.thenBlock) + .getInstruction()) + .addOperand(ifBlock.cond); + ((InstructionBlock)ifBlock.thenBlock).setInstruction(iteo); ifBlock.thenBlock.moveDefinitions(ifBlock, null); ifBlock.thenBlock.replace(ifBlock); @@ -192,7 +192,7 @@ public class CreateIfThenElseOperator { */ public static boolean create(InstructionContainer ic, StructuredBlock last) { - Expression e[] = new Expression[3]; + Expression cond, thenExpr, elseExpr; InstructionBlock thenBlock; if (ic.jump == null || !(last.outer instanceof SequentialBlock)) @@ -210,13 +210,13 @@ public class CreateIfThenElseOperator { thenBlock = (InstructionBlock) ifBlock.thenBlock; - e[1] = thenBlock.getInstruction(); - if (e[1].isVoid() || e[1].getOperandCount() > 0) + thenExpr = thenBlock.getInstruction(); + if (thenExpr.isVoid() || thenExpr.getFreeOperandCount() > 0) return false; - e[2] = ic.getInstruction(); - if (e[2].isVoid() || e[2].getOperandCount() > 0) + elseExpr = ic.getInstruction(); + if (elseExpr.isVoid() || elseExpr.getFreeOperandCount() > 0) return false; - e[0] = ifBlock.cond; + cond = ifBlock.cond; if (GlobalOptions.verboseLevel > 0) GlobalOptions.err.print('?'); @@ -225,10 +225,12 @@ public class CreateIfThenElseOperator { thenBlock.removeJump(); IfThenElseOperator iteo = new IfThenElseOperator - (Type.tSuperType(e[1].getType()) - .intersection(Type.tSuperType(e[2].getType()))); - - ic.setInstruction(new ComplexExpression(iteo, e)); + (Type.tSuperType(thenExpr.getType()) + .intersection(Type.tSuperType(elseExpr.getType()))); + iteo.addOperand(elseExpr); + iteo.addOperand(thenExpr); + iteo.addOperand(cond); + ic.setInstruction(iteo); ic.moveDefinitions(last.outer, last); last.replace(last.outer); return true; diff --git a/jode/jode/flow/CreateNewConstructor.java b/jode/jode/flow/CreateNewConstructor.java index 58b3317..7daec7a 100644 --- a/jode/jode/flow/CreateNewConstructor.java +++ b/jode/jode/flow/CreateNewConstructor.java @@ -19,35 +19,122 @@ package jode.flow; import jode.expr.*; +import jode.bytecode.Reference; +import jode.decompiler.CodeAnalyzer; +import jode.type.Type; public class CreateNewConstructor { public static boolean transform(InstructionContainer ic, StructuredBlock last) { - /* Situation: + return transformNormal(ic, last) || transformJikesString(ic, last); + } + + static boolean transformJikesString(InstructionContainer ic, + StructuredBlock last) { + /* special Situation for Jikes String +=: + * + * PUSH new StringBuffer() + * SWAP + * PUSH POP.append(POP) + * + * We transform it to javac String +=: + * + * PUSH new StringBuffer(String.valueOf(POP)) + */ + if (!(last.outer instanceof SequentialBlock) + || !(ic.getInstruction() instanceof InvokeOperator)) + return false; + + InvokeOperator appendCall = (InvokeOperator) ic.getInstruction(); + if (!appendCall.getClassType().equals(Type.tStringBuffer) + || !appendCall.isFreeOperator(2) + || appendCall.isStatic() + || !appendCall.getMethodName().equals("append") + || appendCall.getMethodType().getParameterTypes().length != 1) + return false; + + SequentialBlock sequBlock = (SequentialBlock) last.outer; + if (!(sequBlock.outer instanceof SequentialBlock) + || !(sequBlock.subBlocks[0] instanceof SpecialBlock)) + return false; + + SpecialBlock swapBlock = (SpecialBlock) sequBlock.subBlocks[0]; + sequBlock = (SequentialBlock) sequBlock.outer; + if (swapBlock.type != SpecialBlock.SWAP + || !(sequBlock.subBlocks[0] instanceof InstructionBlock) + || !(sequBlock.outer instanceof SequentialBlock)) + return false; + + InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0]; + sequBlock = (SequentialBlock) sequBlock.outer; + if (!(ib.getInstruction() instanceof ConstructorOperator) + || !(sequBlock.subBlocks[0] instanceof InstructionBlock)) + return false; + + ConstructorOperator constr = (ConstructorOperator) ib.getInstruction(); + ib = (InstructionBlock) sequBlock.subBlocks[0]; + + if (constr.getClassType() != Type.tStringBuffer + || constr.isVoid() + || constr.getMethodType().getParameterTypes().length != 0) + return false; + + /* Okay everything checked. */ + CodeAnalyzer codeAna = constr.getCodeAnalyzer(); + Expression expr = ib.getInstruction(); + Type appendType = appendCall.getMethodType().getParameterTypes()[0]; + if (!appendType.equals(Type.tString)) { + InvokeOperator valueOf = new InvokeOperator + (codeAna, true, false, + Reference.getReference("Ljava/lang/String;", "valueOf", + "(" + appendType.getTypeSignature() + + ")Ljava/lang/String;")); + expr = valueOf.addOperand(expr); + } + ConstructorOperator newConstr = new ConstructorOperator + (Reference.getReference("Ljava/lang/StringBuffer;", "", + "(Ljava/lang/String;)V"), codeAna, false); + ic.setInstruction(newConstr.addOperand(expr)); + last.replace(sequBlock); + return true; + } + + static boolean transformNormal(InstructionContainer ic, + StructuredBlock last) { + /* Situation (normal): + * + * new + * (optional DUP) + * (void resolved expressions) + * stack_n.(resolved expressions) * + * transform it to + * + * (optional PUSH) new ((optional: stack_n), + * resolved expressions) + * + * special situation for string1 += string2: + * * new * (optional DUP) + * (void resolved expressions) * PUSH load_ops - * optionally: <= used for "string1 += string2" - * DUP_X2/1 <= 2 if above DUP is present - * stack_n.((optional: stack_n), resolved expressions) + * DUP_X2/1 <= 2 if above DUP is present + * stack_n.(stack_n, resolved expressions) * * transform it to * * PUSH load_ops - * optionally: - * DUP <= remove the depth - * (optional PUSH) new ((optional: stack_n), - * resolved expressions) + * DUP <= remove the depth + * (optional PUSH) new (stack_n, resolved expressions) */ if (!(last.outer instanceof SequentialBlock)) return false; - if (!(ic.getInstruction().getOperator() instanceof InvokeOperator)) + if (!(ic.getInstruction() instanceof InvokeOperator)) return false; - Expression constrExpr = ic.getInstruction(); - InvokeOperator constrCall = (InvokeOperator) constrExpr.getOperator(); + InvokeOperator constrCall = (InvokeOperator) ic.getInstruction(); if (!constrCall.isConstructor()) return false; @@ -55,13 +142,12 @@ public class CreateNewConstructor { SpecialBlock optDupX2 = null; SequentialBlock sequBlock = (SequentialBlock) last.outer; - - if (constrExpr instanceof ComplexExpression) { - Expression[] subs = - ((ComplexExpression) constrExpr).getSubExpressions(); + Expression[] subs = constrCall.getSubExpressions(); + int opcount = constrCall.getFreeOperandCount(); + if (subs != null) { if (!(subs[0] instanceof NopOperator)) return false; - if (constrExpr.getOperandCount() > 1) { + if (constrCall.getFreeOperandCount() > 1) { if (!(sequBlock.outer instanceof SequentialBlock) || !(sequBlock.subBlocks[0] instanceof SpecialBlock)) return false; @@ -71,7 +157,6 @@ public class CreateNewConstructor { || optDupX2.depth == 0) return false; int count = optDupX2.count; - int opcount = constrExpr.getOperandCount() - 1; do { if (!(sequBlock.outer instanceof SequentialBlock) || !(sequBlock.subBlocks[0] @@ -86,19 +171,22 @@ public class CreateNewConstructor { continue; count -= expr.getType().stackSize(); opcount--; - } while (count > 0 && opcount > 0); - if (opcount != 0 || count != 0) + } while (count > 0 && opcount > 1); + if (count != 0) return false; - } else if (constrExpr.getOperandCount() != 1) - return false; - } else if (constrExpr.getOperandCount() != 1) + } + } + if (opcount != 1) return false; - while (sequBlock.subBlocks[0] instanceof InstructionBlock - && ((InstructionBlock)sequBlock.subBlocks[0]) - .getInstruction().isVoid() - && sequBlock.outer instanceof SequentialBlock) + while (sequBlock.subBlocks[0] instanceof InstructionBlock + && sequBlock.outer instanceof SequentialBlock) { + Expression expr + = ((InstructionBlock)sequBlock.subBlocks[0]).getInstruction(); + if (!expr.isVoid() || expr.getFreeOperandCount() > 0) + break; sequBlock = (SequentialBlock) sequBlock.outer; + } SpecialBlock dup = null; if (sequBlock.outer instanceof SequentialBlock @@ -133,14 +221,9 @@ public class CreateNewConstructor { Expression newExpr = new ConstructorOperator (constrCall, dup == null); - if (constrExpr instanceof ComplexExpression) { - Expression[] subs = - ((ComplexExpression)constrExpr).getSubExpressions(); - for (int i=subs.length - 1; i>=1; i--) { - if (subs[i] instanceof NopOperator) - break; + if (subs != null) { + for (int i=subs.length; i-- > 1; ) newExpr = newExpr.addOperand(subs[i]); - } } ic.setInstruction(newExpr); return true; diff --git a/jode/jode/flow/CreatePrePostIncExpression.java b/jode/jode/flow/CreatePrePostIncExpression.java index 4b5bf3d..ba92a0c 100644 --- a/jode/jode/flow/CreatePrePostIncExpression.java +++ b/jode/jode/flow/CreatePrePostIncExpression.java @@ -77,12 +77,13 @@ public class CreatePrePostIncExpression { else if (!iinc.getValue().equals("1")) return false; - if (!iinc.matches(load)) + if (!iinc.lvalueMatches(load)) return false; Type type = load.getType().intersection(Type.tUInt); + iinc.makeNonVoid(); Operator ppop = - new LocalPrePostFixOperator(type, op, iinc, isPost); + new PrePostFixOperator(type, op, iinc.getLValue(), isPost); ic.setInstruction(ppop); ic.moveDefinitions(last.outer, last); @@ -103,41 +104,28 @@ public class CreatePrePostIncExpression { * store(stack) = stack_0 +/- 1 */ - if (!(ic.getInstruction() instanceof ComplexExpression) - || !(ic.getInstruction().getOperator() instanceof StoreInstruction) - || !(ic.getInstruction().isVoid())) + if (!(ic.getInstruction() instanceof StoreInstruction)) return false; - ComplexExpression storeExpr = (ComplexExpression) ic.getInstruction(); - StoreInstruction store = - (StoreInstruction) ic.getInstruction().getOperator(); + StoreInstruction store = (StoreInstruction) ic.getInstruction(); /* Make sure that the lvalue part of the store is - * not yet resolved (and not that the rvalue part + * not yet resolved (and note that the rvalue part * should also have 1 remaining operand) */ - int storeParams = store.getLValueOperandCount(); - if (storeExpr.getOperandCount() != storeParams + 1 - || !(storeExpr.getSubExpressions()[storeParams] - instanceof ComplexExpression)) + int lvalueCount = store.getLValue().getFreeOperandCount(); + if (!store.getLValue().isFreeOperator() + || !store.isVoid() + || !(store.getSubExpressions()[1] instanceof BinaryOperator)) return false; - if (storeParams > 0) { - for (int i=0; i< storeParams; i++) { - if (!(storeExpr.getSubExpressions()[i] instanceof NopOperator)) - return false; - } - } - ComplexExpression binExpr = (ComplexExpression) - storeExpr.getSubExpressions()[storeParams]; - if (!(binExpr instanceof ComplexExpression) - || !(binExpr.getOperator() instanceof BinaryOperator) - || !(binExpr.getSubExpressions()[0] instanceof NopOperator) - || !(binExpr.getSubExpressions()[1] instanceof ConstOperator)) + BinaryOperator binOp = (BinaryOperator) store.getSubExpressions()[1]; + if (binOp.getSubExpressions() == null + || !(binOp.getSubExpressions()[0] instanceof NopOperator) + || !(binOp.getSubExpressions()[1] instanceof ConstOperator)) return false; - BinaryOperator binOp = (BinaryOperator) binExpr.getOperator(); - ConstOperator constOp = (ConstOperator) binExpr.getSubExpressions()[1]; + ConstOperator constOp = (ConstOperator) binOp.getSubExpressions()[1]; int op; if (binOp.getOperatorIndex() == store.ADD_OP) op = Operator.INC_OP; @@ -161,8 +149,8 @@ public class CreatePrePostIncExpression { SpecialBlock dup = (SpecialBlock) sb.subBlocks[0]; if (dup.type != SpecialBlock.DUP - || dup.count != store.getLValueType().stackSize() - || dup.depth != store.getLValueOperandCount()) + || dup.count != store.getLValue().getType().stackSize() + || dup.depth != lvalueCount) return false; if (!(sb.outer instanceof SequentialBlock)) @@ -173,10 +161,10 @@ public class CreatePrePostIncExpression { InstructionBlock ib = (InstructionBlock) sb.subBlocks[0]; if (!(ib.getInstruction() instanceof Operator) - || !store.matches((Operator) ib.getInstruction())) + || !store.lvalueMatches((Operator) ib.getInstruction())) return false; - if (store.getLValueOperandCount() > 0) { + if (lvalueCount > 0) { if (!(sb.outer instanceof SequentialBlock)) return false; sb = (SequentialBlock) sb.outer; @@ -184,14 +172,16 @@ public class CreatePrePostIncExpression { return false; SpecialBlock dup2 = (SpecialBlock) sb.subBlocks[0]; if (dup2.type != SpecialBlock.DUP - || dup2.count != store.getLValueOperandCount() + || dup2.count != lvalueCount || dup2.depth != 0) return false; } ic.setInstruction - (new PrePostFixOperator(store.getLValueType(), op, store, true)); + (new PrePostFixOperator(store.getLValue().getType(), op, + store.getLValue(), true)); ic.moveDefinitions(sb, last); last.replace(sb); return true; } } + diff --git a/jode/jode/flow/FlowBlock.java b/jode/jode/flow/FlowBlock.java index 3b8d009..6060c31 100644 --- a/jode/jode/flow/FlowBlock.java +++ b/jode/jode/flow/FlowBlock.java @@ -965,8 +965,7 @@ public class FlowBlock { } if (!createdForBlock - && (((InstructionBlock) - lastModified).getInstruction().getOperator() + && (((InstructionBlock) lastModified).getInstruction() instanceof CombineableOperator)) { /* The only jump is the jump of the last diff --git a/jode/jode/flow/ReturnBlock.java b/jode/jode/flow/ReturnBlock.java index 0142e8a..b6fd5d3 100644 --- a/jode/jode/flow/ReturnBlock.java +++ b/jode/jode/flow/ReturnBlock.java @@ -47,7 +47,7 @@ public class ReturnBlock extends InstructionContainer { public VariableStack mapStackToLocal(VariableStack stack) { VariableStack newStack = stack; if (instr != null) { - int params = instr.getOperandCount(); + int params = instr.getFreeOperandCount(); if (params > 0) { this.stack = stack.peek(params); newStack = stack.pop(params); diff --git a/jode/jode/flow/SpecialBlock.java b/jode/jode/flow/SpecialBlock.java index f81c8c3..6b24184 100644 --- a/jode/jode/flow/SpecialBlock.java +++ b/jode/jode/flow/SpecialBlock.java @@ -113,8 +113,8 @@ public class SpecialBlock extends StructuredBlock { Expression expr2 = block2.getInstruction(); if (expr1.isVoid() || expr2.isVoid() - || expr1.getOperandCount() != 0 - || expr2.getOperandCount() != 0 + || expr1.getFreeOperandCount() != 0 + || expr2.getFreeOperandCount() != 0 || expr1.hasSideEffects(expr2) || expr2.hasSideEffects(expr1)) return false; @@ -175,18 +175,16 @@ public class SpecialBlock extends StructuredBlock { if (instr.getType().stackSize() == count) { StructuredBlock newBlock; - if (instr.getOperator() instanceof InvokeOperator - || instr.getOperator() instanceof ConstructorOperator) { - ComplexExpression newExpr = new ComplexExpression - (new PopOperator(instr.getType()), - new Expression[] { instr }); + if (instr instanceof InvokeOperator + || instr instanceof ConstructorOperator) { + Expression newExpr + = new PopOperator(instr.getType()).addOperand(instr); prev.setInstruction(newExpr); newBlock = prev; } else { - ComplexExpression newCond = new ComplexExpression - (new CompareUnaryOperator(instr.getType(), - Operator.NOTEQUALS_OP), - new Expression[] { instr }); + Expression newCond = new CompareUnaryOperator + (instr.getType(), Operator.NOTEQUALS_OP) + .addOperand(instr); IfThenElseBlock newIfThen = new IfThenElseBlock(newCond); newIfThen.setThenBlock(new EmptyBlock()); newBlock = newIfThen; @@ -204,41 +202,6 @@ public class SpecialBlock extends StructuredBlock { } return true; } - /* The following was another possibility to resolve pops, - * but it turned out to lead to stupid type errors, and - * it is obsolete due to the new stack analysis, now - */ -// } else if (last.outer.outer instanceof SequentialBlock -// && (last.outer.outer.getSubBlocks()[0] -// instanceof InstructionBlock)) { -// InstructionBlock prevprev -// = (InstructionBlock) last.outer.outer.getSubBlocks()[0]; -// Expression previnstr = prevprev.getInstruction(); -// if (previnstr.getType().stackSize() == 1 -// && instr.getType().stackSize() == 1 -// && count == 2 -// && (previnstr.getType().getSuperType() -// .isOfType(instr.getType()) -// || instr.getType().getSuperType() -// .isOfType(previnstr.getType()))) { -// /* compare two objects */ - -// ComplexExpression newCond = new ComplexExpression -// (new CompareBinaryOperator(instr.getType(), -// Operator.EQUALS_OP), -// new Expression[] { previnstr, instr }); -// IfThenElseBlock newIfThen = new IfThenElseBlock(newCond); -// newIfThen.setThenBlock(new EmptyBlock()); -// newIfThen.moveJump(jump); -// if (this == last) { -// newIfThen.replace(last.outer.outer); -// flowBlock.lastModified = newIfThen; -// } else { -// newIfThen.replace(this); -// last.replace(last.outer.outer); -// } -// return true; -// } } return false; } diff --git a/jode/jode/flow/SwitchBlock.java b/jode/jode/flow/SwitchBlock.java index 54ea529..b270628 100644 --- a/jode/jode/flow/SwitchBlock.java +++ b/jode/jode/flow/SwitchBlock.java @@ -89,7 +89,7 @@ implements BreakableBlock { */ public VariableStack mapStackToLocal(VariableStack stack) { VariableStack newStack; - int params = instr.getOperandCount(); + int params = instr.getFreeOperandCount(); if (params > 0) { exprStack = stack.peek(params); newStack = stack.pop(params); diff --git a/jode/jode/flow/TransformExceptionHandlers.java b/jode/jode/flow/TransformExceptionHandlers.java index 2d37396..6dfe263 100644 --- a/jode/jode/flow/TransformExceptionHandlers.java +++ b/jode/jode/flow/TransformExceptionHandlers.java @@ -189,18 +189,19 @@ public class TransformExceptionHandlers { } else if (firstInstr instanceof InstructionBlock) { Expression instr = ((InstructionBlock) firstInstr).getInstruction(); - if (instr instanceof LocalStoreOperator) { + if (instr instanceof StoreInstruction + && (((StoreInstruction)instr).getLValue() + instanceof LocalStoreOperator)) { /* The exception is stored in a local variable */ - local = ((LocalStoreOperator) instr).getLocalInfo(); + local = ((LocalStoreOperator) + ((StoreInstruction)instr).getLValue()).getLocalInfo(); firstInstr.removeBlock(); } } - if (local == null) { - local = new LocalInfo(); - local.setName("ERROR!!!"); - } - local.setType(type); + if (local != null) { + local.setType(type); + } CatchBlock newBlock = new CatchBlock(type, local); ((TryBlock)tryFlow.block).addCatchBlock(newBlock); @@ -222,9 +223,12 @@ public class TransformExceptionHandlers { SequentialBlock sequBlock = (SequentialBlock) subRoutine; InstructionBlock instr = (InstructionBlock)sequBlock.subBlocks[0]; - if (! (instr.getInstruction() instanceof LocalStoreOperator)) + if (!(instr.getInstruction() instanceof StoreInstruction) + || !(((StoreInstruction) instr.getInstruction()).getLValue() + instanceof LocalStoreOperator)) return false; - LocalStoreOperator store = (LocalStoreOperator) instr.getInstruction(); + LocalStoreOperator store = (LocalStoreOperator) + ((StoreInstruction)instr.getInstruction()).getLValue(); while (sequBlock.subBlocks[1] instanceof SequentialBlock) sequBlock = (SequentialBlock) sequBlock.subBlocks[1]; @@ -297,18 +301,20 @@ public class TransformExceptionHandlers { * in this case. */ try { - ComplexExpression expr = (ComplexExpression) + StoreInstruction store = (StoreInstruction) ((InstructionBlock) ret.outer.getSubBlocks()[0]).instr; - LocalStoreOperator store = - (LocalStoreOperator) expr.getOperator(); - if (store.matches((LocalLoadOperator) - ret.getInstruction())) { - ret.setInstruction(expr. - getSubExpressions()[0]); + LocalInfo local = + ((LocalStoreOperator) store.getLValue()) + .getLocalInfo(); + if (store.lvalueMatches + ((LocalLoadOperator) + ret.getInstruction())) { + Expression expr = + store.getSubExpressions()[1]; + ret.setInstruction(expr); ret.replace(ret.outer); - ret.used.removeElement - (store.getLocalInfo()); + ret.used.removeElement(local); } } catch(ClassCastException ex) { /* didn't succeed */ @@ -387,11 +393,11 @@ public class TransformExceptionHandlers { } static boolean isMonitorExit(Expression instr, LocalInfo local) { - if (instr instanceof ComplexExpression) { - ComplexExpression expr = (ComplexExpression)instr; - if (expr.getOperator() instanceof MonitorExitOperator - && expr.getSubExpressions()[0] instanceof LocalLoadOperator - && (((LocalLoadOperator) expr.getSubExpressions()[0]) + if (instr instanceof MonitorExitOperator) { + MonitorExitOperator monExit = (MonitorExitOperator)instr; + if (monExit.getFreeOperandCount() == 0 + && monExit.getSubExpressions()[0] instanceof LocalLoadOperator + && (((LocalLoadOperator) monExit.getSubExpressions()[0]) .getLocalInfo().getSlot() == local.getSlot())) { return true; } @@ -451,16 +457,7 @@ public class TransformExceptionHandlers { if (pred instanceof InstructionBlock) { Expression instr = ((InstructionBlock)pred).getInstruction(); - if (instr instanceof ComplexExpression - && ((ComplexExpression)instr) - .getOperator() instanceof MonitorExitOperator - && ((ComplexExpression)instr) - .getSubExpressions()[0] - instanceof LocalLoadOperator - && (((LocalLoadOperator) - ((ComplexExpression)instr) - .getSubExpressions()[0]).getLocalInfo() - .getSlot() == local.getSlot())) + if (isMonitorExit(instr, local)) continue; } } @@ -522,14 +519,13 @@ public class TransformExceptionHandlers { Expression instr = ((InstructionBlock)catchBlock.subBlocks[0]).getInstruction(); - if (instr instanceof ComplexExpression - && ((ComplexExpression)instr).getOperator() - instanceof MonitorExitOperator - && ((ComplexExpression)instr).getSubExpressions()[0] - instanceof LocalLoadOperator + if (instr instanceof MonitorExitOperator + && instr.getFreeOperandCount() == 0 + && (((MonitorExitOperator)instr).getSubExpressions()[0] + instanceof LocalLoadOperator) && catchBlock.subBlocks[1] instanceof ThrowBlock - && ((ThrowBlock)catchBlock.subBlocks[1]).instr - instanceof NopOperator) { + && (((ThrowBlock)catchBlock.subBlocks[1]).instr + instanceof NopOperator)) { /* This is a synchronized block: * @@ -558,11 +554,11 @@ public class TransformExceptionHandlers { */ catchFlow.removeSuccessor(catchBlock.subBlocks[1].jump); - ComplexExpression monexit = (ComplexExpression) + MonitorExitOperator monexit = (MonitorExitOperator) ((InstructionBlock) catchBlock.subBlocks[0]).instr; LocalInfo local = ((LocalLoadOperator)monexit.getSubExpressions()[0]) - .getLocalInfo(); + .getLocalInfo(); tryFlow.mergeAddr(catchFlow); checkAndRemoveMonitorExit @@ -639,11 +635,11 @@ public class TransformExceptionHandlers { if (catchBlock instanceof SequentialBlock && catchBlock.getSubBlocks()[0] instanceof JsrBlock - && instr instanceof LocalStoreOperator + && instr instanceof StoreInstruction && catchBlock.getSubBlocks()[1] instanceof ThrowBlock && (((ThrowBlock)catchBlock.getSubBlocks()[1]).instr instanceof LocalLoadOperator) - && (((LocalStoreOperator) instr).matches + && (((StoreInstruction) instr).lvalueMatches ((LocalLoadOperator) ((ThrowBlock)catchBlock.getSubBlocks()[1]).instr))) { diff --git a/jode/jode/flow/TryBlock.java b/jode/jode/flow/TryBlock.java index 2ac7034..aed4b5d 100644 --- a/jode/jode/flow/TryBlock.java +++ b/jode/jode/flow/TryBlock.java @@ -21,7 +21,6 @@ package jode.flow; import jode.decompiler.TabbedPrintWriter; import jode.type.*; import jode.expr.Expression; -import jode.expr.ComplexExpression; import jode.expr.InvokeOperator; import jode.expr.ConstructorOperator; import jode.expr.LocalLoadOperator; @@ -64,7 +63,7 @@ public class TryBlock extends StructuredBlock { tryFlow.checkConsistent(); } - public void addCatchBlock(CatchBlock catchBlock) { + public void addCatchBlock(StructuredBlock catchBlock) { StructuredBlock[] newSubBlocks = new StructuredBlock[subBlocks.length+1]; System.arraycopy(subBlocks, 0, newSubBlocks, 0, subBlocks.length); @@ -164,49 +163,41 @@ public class TryBlock extends StructuredBlock { ((InstructionBlock)subBlocks[0]).getInstruction(); CatchBlock catchBlock = (CatchBlock) subBlocks[1]; - if (instr.isVoid() - || !(instr instanceof ComplexExpression) - || !(instr.getOperator() instanceof InvokeOperator) + if (instr.isVoid() || instr.getFreeOperandCount() != 0 + || !(instr instanceof InvokeOperator) || !(catchBlock.catchBlock instanceof ThrowBlock) || !(catchBlock.exceptionType.equals (Type.tClass("java.lang.CloneNotSupportedException")))) return false; - - InvokeOperator arrayClone = - (InvokeOperator) instr.getOperator(); + InvokeOperator arrayClone = (InvokeOperator) instr; if (!arrayClone.getMethodName().equals("clone") || arrayClone.isStatic() - || (arrayClone.getMethodType().getParameterTypes() - .length != 0) - || (arrayClone.getMethodType().getReturnType() - != Type.tObject) - || !(((ComplexExpression) instr).getSubExpressions()[0] + || !(arrayClone.getMethodType().getTypeSignature() + .equals("()Ljava/lang/Object;")) + || !(arrayClone.getSubExpressions()[0] .getType().isOfType(Type.tArray(Type.tUnknown)))) return false; Expression throwExpr = ((ThrowBlock) catchBlock.catchBlock).getInstruction(); - if (!(throwExpr instanceof ComplexExpression) - || !(throwExpr.getOperator() instanceof ConstructorOperator)) + if (throwExpr.getFreeOperandCount() != 0 + || !(throwExpr instanceof ConstructorOperator)) return false; - ConstructorOperator throwOp = - (ConstructorOperator) throwExpr.getOperator(); + ConstructorOperator throwOp = (ConstructorOperator) throwExpr; if (!(throwOp.getClassType() .equals(Type.tClass("java.lang.InternalError"))) || throwOp.getMethodType().getParameterTypes().length != 1) return false; - Expression getMethodExpr = - ((ComplexExpression) throwExpr).getSubExpressions()[0]; - if (!(getMethodExpr instanceof ComplexExpression) - || !(getMethodExpr.getOperator() instanceof InvokeOperator)) + Expression getMethodExpr = throwOp.getSubExpressions()[0]; + if (!(getMethodExpr instanceof InvokeOperator)) return false; - InvokeOperator invoke = (InvokeOperator) getMethodExpr.getOperator(); + InvokeOperator invoke = (InvokeOperator) getMethodExpr; if (!invoke.getMethodName().equals("getMessage") || invoke.isStatic() || (invoke.getMethodType().getParameterTypes() @@ -215,12 +206,12 @@ public class TryBlock extends StructuredBlock { != Type.tString)) return false; - Expression exceptExpr = - ((ComplexExpression) getMethodExpr).getSubExpressions()[0]; + Expression exceptExpr = invoke.getSubExpressions()[0]; if (!(exceptExpr instanceof LocalLoadOperator) || !(((LocalLoadOperator) exceptExpr).getLocalInfo() .equals(catchBlock.exceptionLocal))) return false; + subBlocks[0].replace(this); if (flowBlock.lastModified == this) flowBlock.lastModified = subBlocks[0]; diff --git a/jode/jode/flow/VariableStack.java b/jode/jode/flow/VariableStack.java index fde84f3..ba1abb9 100644 --- a/jode/jode/flow/VariableStack.java +++ b/jode/jode/flow/VariableStack.java @@ -19,7 +19,6 @@ package jode.flow; import jode.decompiler.LocalInfo; -import jode.expr.ComplexExpression; import jode.expr.Expression; import jode.expr.LocalLoadOperator; import jode.expr.Operator; @@ -100,7 +99,7 @@ public class VariableStack { } public Expression mergeIntoExpression(Expression expr, VariableSet used) { - /* assert expr.getOperandCount() == stackMap.length */ + /* assert expr.getFreeOperandCount() == stackMap.length */ for (int i = stackMap.length-1; i >= 0; i--) { if (!used.contains(stackMap[i]))