|
|
@ -51,13 +51,22 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
VariableStack condStack; |
|
|
|
VariableStack condStack; |
|
|
|
/** |
|
|
|
/** |
|
|
|
* The init instruction, only valid if type == FOR or POSSFOR |
|
|
|
* The init instruction block, only valid if type == POSSFOR |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
InstructionBlock init; |
|
|
|
InstructionBlock initBlock; |
|
|
|
/** |
|
|
|
/** |
|
|
|
* The increase instruction, only valid if type == FOR or POSSFOR. |
|
|
|
* The increase instruction block, only valid if type == POSSFOR. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
InstructionBlock incr; |
|
|
|
InstructionBlock incrBlock; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* The init instruction, only valid if type == FOR. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Expression initInstr; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* The increase instruction, only valid if type == FOR. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Expression incrInstr; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* True, if the initializer is a declaration. |
|
|
|
* True, if the initializer is a declaration. |
|
|
@ -84,17 +93,22 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
VariableStack continueStack; |
|
|
|
VariableStack continueStack; |
|
|
|
|
|
|
|
|
|
|
|
/*{ invariant { type == POSSFOR || type == FOR || incr == null |
|
|
|
/*{ invariant { type == POSSFOR || (incrBlock == null && initBlock == null) |
|
|
|
:: "(while/do while) with incr"; |
|
|
|
:: "(while/do while) with incr"; |
|
|
|
type == FOR || init == null |
|
|
|
type == FOR || (incrInstr == null && initInstr == null) |
|
|
|
:: "(while/do while/poss for) with init"; |
|
|
|
:: "(while/do while/poss for) with init"; |
|
|
|
(type != FOR && type != POSSFOR) || incr != null |
|
|
|
type != POSSFOR || incrBlock != null |
|
|
|
:: "(possible) for without incr"; |
|
|
|
:: "possible for without incr"; |
|
|
|
|
|
|
|
type != FOR || incrInstr != null |
|
|
|
|
|
|
|
:: "for without incr"; |
|
|
|
type != POSSFOR || |
|
|
|
type != POSSFOR || |
|
|
|
(incr.getInstruction() instanceof CombineableOperator) |
|
|
|
incrBlock.getInstruction() instanceof CombineableOperator |
|
|
|
:: "possible for with invalid incr"; |
|
|
|
:: "possible for with invalid incr"; |
|
|
|
init == null || |
|
|
|
initBlock == null || |
|
|
|
(init.getInstruction() instanceof CombinableOperator) |
|
|
|
(initBlock.getInstruction() instanceof CombinableOperator) |
|
|
|
|
|
|
|
:: "Initializer is not combinableOperator"; |
|
|
|
|
|
|
|
initInstr == null || |
|
|
|
|
|
|
|
(initInstr instanceof CombinableOperator) |
|
|
|
:: "Initializer is not combinableOperator"; |
|
|
|
:: "Initializer is not combinableOperator"; |
|
|
|
cond != null && cond.getType() == Type.tBoolean |
|
|
|
cond != null && cond.getType() == Type.tBoolean |
|
|
|
:: "invalid condition type"; |
|
|
|
:: "invalid condition type"; |
|
|
@ -128,10 +142,13 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
body.setFlowBlock(flowBlock); |
|
|
|
body.setFlowBlock(flowBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setInit(InstructionBlock init) { |
|
|
|
public void setInit(InstructionBlock initBlock) { |
|
|
|
this.init = init; |
|
|
|
if (type == POSSFOR) { |
|
|
|
if (type == FOR) |
|
|
|
this.initBlock = initBlock; |
|
|
|
init.removeBlock(); |
|
|
|
} else if (type == FOR) { |
|
|
|
|
|
|
|
this.initInstr = initBlock.getInstruction(); |
|
|
|
|
|
|
|
initBlock.removeBlock(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean conditionMatches(CombineableOperator combinable) { |
|
|
|
public boolean conditionMatches(CombineableOperator combinable) { |
|
|
@ -149,23 +166,24 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
/* We can now say, if this is a for block or not. |
|
|
|
/* We can now say, if this is a for block or not. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (cond.containsMatchingLoad((CombineableOperator) |
|
|
|
if (cond.containsMatchingLoad((CombineableOperator) |
|
|
|
incr.getInstruction())) { |
|
|
|
incrBlock.getInstruction())) { |
|
|
|
type = FOR; |
|
|
|
type = FOR; |
|
|
|
incr.removeBlock(); |
|
|
|
incrInstr = incrBlock.getInstruction(); |
|
|
|
if (init != null) { |
|
|
|
incrBlock.removeBlock(); |
|
|
|
if (cond.containsMatchingLoad((CombineableOperator) |
|
|
|
if (initBlock != null) { |
|
|
|
init.getInstruction())) |
|
|
|
if (cond.containsMatchingLoad |
|
|
|
init.removeBlock(); |
|
|
|
((CombineableOperator) initBlock.getInstruction())) { |
|
|
|
else |
|
|
|
initInstr = initBlock.getInstruction(); |
|
|
|
init = null; |
|
|
|
initBlock.removeBlock(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
/* This is not a for block, as it seems first. Make |
|
|
|
/* This is not a for block, as it seems first. Make |
|
|
|
* it a while block again, and forget about init and |
|
|
|
* it a while block again, and forget about init and |
|
|
|
* incr. */ |
|
|
|
* incr. */ |
|
|
|
type = WHILE; |
|
|
|
type = WHILE; |
|
|
|
init = incr = null; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
initBlock = incrBlock = null; |
|
|
|
} |
|
|
|
} |
|
|
|
mayChangeJump = false; |
|
|
|
mayChangeJump = false; |
|
|
|
} |
|
|
|
} |
|
|
@ -183,10 +201,8 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
* loop-block. This is the initializer for for-blocks. |
|
|
|
* loop-block. This is the initializer for for-blocks. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void removeLocallyDeclareable(VariableSet set) { |
|
|
|
public void removeLocallyDeclareable(VariableSet set) { |
|
|
|
if (type == FOR && init != null |
|
|
|
if (type == FOR && initInstr instanceof StoreInstruction) { |
|
|
|
&& init.getInstruction() instanceof StoreInstruction) { |
|
|
|
StoreInstruction storeOp = (StoreInstruction) initInstr; |
|
|
|
StoreInstruction storeOp = |
|
|
|
|
|
|
|
(StoreInstruction) init.getInstruction(); |
|
|
|
|
|
|
|
if (storeOp.getLValue() instanceof LocalStoreOperator) { |
|
|
|
if (storeOp.getLValue() instanceof LocalStoreOperator) { |
|
|
|
LocalInfo local = |
|
|
|
LocalInfo local = |
|
|
|
((LocalStoreOperator) storeOp.getLValue()).getLocalInfo(); |
|
|
|
((LocalStoreOperator) storeOp.getLValue()).getLocalInfo(); |
|
|
@ -196,12 +212,14 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public VariableSet propagateUsage() { |
|
|
|
public VariableSet propagateUsage() { |
|
|
|
|
|
|
|
if (used == null) |
|
|
|
|
|
|
|
used = new VariableSet(); /*XXX*/ |
|
|
|
if (type == FOR) { |
|
|
|
if (type == FOR) { |
|
|
|
if (init != null) |
|
|
|
incrInstr.fillInGenSet(null, used); |
|
|
|
used.unionExact(init.used); |
|
|
|
if (initInstr != null) |
|
|
|
if (incr != null) |
|
|
|
initInstr.fillInGenSet(null, used); |
|
|
|
used.unionExact(incr.used); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
cond.fillInGenSet(null, used); |
|
|
|
VariableSet allUse = (VariableSet) used.clone(); |
|
|
|
VariableSet allUse = (VariableSet) used.clone(); |
|
|
|
allUse.unionExact(bodyBlock.propagateUsage()); |
|
|
|
allUse.unionExact(bodyBlock.propagateUsage()); |
|
|
|
return allUse; |
|
|
|
return allUse; |
|
|
@ -229,6 +247,30 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
return new StructuredBlock[] { bodyBlock }; |
|
|
|
return new StructuredBlock[] { bodyBlock }; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Check if this is an local store instruction to a not yet declared |
|
|
|
|
|
|
|
* variable. In that case mark this as declaration and return the |
|
|
|
|
|
|
|
* variable. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void checkDeclaration(VariableSet declareSet) { |
|
|
|
|
|
|
|
if (initInstr instanceof StoreInstruction |
|
|
|
|
|
|
|
&& (((StoreInstruction)initInstr).getLValue() |
|
|
|
|
|
|
|
instanceof LocalStoreOperator)) { |
|
|
|
|
|
|
|
StoreInstruction storeOp = (StoreInstruction) initInstr; |
|
|
|
|
|
|
|
LocalInfo local = |
|
|
|
|
|
|
|
((LocalStoreOperator) storeOp.getLValue()).getLocalInfo(); |
|
|
|
|
|
|
|
if (declareSet.contains(local)) { |
|
|
|
|
|
|
|
/* Special case: This is a variable assignment, and |
|
|
|
|
|
|
|
* the variable has not been declared before. We can |
|
|
|
|
|
|
|
* change this to a initializing variable declaration. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
isDeclaration = true; |
|
|
|
|
|
|
|
storeOp.getSubExpressions()[1].makeInitializer(); |
|
|
|
|
|
|
|
declareSet.removeElement(local); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Make the declarations, i.e. initialize the declare variable |
|
|
|
* Make the declarations, i.e. initialize the declare variable |
|
|
|
* to correct values. This will declare every variable that |
|
|
|
* to correct values. This will declare every variable that |
|
|
@ -237,8 +279,8 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void makeDeclaration(VariableSet done) { |
|
|
|
public void makeDeclaration(VariableSet done) { |
|
|
|
super.makeDeclaration(done); |
|
|
|
super.makeDeclaration(done); |
|
|
|
if (type == FOR && init != null) |
|
|
|
if (type == FOR && initInstr != null) |
|
|
|
init.checkDeclaration(declare); |
|
|
|
checkDeclaration(declare); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void dumpSource(TabbedPrintWriter writer) |
|
|
|
public void dumpSource(TabbedPrintWriter writer) |
|
|
@ -274,21 +316,21 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
break; |
|
|
|
break; |
|
|
|
case FOR: |
|
|
|
case FOR: |
|
|
|
writer.print("for ("); |
|
|
|
writer.print("for ("); |
|
|
|
if (init != null) { |
|
|
|
if (initInstr != null) { |
|
|
|
if (init.isDeclaration) { |
|
|
|
if (isDeclaration) { |
|
|
|
writer.printType(((LocalStoreOperator) |
|
|
|
writer.printType(((LocalStoreOperator) |
|
|
|
((CombineableOperator) |
|
|
|
((CombineableOperator) initInstr) |
|
|
|
init.getInstruction()).getLValue()) |
|
|
|
.getLValue()) |
|
|
|
.getLocalInfo().getType().getHint()); |
|
|
|
.getLocalInfo().getType().getHint()); |
|
|
|
writer.print(" "); |
|
|
|
writer.print(" "); |
|
|
|
} |
|
|
|
} |
|
|
|
init.getInstruction().dumpExpression(writer); |
|
|
|
initInstr.dumpExpression(writer); |
|
|
|
} else |
|
|
|
} else |
|
|
|
writer.print("/**/"); |
|
|
|
writer.print("/**/"); |
|
|
|
writer.print("; "); |
|
|
|
writer.print("; "); |
|
|
|
cond.dumpExpression(writer); |
|
|
|
cond.dumpExpression(writer); |
|
|
|
writer.print("; "); |
|
|
|
writer.print("; "); |
|
|
|
incr.getInstruction().dumpExpression(writer); |
|
|
|
incrInstr.dumpExpression(writer); |
|
|
|
writer.print(")"); |
|
|
|
writer.print(")"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -411,7 +453,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
|
|
|
|
|
|
|
|
public void removePush() { |
|
|
|
public void removePush() { |
|
|
|
if (condStack != null) |
|
|
|
if (condStack != null) |
|
|
|
cond = condStack.mergeIntoExpression(cond, used); |
|
|
|
cond = condStack.mergeIntoExpression(cond); |
|
|
|
bodyBlock.removePush(); |
|
|
|
bodyBlock.removePush(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -427,9 +469,9 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
public void removeOnetimeLocals() { |
|
|
|
public void removeOnetimeLocals() { |
|
|
|
cond = cond.removeOnetimeLocals(); |
|
|
|
cond = cond.removeOnetimeLocals(); |
|
|
|
if (type == FOR) { |
|
|
|
if (type == FOR) { |
|
|
|
if (init != null) |
|
|
|
if (initInstr != null) |
|
|
|
init.removeOnetimeLocals(); |
|
|
|
initInstr.removeOnetimeLocals(); |
|
|
|
incr.removeOnetimeLocals(); |
|
|
|
incrInstr.removeOnetimeLocals(); |
|
|
|
} |
|
|
|
} |
|
|
|
super.removeOnetimeLocals(); |
|
|
|
super.removeOnetimeLocals(); |
|
|
|
} |
|
|
|
} |
|
|
@ -470,15 +512,16 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock { |
|
|
|
public void simplify() { |
|
|
|
public void simplify() { |
|
|
|
cond = cond.simplify(); |
|
|
|
cond = cond.simplify(); |
|
|
|
if (type == FOR) { |
|
|
|
if (type == FOR) { |
|
|
|
incr.simplify(); |
|
|
|
incrInstr.simplify(); |
|
|
|
if (init != null) |
|
|
|
if (initInstr != null) |
|
|
|
init.simplify(); |
|
|
|
initInstr.simplify(); |
|
|
|
} |
|
|
|
} |
|
|
|
super.simplify(); |
|
|
|
super.simplify(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean doTransformations() { |
|
|
|
public boolean doTransformations() { |
|
|
|
return init == null && (type == FOR || type == POSSFOR) |
|
|
|
return ((initBlock == null && type == POSSFOR) |
|
|
|
|
|
|
|
|| (initInstr == null && type == FOR)) |
|
|
|
&& CreateForInitializer.transform(this, flowBlock.lastModified); |
|
|
|
&& CreateForInitializer.transform(this, flowBlock.lastModified); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|