Skip to content

Commit 9547a5c

Browse files
committed
Shared: Update basic block documentation and make minor tweaks
1 parent e5f419c commit 9547a5c

File tree

3 files changed

+83
-40
lines changed

3 files changed

+83
-40
lines changed

csharp/ql/lib/semmle/code/csharp/controlflow/BasicBlocks.qll

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,13 @@ final class BasicBlock extends BasicBlocksImpl::BasicBlock {
7676
/**
7777
* Holds if this basic block immediately dominates basic block `bb`.
7878
*
79-
* That is, all paths reaching basic block `bb` from some entry point
80-
* basic block must go through this basic block (which is an immediate
81-
* predecessor of `bb`).
79+
* That is, this basic block is the unique basic block satisfying:
80+
* 1. This basic block strictly dominates `bb`
81+
* 2. There exists no other basic block that is strictly dominated by this
82+
* basic block and which strictly dominates `bb`.
83+
*
84+
* All basic blocks, except entry basic blocks, have a unique immediate
85+
* dominator.
8286
*
8387
* Example:
8488
*
@@ -174,8 +178,13 @@ final class BasicBlock extends BasicBlocksImpl::BasicBlock {
174178
/**
175179
* Gets the basic block that immediately dominates this basic block, if any.
176180
*
177-
* That is, all paths reaching this basic block from some entry point
178-
* basic block must go through the result.
181+
* That is, the result is the unique basic block satisfying:
182+
* 1. The result strictly dominates this basic block.
183+
* 2. There exists no other basic block that is strictly dominated by the
184+
* result and which strictly dominates this basic block.
185+
*
186+
* All basic blocks, except entry basic blocks, have a unique immediate
187+
* dominator.
179188
*
180189
* Example:
181190
*

ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ final class BasicBlock extends BasicBlocksImpl::BasicBlock {
4040
/**
4141
* Holds if this basic block immediately dominates basic block `bb`.
4242
*
43-
* That is, all paths reaching basic block `bb` from some entry point
44-
* basic block must go through this basic block (which is an immediate
45-
* predecessor of `bb`).
43+
* That is, this basic block is the unique basic block satisfying:
44+
* 1. This basic block strictly dominates `bb`
45+
* 2. There exists no other basic block that is strictly dominated by this
46+
* basic block and which strictly dominates `bb`.
47+
*
48+
* All basic blocks, except entry basic blocks, have a unique immediate
49+
* dominator.
4650
*
4751
* Example:
4852
*
@@ -138,9 +142,13 @@ final class BasicBlock extends BasicBlocksImpl::BasicBlock {
138142
/**
139143
* Gets the basic block that immediately dominates this basic block, if any.
140144
*
141-
* That is, all paths reaching this basic block from some entry point
142-
* basic block must go through the result, which is an immediate basic block
143-
* predecessor of this basic block.
145+
* That is, the result is the unique basic block satisfying:
146+
* 1. The result strictly dominates this basic block.
147+
* 2. There exists no other basic block that is strictly dominated by the
148+
* result and which strictly dominates this basic block.
149+
*
150+
* All basic blocks, except entry basic blocks, have a unique immediate
151+
* dominator.
144152
*
145153
* Example:
146154
*

shared/controlflow/codeql/controlflow/BasicBlock.qll

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ signature module InputSig<LocationSig Location> {
1515
/** Hold if `t` represents a conditional successor type. */
1616
predicate successorTypeIsCondition(SuccessorType t);
1717

18-
/** Represents a delineated part of the AST with its own CFG. */
18+
/** A delineated part of the AST with its own CFG. */
1919
class CfgScope;
2020

2121
/** The class of control flow nodes. */
@@ -106,24 +106,28 @@ module Make<LocationSig Location, InputSig<Location> Input> {
106106
/**
107107
* Holds if this basic block immediately dominates basic block `bb`.
108108
*
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.
112116
*/
113117
predicate immediatelyDominates(BasicBlock bb) { bbIDominates(this, bb) }
114118

115119
/**
116120
* Holds if this basic block strictly dominates basic block `bb`.
117121
*
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
119123
* go through this basic block and this basic block is different from `bb`.
120124
*/
121125
predicate strictlyDominates(BasicBlock bb) { bbIDominates+(this, bb) }
122126

123127
/**
124128
* Holds if this basic block dominates basic block `bb`.
125129
*
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
127131
* go through this basic block.
128132
*/
129133
predicate dominates(BasicBlock bb) {
@@ -154,46 +158,67 @@ module Make<LocationSig Location, InputSig<Location> Input> {
154158
/**
155159
* Gets the basic block that immediately dominates this basic block, if any.
156160
*
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.
160168
*/
161169
BasicBlock getImmediateDominator() { bbIDominates(result, this) }
162170

163171
/**
164172
* 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`.
168174
*
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.
184178
*/
185179
pragma[nomagic]
186180
predicate immediatelyControls(BasicBlock succ, SuccessorType s) {
187181
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.
188199
forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this |
189200
succ.dominates(pred)
190201
)
191202
}
192203

193204
/**
194205
* 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.
197222
*/
198223
predicate controls(BasicBlock controlled, SuccessorType s) {
199224
// 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> {
308333
* Holds if `bbStart` is the first node in a basic block and `cfn` is the
309334
* `i`th node in the same basic block.
310335
*/
336+
pragma[nomagic]
311337
private predicate bbIndex(Node bbStart, Node cfn, int i) =
312338
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
313339

0 commit comments

Comments
 (0)