Mirror of the JODE repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
jode/jode/src/net/sf/jode/flow/CreatePrePostIncExpression....

183 lines
6.1 KiB

/* 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;
}
}