|
|
|
/* CreatePrePostIncExpression Copyright (C) 1998-2002 Jochen Hoenicke.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* along with this program; see the file COPYING.LESSER. If not, write to
|
|
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
package net.sf.jode.flow;
|
|
|
|
import net.sf.jode.expr.*;
|
|
|
|
import net.sf.jode.type.Type;
|
|
|
|
|
|
|
|
public class CreatePrePostIncExpression {
|
|
|
|
|
|
|
|
public static boolean transform(InstructionContainer ic,
|
|
|
|
StructuredBlock last)
|
|
|
|
{
|
|
|
|
return (createLocalPrePostInc(ic, last) || createPostInc(ic, last));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean createLocalPrePostInc(InstructionContainer ic,
|
|
|
|
StructuredBlock last) {
|
|
|
|
/* Situations:
|
|
|
|
*
|
|
|
|
* PUSH local_x -> PUSH local_x++
|
|
|
|
* IINC local_x, +/-1
|
|
|
|
*
|
|
|
|
* IINC local_x, +/-1
|
|
|
|
* PUSH local_x -> PUSH ++local_x
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!(last.outer instanceof SequentialBlock)
|
|
|
|
|| !(last.outer.getSubBlocks()[0] instanceof InstructionBlock))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Expression instr1 = ((InstructionBlock)
|
|
|
|
last.outer.getSubBlocks()[0]).getInstruction();
|
|
|
|
Expression instr2 = ic.getInstruction();
|
|
|
|
|
|
|
|
IIncOperator iinc;
|
|
|
|
LocalLoadOperator load;
|
|
|
|
boolean isPost;
|
|
|
|
if (instr1 instanceof IIncOperator
|
|
|
|
&& instr2 instanceof LocalLoadOperator) {
|
|
|
|
iinc = (IIncOperator) instr1;
|
|
|
|
load = (LocalLoadOperator) instr2;
|
|
|
|
isPost = false;
|
|
|
|
} else if (instr1 instanceof LocalLoadOperator
|
|
|
|
&& instr2 instanceof IIncOperator) {
|
|
|
|
load = (LocalLoadOperator) instr1;
|
|
|
|
iinc = (IIncOperator) instr2;
|
|
|
|
isPost = true;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int op;
|
|
|
|
if (iinc.getOperatorIndex() == Operator.ADD_OP + Operator.OPASSIGN_OP)
|
|
|
|
op = Operator.INC_OP;
|
|
|
|
else if (iinc.getOperatorIndex() == Operator.SUB_OP + Operator.OPASSIGN_OP)
|
|
|
|
op = Operator.DEC_OP;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (iinc.getValue() == -1)
|
|
|
|
op ^= 1;
|
|
|
|
else if (iinc.getValue() != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!iinc.lvalueMatches(load))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Type type = load.getType().intersection(Type.tUInt);
|
|
|
|
iinc.makeNonVoid();
|
|
|
|
Operator ppop =
|
|
|
|
new PrePostFixOperator(type, op, iinc.getLValue(), isPost);
|
|
|
|
|
|
|
|
ic.setInstruction(ppop);
|
|
|
|
ic.moveDefinitions(last.outer, last);
|
|
|
|
last.replace(last.outer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean createPostInc(InstructionContainer ic,
|
|
|
|
StructuredBlock last) {
|
|
|
|
|
|
|
|
/* Situation:
|
|
|
|
*
|
|
|
|
* PUSH load/storeOps (optional/
|
|
|
|
* not checked) PUSH load/storeOps
|
|
|
|
* DUP load/storeOps (optional) PUSH store++/--
|
|
|
|
* PUSH load(stack)
|
|
|
|
* DUP_X(storeOps count) ->
|
|
|
|
* store(stack) = stack_0 +/- 1
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!(ic.getInstruction() instanceof StoreInstruction))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
StoreInstruction store = (StoreInstruction) ic.getInstruction();
|
|
|
|
|
|
|
|
/* Make sure that the lvalue part of the store is
|
|
|
|
* not yet resolved (and note that the rvalue part
|
|
|
|
* should also have 1 remaining operand)
|
|
|
|
*/
|
|
|
|
Expression lvalue = store.getSubExpressions()[0];
|
|
|
|
int lvalueCount = lvalue.getFreeOperandCount();
|
|
|
|
if (!((Operator)lvalue).isFreeOperator()
|
|
|
|
|| !store.isVoid()
|
|
|
|
|| !(store.getSubExpressions()[1] instanceof BinaryOperator))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
BinaryOperator binOp = (BinaryOperator) store.getSubExpressions()[1];
|
|
|
|
if (binOp.getSubExpressions() == null
|
|
|
|
|| !(binOp.getSubExpressions()[0] instanceof NopOperator)
|
|
|
|
|| !(binOp.getSubExpressions()[1] instanceof ConstOperator))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ConstOperator constOp = (ConstOperator) binOp.getSubExpressions()[1];
|
|
|
|
int op;
|
|
|
|
if (binOp.getOperatorIndex() == Operator.ADD_OP)
|
|
|
|
op = Operator.INC_OP;
|
|
|
|
else if (binOp.getOperatorIndex() == Operator.SUB_OP)
|
|
|
|
op = Operator.DEC_OP;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!constOp.isOne(lvalue.getType()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(last.outer instanceof SequentialBlock))
|
|
|
|
return false;
|
|
|
|
SequentialBlock sb = (SequentialBlock)last.outer;
|
|
|
|
if (!(sb.subBlocks[0] instanceof SpecialBlock))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SpecialBlock dup = (SpecialBlock) sb.subBlocks[0];
|
|
|
|
if (dup.type != SpecialBlock.DUP
|
|
|
|
|| dup.count != lvalue.getType().stackSize()
|
|
|
|
|| dup.depth != lvalueCount)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(sb.outer instanceof SequentialBlock))
|
|
|
|
return false;
|
|
|
|
sb = (SequentialBlock) sb.outer;
|
|
|
|
if (!(sb.subBlocks[0] instanceof InstructionBlock))
|
|
|
|
return false;
|
|
|
|
InstructionBlock ib = (InstructionBlock) sb.subBlocks[0];
|
|
|
|
|
|
|
|
if (!(ib.getInstruction() instanceof Operator)
|
|
|
|
|| !store.lvalueMatches((Operator) ib.getInstruction()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (lvalueCount > 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 != lvalueCount
|
|
|
|
|| dup2.depth != 0)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ic.setInstruction
|
|
|
|
(new PrePostFixOperator(lvalue.getType(), op,
|
|
|
|
store.getLValue(), true));
|
|
|
|
ic.moveDefinitions(sb, last);
|
|
|
|
last.replace(sb);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|