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/CreateAssignExpression.java

216 lines
7.5 KiB

/* CreateAssignExpression 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 CreateAssignExpression {
public static boolean transform(InstructionContainer ic,
StructuredBlock last) {
if (!(last.outer instanceof SequentialBlock)
|| !(ic.getInstruction() instanceof StoreInstruction)
|| !(ic.getInstruction().isVoid()))
return false;
return (createAssignOp(ic, last) || createAssignExpression(ic, last));
}
public static boolean createAssignOp(InstructionContainer ic,
StructuredBlock last) {
/* Situation:
*
* (push loadstoreOps) <- not checked
* sequBlock:
* dup (may be missing for static / local variables)
* opBlock:
* PUSH (optional narrow)((optional wide) load(stack) * RHS)
* (optional dup_x)
* store(POP)
*
* We transform it to:
* (push loadstoreOps)
* rightHandSide
* (optional dup_x)
* 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() || store.isOpAssign())
return false;
Expression lvalue = store.getSubExpressions()[0];
int lvalueCount = lvalue.getFreeOperandCount();
boolean isAssignOp = false;
if (opBlock.subBlocks[0] instanceof SpecialBlock) {
SpecialBlock dup = (SpecialBlock) opBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != lvalueCount
|| dup.count != lvalue.getType().stackSize()
|| !(opBlock.outer instanceof SequentialBlock))
return false;
opBlock = (SequentialBlock) opBlock.outer;
isAssignOp = true;
}
if (!(opBlock.subBlocks[0] instanceof InstructionBlock))
return false;
InstructionBlock ib = (InstructionBlock) opBlock.subBlocks[0];
if (!(ib.getInstruction() instanceof Operator))
return false;
Operator expr = (Operator) ib.getInstruction();
if (expr.getFreeOperandCount() != lvalueCount)
return false;
Type rvalueType = expr.getType();
SpecialBlock dup = null;
if (lvalueCount > 0) {
if (!(opBlock.outer instanceof SequentialBlock)
|| !(opBlock.outer.getSubBlocks()[0] instanceof SpecialBlock))
return false;
SequentialBlock sequBlock = (SequentialBlock) opBlock.outer;
dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != 0 || dup.count != lvalueCount)
return false;
}
int opIndex;
Expression rightHandSide;
if (expr instanceof ConvertOperator
&& expr.getSubExpressions()[0] instanceof Operator
&& expr.getType().isOfType(lvalue.getType())) {
/* This gets tricky. We need to allow something like
* s = (short) (int) ((double) s / 0.1);
*/
expr = (Operator) expr.getSubExpressions()[0];
while (expr instanceof ConvertOperator
&& expr.getSubExpressions()[0] instanceof Operator)
expr = (Operator) expr.getSubExpressions()[0];
}
if (expr instanceof BinaryOperator) {
opIndex = expr.getOperatorIndex();
if (opIndex < Operator.ADD_OP || opIndex >= Operator.ASSIGN_OP)
return false;
if (!(expr.getSubExpressions()[0] instanceof Operator))
return false;
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 (lvalue instanceof LocalStoreOperator)
((LocalLoadOperator)loadExpr).getLocalInfo().combineWith
(((LocalStoreOperator)lvalue).getLocalInfo());
rightHandSide = expr.getSubExpressions()[1];
} else {
/* For String += the situation is more complex.
* what is marked as load(stack) * rightHandSide above is
* really (after simplification):
*
* PUSH ((load(stack) + right) + Hand) + Side
*/
Expression simple = expr.simplifyString();
rightHandSide = simple;
/* Now search for the leftmost operand ... */
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.lvalueMatches((Operator) simple)
|| !(((Operator) simple).isFreeOperator(lvalueCount)))
return false;
if (lvalue instanceof LocalStoreOperator)
((LocalLoadOperator)simple).getLocalInfo().combineWith
(((LocalStoreOperator)lvalue).getLocalInfo());
/* ... and remove it. */
if (parent != null) {
parent.setSubExpressions(0, lastExpr.getSubExpressions()[1]);
} else {
rightHandSide = lastExpr.getSubExpressions()[1];
}
opIndex = Operator.ADD_OP;
}
if (dup != null)
dup.removeBlock();
ib.setInstruction(rightHandSide);
lvalue.setType(rvalueType);
store.makeOpAssign(Operator.OPASSIGN_OP + opIndex);
if (isAssignOp)
store.makeNonVoid();
last.replace(opBlock.subBlocks[1]);
return true;
}
public static boolean createAssignExpression(InstructionContainer ic,
StructuredBlock last) {
/* Situation:
* sequBlock:
* dup_X(lvalue_count)
* store(POP) = POP
*/
SequentialBlock sequBlock = (SequentialBlock) last.outer;
StoreInstruction store = (StoreInstruction) ic.getInstruction();
if (sequBlock.subBlocks[0] instanceof SpecialBlock
&& store.isFreeOperator()) {
Expression lvalue = store.getSubExpressions()[0];
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0];
if (dup.type != SpecialBlock.DUP
|| dup.depth != lvalue.getFreeOperandCount()
|| dup.count != lvalue.getType().stackSize())
return false;
dup.removeBlock();
store.makeNonVoid();
return true;
}
return false;
}
}