@@ -15,7 +15,7 @@ signature module InputSig<LocationSig Location> {
15
15
/** Hold if `t` represents a conditional successor type. */
16
16
predicate successorTypeIsCondition ( SuccessorType t ) ;
17
17
18
- /** Represents a delineated part of the AST with its own CFG. */
18
+ /** A delineated part of the AST with its own CFG. */
19
19
class CfgScope ;
20
20
21
21
/** The class of control flow nodes. */
@@ -106,24 +106,28 @@ module Make<LocationSig Location, InputSig<Location> Input> {
106
106
/**
107
107
* Holds if this basic block immediately dominates basic block `bb`.
108
108
*
109
- * That is, `bb` is an immediate successor of this basic block and all
110
- * paths reaching basic block `bb` from some entry point basic block must
111
- * go through this basic block.
109
+ * That is, this basic block is the unique basic block satisfying:
110
+ * 1. This basic block strictly dominates `bb`
111
+ * 2. There exists no other basic block that is strictly dominated by this
112
+ * basic block and which strictly dominates `bb`.
113
+ *
114
+ * All basic blocks, except entry basic blocks, have a unique immediate
115
+ * dominator.
112
116
*/
113
117
predicate immediatelyDominates ( BasicBlock bb ) { bbIDominates ( this , bb ) }
114
118
115
119
/**
116
120
* Holds if this basic block strictly dominates basic block `bb`.
117
121
*
118
- * That is, all paths reaching `bb` from some entry point basic block must
122
+ * That is, all paths reaching `bb` from the entry point basic block must
119
123
* go through this basic block and this basic block is different from `bb`.
120
124
*/
121
125
predicate strictlyDominates ( BasicBlock bb ) { bbIDominates + ( this , bb ) }
122
126
123
127
/**
124
128
* Holds if this basic block dominates basic block `bb`.
125
129
*
126
- * That is, all paths reaching `bb` from some entry point basic block must
130
+ * That is, all paths reaching `bb` from the entry point basic block must
127
131
* go through this basic block.
128
132
*/
129
133
predicate dominates ( BasicBlock bb ) {
@@ -154,46 +158,67 @@ module Make<LocationSig Location, InputSig<Location> Input> {
154
158
/**
155
159
* Gets the basic block that immediately dominates this basic block, if any.
156
160
*
157
- * That is, all paths reaching this basic block from some entry point
158
- * basic block must go through the result, which is an immediate basic block
159
- * predecessor of this basic block.
161
+ * That is, the result is the unique basic block satisfying:
162
+ * 1. The result strictly dominates this basic block.
163
+ * 2. There exists no other basic block that is strictly dominated by the
164
+ * result and which strictly dominates this basic block.
165
+ *
166
+ * All basic blocks, except entry basic blocks, have a unique immediate
167
+ * dominator.
160
168
*/
161
169
BasicBlock getImmediateDominator ( ) { bbIDominates ( result , this ) }
162
170
163
171
/**
164
172
* Holds if basic block `succ` is immediately controlled by this basic
165
- * block with successor type `s`. That is, `succ` is an immediate successor
166
- * of this block, and `succ` can only be reached from the entry block by
167
- * going via the `s` edge out of this basic block.
173
+ * block with successor type `s`.
168
174
*
169
- * The above implies that this block immediately dominates `succ`. But
170
- * "controls" is a stronger notion than "dominates". It is not the case
171
- * that any immediate successor that is immediately dominated by this block
172
- * is also immediately controlled by this block. To see why, consider this
173
- * example corresponding to an `if`-statement without an `else` block:
174
- * ```
175
- * ... --> cond --[true]--> ... --> if stmt
176
- * \ /
177
- * ----[false]-----------
178
- * ```
179
- * The basic block for `cond` immediately dominates the immediately
180
- * succeeding basic block for the `if` statement. But the `if` statement
181
- * is not immediately controlled by the `cond` basic block and the `false`
182
- * edge since it is also possible to reach the `if` statement via a path
183
- * through the `true` edge.
175
+ * That is, `succ` is an immediate successor of this block, and `succ` can
176
+ * only be reached from the entry block by going via the `s` edge out of
177
+ * this basic block.
184
178
*/
185
179
pragma [ nomagic]
186
180
predicate immediatelyControls ( BasicBlock succ , SuccessorType s ) {
187
181
succ = this .getASuccessor ( s ) and
182
+ bbIDominates ( this , succ ) and
183
+ // The above is not sufficient to ensure that `succ` can only be reached
184
+ // through `s`. To see why, consider this example corresponding to an
185
+ // `if` expression without an `else` block:
186
+ // ```
187
+ // ... --> cond --[true]--> ... --> if expr
188
+ // \ /
189
+ // ----[false]-----------
190
+ // ```
191
+ // The basic block for `cond` immediately dominates the directly
192
+ // succeeding basic block for the `if` expression. But the `if`
193
+ // expression is not immediately controlled by the `cond` basic block and
194
+ // the `false` edge since it is also possible to reach the `if`
195
+ // expression via the `true` edge.
196
+ //
197
+ // Note that the first and third conjunct implies the second. But
198
+ // explicitly including the second conjunct leads to a better join order.
188
199
forall ( BasicBlock pred | pred = succ .getAPredecessor ( ) and pred != this |
189
200
succ .dominates ( pred )
190
201
)
191
202
}
192
203
193
204
/**
194
205
* Holds if basic block `controlled` is controlled by this basic block with
195
- * successor type `s`. That is, `controlled` can only be reached from the
196
- * entry point by going via the `s` edge out of this basic block.
206
+ * successor type `s`.
207
+ *
208
+ * That is, all paths reaching `controlled` from the entry point basic
209
+ * block must go through the `s` edge out of this basic block.
210
+ *
211
+ * Control is similar to dominance except it concerns edges instead of
212
+ * nodes: A basic block is _dominated_ by a _basic block_ `bb` if it can
213
+ * only be reached through `bb` and _controlled_ by an _edge_ `s` if it can
214
+ * only be reached through `s`.
215
+ *
216
+ * Note that where all basic blocks (except the entry basic block) are
217
+ * strictly dominated by at least one basic block, a basic block may not be
218
+ * controlled by any edge. If an edge controls a basic block `bb`, then
219
+ * both endpoints of the edge dominates `bb`. The converse is not the case,
220
+ * as there may be multiple paths between the endpoints with none of them
221
+ * dominating.
197
222
*/
198
223
predicate controls ( BasicBlock controlled , SuccessorType s ) {
199
224
// For this block to control the block `controlled` with `s` the following must be true:
@@ -308,6 +333,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
308
333
* Holds if `bbStart` is the first node in a basic block and `cfn` is the
309
334
* `i`th node in the same basic block.
310
335
*/
336
+ pragma [ nomagic]
311
337
private predicate bbIndex ( Node bbStart , Node cfn , int i ) =
312
338
shortestDistances( startsBB / 1 , intraBBSucc / 2 ) ( bbStart , cfn , i )
313
339
0 commit comments