|
|
@ -23,108 +23,147 @@ import jode.*; |
|
|
|
public class CreateAssignExpression implements Transformation{ |
|
|
|
public class CreateAssignExpression implements Transformation{ |
|
|
|
|
|
|
|
|
|
|
|
public boolean transform(FlowBlock flow) { |
|
|
|
public boolean transform(FlowBlock flow) { |
|
|
|
|
|
|
|
if (!(flow.lastModified instanceof InstructionContainer) |
|
|
|
|
|
|
|
|| !(flow.lastModified.outer instanceof SequentialBlock) |
|
|
|
|
|
|
|
|| !(((InstructionContainer)flow.lastModified).getInstruction() |
|
|
|
|
|
|
|
instanceof StoreInstruction) |
|
|
|
|
|
|
|
|| !(((InstructionContainer)flow.lastModified).getInstruction() |
|
|
|
|
|
|
|
.isVoid())) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
return (createAssignOp(flow) || createAssignExpression(flow)); |
|
|
|
return (createAssignOp(flow) || createAssignExpression(flow)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean createAssignOp(FlowBlock flow) { |
|
|
|
public boolean createAssignOp(FlowBlock flow) { |
|
|
|
Expression rightHandSide; |
|
|
|
|
|
|
|
StoreInstruction store; |
|
|
|
|
|
|
|
BinaryOperator binop; |
|
|
|
|
|
|
|
InstructionContainer lastBlock; |
|
|
|
|
|
|
|
SequentialBlock opBlock; |
|
|
|
|
|
|
|
SequentialBlock sequBlock; |
|
|
|
|
|
|
|
boolean isExpression = false; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
InstructionBlock ib; |
|
|
|
|
|
|
|
lastBlock = (InstructionContainer) flow.lastModified; |
|
|
|
|
|
|
|
store = (StoreInstruction) lastBlock.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opBlock = (SequentialBlock) lastBlock.outer; |
|
|
|
|
|
|
|
if (opBlock.subBlocks[1] != lastBlock) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Situation: |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* (push loadstoreOps) <- not checked |
|
|
|
|
|
|
|
* sequBlock: |
|
|
|
|
|
|
|
* dup |
|
|
|
|
|
|
|
* opBlock: |
|
|
|
|
|
|
|
* load(stack) * rightHandSide |
|
|
|
|
|
|
|
* (optional dup_x) |
|
|
|
|
|
|
|
* store(stack) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* We transform it to: |
|
|
|
|
|
|
|
* (push loadstoreOps) |
|
|
|
|
|
|
|
* rightHandSide |
|
|
|
|
|
|
|
* store(stack) *= (stack) |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* If the optional dup is present the store*= becomes non void. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
InstructionContainer lastBlock |
|
|
|
|
|
|
|
= (InstructionContainer) flow.lastModified; |
|
|
|
|
|
|
|
SequentialBlock opBlock = (SequentialBlock) lastBlock.outer; |
|
|
|
|
|
|
|
StoreInstruction store |
|
|
|
|
|
|
|
= (StoreInstruction) lastBlock.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean isAssignOp = false; |
|
|
|
if (opBlock.subBlocks[0] instanceof SpecialBlock) { |
|
|
|
if (opBlock.subBlocks[0] instanceof SpecialBlock) { |
|
|
|
SpecialBlock dup = (SpecialBlock) opBlock.subBlocks[0]; |
|
|
|
SpecialBlock dup = (SpecialBlock) opBlock.subBlocks[0]; |
|
|
|
if (dup.type != SpecialBlock.DUP |
|
|
|
if (dup.type != SpecialBlock.DUP |
|
|
|
|| dup.depth != store.getLValueOperandCount() |
|
|
|
|| dup.depth != store.getLValueOperandCount() |
|
|
|
|| dup.count != store.getLValueType().stackSize()) |
|
|
|
|| dup.count != store.getLValueType().stackSize() |
|
|
|
|
|
|
|
|| !(opBlock.outer instanceof SequentialBlock)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
opBlock = (SequentialBlock) lastBlock.outer; |
|
|
|
opBlock = (SequentialBlock) opBlock.outer; |
|
|
|
isExpression = true; |
|
|
|
isAssignOp = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ib = (InstructionBlock) opBlock.subBlocks[0]; |
|
|
|
if (!(opBlock.subBlocks[0] instanceof InstructionBlock)) |
|
|
|
ComplexExpression binopExpr = |
|
|
|
|
|
|
|
(ComplexExpression) ib.getInstruction(); |
|
|
|
|
|
|
|
binop = (BinaryOperator) binopExpr.getOperator(); |
|
|
|
|
|
|
|
if (binop.getOperatorIndex() < binop.ADD_OP || |
|
|
|
|
|
|
|
binop.getOperatorIndex() >= binop.ASSIGN_OP) |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
rightHandSide = binopExpr.getSubExpressions()[1]; |
|
|
|
InstructionBlock ib = (InstructionBlock) opBlock.subBlocks[0]; |
|
|
|
if (rightHandSide.isVoid()) |
|
|
|
|
|
|
|
return false; /* XXX */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Operator load = (Operator) binopExpr.getSubExpressions()[0]; |
|
|
|
if (!(opBlock.outer instanceof SequentialBlock) |
|
|
|
if (!store.matches(load)) |
|
|
|
|| !(opBlock.outer.getSubBlocks()[0] instanceof SpecialBlock)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
sequBlock = (SequentialBlock) opBlock.outer; |
|
|
|
SequentialBlock sequBlock = (SequentialBlock) opBlock.outer; |
|
|
|
|
|
|
|
|
|
|
|
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; |
|
|
|
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; |
|
|
|
if (dup.type != SpecialBlock.DUP |
|
|
|
if (dup.type != SpecialBlock.DUP |
|
|
|
|| dup.depth != 0 |
|
|
|
|| dup.depth != 0 |
|
|
|
|| dup.count != store.getLValueOperandCount()) |
|
|
|
|| dup.count != store.getLValueOperandCount()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} catch (ClassCastException ex) { |
|
|
|
|
|
|
|
|
|
|
|
if (!(ib.getInstruction() instanceof ComplexExpression)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} catch (NullPointerException ex) { |
|
|
|
ComplexExpression expr = (ComplexExpression) ib.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int opIndex; |
|
|
|
|
|
|
|
Expression rightHandSide; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (expr.getOperator() instanceof BinaryOperator) { |
|
|
|
|
|
|
|
BinaryOperator binop = (BinaryOperator) expr.getOperator(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opIndex = binop.getOperatorIndex(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (opIndex < binop.ADD_OP || opIndex >= binop.ASSIGN_OP |
|
|
|
|
|
|
|
|| !(expr.getSubExpressions()[0] instanceof Operator) |
|
|
|
|
|
|
|
|| !store.matches((Operator) expr.getSubExpressions()[0])) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rightHandSide = expr.getSubExpressions()[1]; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
Expression simple = expr.simplifyString(); |
|
|
|
|
|
|
|
rightHandSide = simple; |
|
|
|
|
|
|
|
/* Now search for the leftmost operand ... */ |
|
|
|
|
|
|
|
ComplexExpression last = null; |
|
|
|
|
|
|
|
while (simple instanceof ComplexExpression |
|
|
|
|
|
|
|
&& simple.getOperator() instanceof StringAddOperator) { |
|
|
|
|
|
|
|
last = (ComplexExpression) simple; |
|
|
|
|
|
|
|
simple = last.getSubExpressions()[0]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ... check it ... */ |
|
|
|
|
|
|
|
if (last == null || !(simple instanceof Operator) |
|
|
|
|
|
|
|
|| !store.matches((Operator) simple)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ... and remove it. */ |
|
|
|
|
|
|
|
if (last.getParent() != null) { |
|
|
|
|
|
|
|
((ComplexExpression)last.getParent()).getSubExpressions()[0] |
|
|
|
|
|
|
|
= last.getSubExpressions()[1]; |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
rightHandSide = last.getSubExpressions()[1]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opIndex = Operator.ADD_OP; |
|
|
|
} |
|
|
|
} |
|
|
|
((InstructionBlock)opBlock.subBlocks[0]) |
|
|
|
dup.removeBlock(); |
|
|
|
.setInstruction(rightHandSide); |
|
|
|
ib.setInstruction(rightHandSide); |
|
|
|
opBlock.moveDefinitions(sequBlock, opBlock); |
|
|
|
|
|
|
|
opBlock.replace(sequBlock); |
|
|
|
store.setOperatorIndex(store.OPASSIGN_OP+opIndex); |
|
|
|
|
|
|
|
|
|
|
|
store.setOperatorIndex(store.OPASSIGN_OP+binop.getOperatorIndex()); |
|
|
|
if (isAssignOp) |
|
|
|
store.setLValueType(binop.getType() |
|
|
|
store.makeNonVoid(); |
|
|
|
.intersection(store.getLValueType())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isExpression) |
|
|
|
|
|
|
|
lastBlock.setInstruction |
|
|
|
|
|
|
|
(new AssignOperator(store.getOperatorIndex(), store)); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
lastBlock.setInstruction(store); |
|
|
|
|
|
|
|
lastBlock.moveDefinitions(opBlock.subBlocks[1], lastBlock); |
|
|
|
|
|
|
|
lastBlock.replace(opBlock.subBlocks[1]); |
|
|
|
lastBlock.replace(opBlock.subBlocks[1]); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean createAssignExpression(FlowBlock flow) { |
|
|
|
public boolean createAssignExpression(FlowBlock flow) { |
|
|
|
StoreInstruction store; |
|
|
|
/* Situation: |
|
|
|
InstructionContainer lastBlock; |
|
|
|
* sequBlock: |
|
|
|
SequentialBlock sequBlock; |
|
|
|
* dup_X(lvalue_count) |
|
|
|
try { |
|
|
|
* store instruction |
|
|
|
lastBlock = (InstructionContainer) flow.lastModified; |
|
|
|
*/ |
|
|
|
store = (StoreInstruction) lastBlock.getInstruction(); |
|
|
|
InstructionContainer lastBlock |
|
|
|
|
|
|
|
= (InstructionContainer) flow.lastModified; |
|
|
|
|
|
|
|
SequentialBlock sequBlock = (SequentialBlock) lastBlock.outer; |
|
|
|
|
|
|
|
StoreInstruction store = (StoreInstruction) lastBlock.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
sequBlock = (SequentialBlock) lastBlock.outer; |
|
|
|
if (sequBlock.subBlocks[0] instanceof SpecialBlock) { |
|
|
|
|
|
|
|
|
|
|
|
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; |
|
|
|
SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; |
|
|
|
if (dup.type != SpecialBlock.DUP |
|
|
|
if (dup.type != SpecialBlock.DUP |
|
|
|
|| dup.depth != store.getLValueOperandCount() |
|
|
|
|| dup.depth != store.getLValueOperandCount() |
|
|
|
|| dup.count != store.getLValueType().stackSize()) |
|
|
|
|| dup.count != store.getLValueType().stackSize()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} catch (NullPointerException ex) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} catch (ClassCastException ex) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
lastBlock.setInstruction |
|
|
|
|
|
|
|
(new AssignOperator(store.getOperatorIndex(), store)); |
|
|
|
|
|
|
|
lastBlock.moveDefinitions(sequBlock, lastBlock); |
|
|
|
|
|
|
|
lastBlock.replace(sequBlock); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dup.removeBlock(); |
|
|
|
|
|
|
|
store.makeNonVoid(); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|