|
|
@ -27,15 +27,29 @@ import jode.decompiler.*; |
|
|
|
* The parameters may be stored in locals, before inlining the body of the |
|
|
|
* The parameters may be stored in locals, before inlining the body of the |
|
|
|
* method. |
|
|
|
* method. |
|
|
|
* |
|
|
|
* |
|
|
|
* This transformation will mark the expression as inlined and |
|
|
|
* Inlined methods look as follows: |
|
|
|
* This transformation creates expressions. It transforms |
|
|
|
* |
|
|
|
* <pre> |
|
|
|
* local_1 = expr_1 |
|
|
|
* Sequ[expr_1, Sequ[expr_2, ..., Sequ[expr_n, op] ...]] |
|
|
|
* local_2 = expr_2 |
|
|
|
* </pre> |
|
|
|
* [PUSH ]expr(local_1,local_2,constants...) |
|
|
|
* to |
|
|
|
* |
|
|
|
* <pre> |
|
|
|
* where local_1 and local_2 aren't used any more. |
|
|
|
* expr(op, [ expr_1, ..., expr_n ]) |
|
|
|
* |
|
|
|
* </pre> |
|
|
|
* If later one finds a reuse of local_x, the inline transformation |
|
|
|
|
|
|
|
* must be reverted: If there is no surrounding expression, the locals |
|
|
|
|
|
|
|
* are moved to initializers around; otherwise if the locals are used |
|
|
|
|
|
|
|
* in the expression or a super expression, they are combined with the |
|
|
|
|
|
|
|
* next occurence; otherwise the locals are moved behind the next expression. |
|
|
|
|
|
|
|
* This doesn't care for side effects though :-( |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* There are many other reasons why a part could look like this; only |
|
|
|
|
|
|
|
* if a matching method is found, that does exactly this (or if the |
|
|
|
|
|
|
|
* options createInlines is given), we may call this method. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* As long as inlines are not supported, if the local is never used, it |
|
|
|
|
|
|
|
* is simply removed; if the local is used only one time and there are |
|
|
|
|
|
|
|
* no side effects to the expression on the right hand side between usage |
|
|
|
|
|
|
|
* and initialization, the usage is replaced by the right hand side. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class MarkInlineExpression { |
|
|
|
public class MarkInlineExpression { |
|
|
|
|
|
|
|
|
|
|
@ -52,88 +66,51 @@ public class MarkInlineExpression { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
ComplexExpression parent = null; |
|
|
|
ComplexExpression parent = null; |
|
|
|
Expression inner = ic.getInstruction(); |
|
|
|
Expression expr = 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)) |
|
|
|
if (!(last.outer instanceof SequentialBlock)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
SequentialBlock sequBlock = (SequentialBlock)last.outer; |
|
|
|
SequentialBlock sequBlock = (SequentialBlock)last.outer; |
|
|
|
|
|
|
|
|
|
|
|
/* First check if Expression can be created, but do nothing yet. |
|
|
|
int localCount = 0; |
|
|
|
*/ |
|
|
|
while (sequBlock.subBlocks[0] instanceof InstructionBlock) { |
|
|
|
Expression lastExpression = null; |
|
|
|
InstructionBlock assign = |
|
|
|
for (int i = params;;) { |
|
|
|
(InstructionBlock) sequBlock.subBlocks[0]; |
|
|
|
|
|
|
|
if (!(assign.getInstruction().getOperator() |
|
|
|
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) |
|
|
|
instanceof LocalStoreOperator) |
|
|
|
return false; |
|
|
|
|| assign.getInstruction().getOperandCount() == 0) |
|
|
|
|
|
|
|
|
|
|
|
Expression expr = |
|
|
|
|
|
|
|
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!expr.isVoid()) { |
|
|
|
|
|
|
|
if (--i == 0) |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} else if (lastExpression == null |
|
|
|
|
|
|
|
|| lastExpression.canCombine(expr) <= 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (expr.getOperandCount() > 0) |
|
|
|
LocalStoreOperator store = (LocalStoreOperator) |
|
|
|
/* This is a not fully resolved expression in the |
|
|
|
assign.getInstruction().getOperator(); |
|
|
|
* middle, we must not touch it. */ |
|
|
|
if (!store.getLocal().onlyUsedInside(expr)) |
|
|
|
return false; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
lastExpression = expr; |
|
|
|
localCount++; |
|
|
|
|
|
|
|
|
|
|
|
if (!(sequBlock.outer instanceof SequentialBlock)) |
|
|
|
if (!(sequBlock.outer instanceof SequentialBlock)) |
|
|
|
return false; |
|
|
|
break; |
|
|
|
sequBlock = (SequentialBlock) sequBlock.outer; |
|
|
|
sequBlock = (SequentialBlock)sequBlock.outer; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (localCount == 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
/* Now, do the combination. Everything must succeed now. |
|
|
|
Expression[] stores = new Expression[localCount]; |
|
|
|
*/ |
|
|
|
|
|
|
|
Expression[] exprs = new Expression[params]; |
|
|
|
|
|
|
|
sequBlock = (SequentialBlock) last.outer; |
|
|
|
sequBlock = (SequentialBlock) last.outer; |
|
|
|
for (int i=params; ;) { |
|
|
|
for (int i=0; i<stores; i++) { |
|
|
|
|
|
|
|
stores[i] = ((InstructionBlock)sequBlock.subBlocks[0]) |
|
|
|
Expression expr = |
|
|
|
.getInstruction(); |
|
|
|
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction(); |
|
|
|
LocalStoreOperator store = |
|
|
|
|
|
|
|
(LocalStoreOperator) stores[i].getOperator(); |
|
|
|
if (!expr.isVoid()) { |
|
|
|
if (!store.getLocal().onlyUsedInside(expr)) |
|
|
|
exprs[--i] = expr; |
|
|
|
stores[i].get.markInlinedIn(expr); |
|
|
|
if (i == 0) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
exprs[i] = exprs[i].combine(expr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sequBlock = (SequentialBlock)sequBlock.outer; |
|
|
|
sequBlock = (SequentialBlock)sequBlock.outer; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(Decompiler.isVerbose) |
|
|
|
expr.markInlineExpression(stores); |
|
|
|
Decompiler.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); |
|
|
|
ic.moveDefinitions(sequBlock, last); |
|
|
|
last.replace(sequBlock); |
|
|
|
last.replace(sequBlock); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|