|
|
@ -199,69 +199,74 @@ public class FlowBlock { |
|
|
|
ConditionalBlock cb = (ConditionalBlock) jump.prev.outer; |
|
|
|
ConditionalBlock cb = (ConditionalBlock) jump.prev.outer; |
|
|
|
Expression instr = cb.getInstruction(); |
|
|
|
Expression instr = cb.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
// if (cb.outer instanceof LoopBlock
|
|
|
|
/* If this is the first instruction of a |
|
|
|
// || (cb.outer instanceof SequentialBlock
|
|
|
|
* while/for(true) block, make this the loop condition |
|
|
|
// && cb.outer.getSubBlocks()[0] == cb
|
|
|
|
* (negated of course). |
|
|
|
// && cb.outer.outer instanceof LoopBlock)) {
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
// LoopBlock loopBlock = (cb.outer instanceof LoopBlock) ?
|
|
|
|
|
|
|
|
// (LoopBlock) cb.outer : (LoopBlock) cb.outer.outer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (loopBlock.getCondition() == LoopBlock.TRUE &&
|
|
|
|
|
|
|
|
// loopBlock.getType() != LoopBlock.DOWHILE &&
|
|
|
|
|
|
|
|
// (loopBlock.jumpMayBeChanged()
|
|
|
|
|
|
|
|
// || loopBlock.getNextFlowBlock() == succ)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (loopBlock.jump == null) {
|
|
|
|
|
|
|
|
// /* consider this jump again */
|
|
|
|
|
|
|
|
// loopBlock.moveJump(jump);
|
|
|
|
|
|
|
|
// jumps = jump;
|
|
|
|
|
|
|
|
// } else
|
|
|
|
|
|
|
|
// jump.prev.removeJump();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// loopBlock.setCondition(instr.negate());
|
|
|
|
|
|
|
|
// loopBlock.moveDefinitions(cb, null);
|
|
|
|
|
|
|
|
// cb.removeBlock();
|
|
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// } else if (cb.outer instanceof SequentialBlock
|
|
|
|
if (cb.outer instanceof LoopBlock |
|
|
|
// && cb.outer.getSubBlocks()[1] == cb) {
|
|
|
|
|| (cb.outer instanceof SequentialBlock |
|
|
|
|
|
|
|
&& cb.outer.getSubBlocks()[0] == cb |
|
|
|
|
|
|
|
&& cb.outer.outer instanceof LoopBlock)) { |
|
|
|
|
|
|
|
|
|
|
|
// /* And now for do/while loops, where the jump is
|
|
|
|
LoopBlock loopBlock = (cb.outer instanceof LoopBlock) ? |
|
|
|
// * at the end of the loop.
|
|
|
|
(LoopBlock) cb.outer : (LoopBlock) cb.outer.outer; |
|
|
|
// */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// /* First find the beginning of the loop */
|
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
// StructuredBlock sb = cb.outer.outer;
|
|
|
|
loopBlock.getType() != LoopBlock.DOWHILE && |
|
|
|
// while (sb instanceof SequentialBlock) {
|
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
// sb = sb.outer;
|
|
|
|
|| loopBlock.getNextFlowBlock() == succ)) { |
|
|
|
// }
|
|
|
|
|
|
|
|
// /* sb is now the first and cb is the last
|
|
|
|
if (loopBlock.jump == null) { |
|
|
|
// * instruction in the current block.
|
|
|
|
/* consider this jump again */ |
|
|
|
// */
|
|
|
|
loopBlock.moveJump(jump); |
|
|
|
// if (sb instanceof LoopBlock) {
|
|
|
|
jumps = jump; |
|
|
|
// LoopBlock loopBlock = (LoopBlock) sb;
|
|
|
|
} else |
|
|
|
// if (loopBlock.getCondition() == LoopBlock.TRUE &&
|
|
|
|
jump.prev.removeJump(); |
|
|
|
// loopBlock.getType() == LoopBlock.WHILE &&
|
|
|
|
|
|
|
|
// (loopBlock.jumpMayBeChanged()
|
|
|
|
loopBlock.setCondition(instr.negate()); |
|
|
|
// || loopBlock.getNextFlowBlock() == succ)) {
|
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
|
|
|
|
cb.removeBlock(); |
|
|
|
// if (loopBlock.jump == null) {
|
|
|
|
continue; |
|
|
|
// /* consider this jump again */
|
|
|
|
} |
|
|
|
// loopBlock.moveJump(jump);
|
|
|
|
|
|
|
|
// jumps = jump;
|
|
|
|
} else if (cb.outer instanceof SequentialBlock |
|
|
|
// } else
|
|
|
|
&& cb.outer.getSubBlocks()[1] == cb) { |
|
|
|
// jump.prev.removeJump();
|
|
|
|
|
|
|
|
|
|
|
|
/* And now for do/while loops, where the jump is |
|
|
|
// loopBlock.setType(LoopBlock.DOWHILE);
|
|
|
|
* at the end of the loop. |
|
|
|
// loopBlock.setCondition(instr.negate());
|
|
|
|
*/ |
|
|
|
// loopBlock.moveDefinitions(cb, null);
|
|
|
|
|
|
|
|
// cb.removeBlock();
|
|
|
|
/* First find the beginning of the loop */ |
|
|
|
// continue;
|
|
|
|
StructuredBlock sb = cb.outer.outer; |
|
|
|
// }
|
|
|
|
while (sb instanceof SequentialBlock) { |
|
|
|
// }
|
|
|
|
sb = sb.outer; |
|
|
|
// }
|
|
|
|
} |
|
|
|
|
|
|
|
/* sb is now the first and cb is the last |
|
|
|
|
|
|
|
* instruction in the current block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (sb instanceof LoopBlock) { |
|
|
|
|
|
|
|
LoopBlock loopBlock = (LoopBlock) sb; |
|
|
|
|
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
|
|
|
|
loopBlock.getType() == LoopBlock.WHILE && |
|
|
|
|
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|
|
|
|
|| loopBlock.getNextFlowBlock() == succ)) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.jump == null) { |
|
|
|
|
|
|
|
/* consider this jump again */ |
|
|
|
|
|
|
|
loopBlock.moveJump(jump); |
|
|
|
|
|
|
|
jumps = jump; |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loopBlock.setType(LoopBlock.DOWHILE); |
|
|
|
|
|
|
|
loopBlock.setCondition(instr.negate()); |
|
|
|
|
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
|
|
|
|
cb.removeBlock(); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* replace all conditional jumps to the successor, which |
|
|
|
/* replace all conditional jumps to the successor, which |
|
|
|
* are followed by a block which has the end of the block |
|
|
|
* are followed by a block which has the end of the block |
|
|
@ -669,44 +674,44 @@ public class FlowBlock { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
// /**
|
|
|
|
* Find the exit condition of a for/while block. The loop block |
|
|
|
// * Find the exit condition of a for/while block. The loop block
|
|
|
|
* mustn't have an exit condition yet. |
|
|
|
// * mustn't have an exit condition yet.
|
|
|
|
*/ |
|
|
|
// */
|
|
|
|
public void mergeCondition() { |
|
|
|
// public void mergeCondition() {
|
|
|
|
/* If the first instruction of a while is a conditional |
|
|
|
// /* If the first instruction of a while is a conditional
|
|
|
|
* block, which jumps to the next address use the condition |
|
|
|
// * block, which jumps to the next address use the condition
|
|
|
|
* as while condition. |
|
|
|
// * as while condition.
|
|
|
|
*/ |
|
|
|
// */
|
|
|
|
LoopBlock loopBlock = (LoopBlock) lastModified; |
|
|
|
// LoopBlock loopBlock = (LoopBlock) lastModified;
|
|
|
|
int loopType = loopBlock.getType(); |
|
|
|
// int loopType = loopBlock.getType();
|
|
|
|
|
|
|
|
|
|
|
|
ConditionalBlock cb = null; |
|
|
|
// ConditionalBlock cb = null;
|
|
|
|
if (loopBlock.bodyBlock instanceof ConditionalBlock) |
|
|
|
// if (loopBlock.bodyBlock instanceof ConditionalBlock)
|
|
|
|
cb = (ConditionalBlock) loopBlock.bodyBlock; |
|
|
|
// cb = (ConditionalBlock) loopBlock.bodyBlock;
|
|
|
|
else if (loopBlock.bodyBlock instanceof SequentialBlock |
|
|
|
// else if (loopBlock.bodyBlock instanceof SequentialBlock
|
|
|
|
&& loopBlock.bodyBlock.getSubBlocks()[0] |
|
|
|
// && loopBlock.bodyBlock.getSubBlocks()[0]
|
|
|
|
instanceof ConditionalBlock) |
|
|
|
// instanceof ConditionalBlock)
|
|
|
|
cb = (ConditionalBlock) loopBlock.bodyBlock.getSubBlocks()[0]; |
|
|
|
// cb = (ConditionalBlock) loopBlock.bodyBlock.getSubBlocks()[0];
|
|
|
|
else if (loopBlock.bodyBlock instanceof SequentialBlock |
|
|
|
// else if (loopBlock.bodyBlock instanceof SequentialBlock
|
|
|
|
&& loopType == LoopBlock.WHILE) { |
|
|
|
// && loopType == LoopBlock.WHILE) {
|
|
|
|
loopType = LoopBlock.DOWHILE; |
|
|
|
// loopType = LoopBlock.DOWHILE;
|
|
|
|
SequentialBlock sequBlock = (SequentialBlock) loopBlock.bodyBlock; |
|
|
|
// SequentialBlock sequBlock = (SequentialBlock) loopBlock.bodyBlock;
|
|
|
|
while (sequBlock.subBlocks[1] instanceof SequentialBlock) |
|
|
|
// while (sequBlock.subBlocks[1] instanceof SequentialBlock)
|
|
|
|
sequBlock = (SequentialBlock) sequBlock.subBlocks[1]; |
|
|
|
// sequBlock = (SequentialBlock) sequBlock.subBlocks[1];
|
|
|
|
if (sequBlock.subBlocks[1] instanceof ConditionalBlock) |
|
|
|
// if (sequBlock.subBlocks[1] instanceof ConditionalBlock)
|
|
|
|
cb = (ConditionalBlock) sequBlock.subBlocks[1]; |
|
|
|
// cb = (ConditionalBlock) sequBlock.subBlocks[1];
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
if (cb != null |
|
|
|
// if (cb != null
|
|
|
|
&& cb.trueBlock.jump.destination.addr == addr + length) { |
|
|
|
// && cb.trueBlock.jump.destination.addr == addr + length) {
|
|
|
|
loopBlock.moveJump(cb.trueBlock.jump); |
|
|
|
// loopBlock.moveJump(cb.trueBlock.jump);
|
|
|
|
loopBlock.setCondition(cb.getInstruction().negate()); |
|
|
|
// loopBlock.setCondition(cb.getInstruction().negate());
|
|
|
|
loopBlock.setType(loopType); |
|
|
|
// loopBlock.setType(loopType);
|
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
// loopBlock.moveDefinitions(cb, null);
|
|
|
|
cb.removeBlock(); |
|
|
|
// cb.removeBlock();
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
public boolean doT2(int start, int end) { |
|
|
|
public boolean doT2(int start, int end) { |
|
|
|
/* If there are no jumps to the beginning of this flow block |
|
|
|
/* If there are no jumps to the beginning of this flow block |
|
|
@ -749,8 +754,6 @@ public class FlowBlock { |
|
|
|
&& lastModified instanceof InstructionBlock |
|
|
|
&& lastModified instanceof InstructionBlock |
|
|
|
&& ((InstructionBlock)lastModified).getInstruction().isVoid()) { |
|
|
|
&& ((InstructionBlock)lastModified).getInstruction().isVoid()) { |
|
|
|
|
|
|
|
|
|
|
|
Expression instr = |
|
|
|
|
|
|
|
((InstructionBlock)lastModified).getInstruction(); |
|
|
|
|
|
|
|
if (lastModified.outer instanceof SequentialBlock |
|
|
|
if (lastModified.outer instanceof SequentialBlock |
|
|
|
&& lastModified.outer.getSubBlocks()[0] |
|
|
|
&& lastModified.outer.getSubBlocks()[0] |
|
|
|
instanceof LoopBlock) { |
|
|
|
instanceof LoopBlock) { |
|
|
@ -767,38 +770,40 @@ public class FlowBlock { |
|
|
|
* continue to for. |
|
|
|
* continue to for. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
LoopBlock forBlock = |
|
|
|
LoopBlock forBlock = |
|
|
|
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE); |
|
|
|
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE); |
|
|
|
forBlock.replace(bodyBlock); |
|
|
|
forBlock.replace(bodyBlock); |
|
|
|
forBlock.setBody(bodyBlock); |
|
|
|
forBlock.setBody(bodyBlock); |
|
|
|
forBlock.incr = instr; |
|
|
|
forBlock.incr = (InstructionBlock) lastModified; |
|
|
|
forBlock.moveDefinitions(lastModified, null); |
|
|
|
|
|
|
|
forBlock.replaceBreakContinue(lb); |
|
|
|
forBlock.replaceBreakContinue(lb); |
|
|
|
|
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
|
|
|
|
lb.bodyBlock.replace(lastModified.outer); |
|
|
|
lb.bodyBlock.replace(lastModified.outer); |
|
|
|
createdForBlock = true; |
|
|
|
createdForBlock = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!createdForBlock && |
|
|
|
if (!createdForBlock |
|
|
|
(instr.getOperator() instanceof StoreInstruction |
|
|
|
&& ((InstructionBlock) |
|
|
|
|| instr.getOperator() instanceof IIncOperator)) { |
|
|
|
lastModified).getInstruction().isVoid()) { |
|
|
|
|
|
|
|
|
|
|
|
/* The only jump is the jump of the last |
|
|
|
/* The only jump is the jump of the last |
|
|
|
* instruction lastModified */ |
|
|
|
* instruction lastModified, there is a big |
|
|
|
|
|
|
|
* chance, that this is a for block, but we |
|
|
|
|
|
|
|
* can't be sure until we have seen the condition. |
|
|
|
|
|
|
|
* We will transform it to a for block, and take |
|
|
|
|
|
|
|
* that back, when we get a non matching condition. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
LoopBlock forBlock = |
|
|
|
LoopBlock forBlock = |
|
|
|
new LoopBlock(LoopBlock.FOR, LoopBlock.TRUE); |
|
|
|
new LoopBlock(LoopBlock.POSSFOR, LoopBlock.TRUE); |
|
|
|
forBlock.replace(bodyBlock); |
|
|
|
forBlock.replace(bodyBlock); |
|
|
|
forBlock.setBody(bodyBlock); |
|
|
|
forBlock.setBody(bodyBlock); |
|
|
|
forBlock.incr = instr; |
|
|
|
forBlock.incr = (InstructionBlock) lastModified; |
|
|
|
forBlock.moveDefinitions(lastModified, null); |
|
|
|
lastModified.removeBlock(); |
|
|
|
|
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
|
|
|
|
lastModified.outer.getSubBlocks()[0] |
|
|
|
|
|
|
|
.replace(lastModified.outer); |
|
|
|
|
|
|
|
createdForBlock = true; |
|
|
|
createdForBlock = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -864,7 +869,8 @@ public class FlowBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
predecessors.removeElement(this); |
|
|
|
predecessors.removeElement(this); |
|
|
|
lastModified = block; |
|
|
|
lastModified = block; |
|
|
|
mergeCondition(); |
|
|
|
doTransformations(); |
|
|
|
|
|
|
|
// mergeCondition();
|
|
|
|
|
|
|
|
|
|
|
|
/* T2 analysis succeeded */ |
|
|
|
/* T2 analysis succeeded */ |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
@ -942,6 +948,7 @@ public class FlowBlock { |
|
|
|
if (lastModified.jump.destination == END_OF_METHOD) |
|
|
|
if (lastModified.jump.destination == END_OF_METHOD) |
|
|
|
lastModified.removeJump(); |
|
|
|
lastModified.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
doTransformations(); |
|
|
|
/* transformation succeeded */ |
|
|
|
/* transformation succeeded */ |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
} |
|
|
|
} |
|
|
|