Python: Fix ForNode class to support loop unrolling.

This commit is contained in:
Mark Shannon 2019-06-20 10:33:40 +01:00
Родитель a3d5d2c8e4
Коммит eb23c11142
1 изменённых файлов: 26 добавлений и 5 удалений

Просмотреть файл

@ -884,17 +884,38 @@ class ForNode extends ControlFlowNode {
override For getNode() { result = super.getNode() }
/** Whether this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */
/** Holds if this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */
predicate iterates(ControlFlowNode target, ControlFlowNode sequence) {
sequence = getSequence() and
target = possibleTarget() and
not target = unrolledSuffix().possibleTarget()
}
/** Gets the sequence node for this `for` statement. */
ControlFlowNode getSequence() {
exists(For for |
toAst(this) = for and
for.getTarget() = target.getNode() and
for.getIter() = sequence.getNode() |
sequence.getBasicBlock().dominates(this.getBasicBlock()) and
sequence.getBasicBlock().dominates(target.getBasicBlock())
for.getIter() = result.getNode() |
result.getBasicBlock().dominates(this.getBasicBlock())
)
}
/** A possible `target` for this `for` statement, not accounting for loop unrolling */
private ControlFlowNode possibleTarget() {
exists(For for |
toAst(this) = for and
for.getTarget() = result.getNode() and
this.getBasicBlock().dominates(result.getBasicBlock())
)
}
/** The unrolled `for` statement node matching this one */
private ForNode unrolledSuffix() {
not this = result and
toAst(this) = toAst(result) and
this.getBasicBlock().dominates(result.getBasicBlock())
}
}
/** A flow node for a `raise` statement */