44
55import go
66private import ControlFlowGraphImpl
7+ private import codeql.controlflow.BasicBlock as BB
8+ private import codeql.controlflow.SuccessorType
9+
10+ private module Input implements BB:: InputSig< Location > {
11+ // /** Hold if `t` represents a conditional successor type. */
12+ // predicate successorTypeIsCondition(SuccessorType t) { none() }
13+ /** A delineated part of the AST with its own CFG. */
14+ class CfgScope = ControlFlow:: Root ;
15+
16+ /** The class of control flow nodes. */
17+ class Node = ControlFlowNode ;
18+
19+ /** Gets the CFG scope in which this node occurs. */
20+ CfgScope nodeGetCfgScope ( Node node ) { node .getRoot ( ) = result }
21+
22+ /** Gets an immediate successor of this node. */
23+ Node nodeGetASuccessor ( Node node , SuccessorType t ) {
24+ result = node .getASuccessor ( ) and
25+ (
26+ not result instanceof ControlFlow:: ConditionGuardNode and t instanceof DirectSuccessor
27+ or
28+ t .( BooleanSuccessor ) .getValue ( ) = result .( ControlFlow:: ConditionGuardNode ) .getOutcome ( )
29+ )
30+ }
731
8- /**
9- * Holds if `nd` starts a new basic block.
10- */
11- private predicate startsBB ( ControlFlow:: Node nd ) {
12- count ( nd .getAPredecessor ( ) ) != 1
13- or
14- nd .getAPredecessor ( ) .isBranch ( )
15- }
16-
17- /**
18- * Holds if the first node of basic block `succ` is a control flow
19- * successor of the last node of basic block `bb`.
20- */
21- private predicate succBB ( BasicBlock bb , BasicBlock succ ) { succ = bb .getLastNode ( ) .getASuccessor ( ) }
22-
23- /**
24- * Holds if the first node of basic block `bb` is a control flow
25- * successor of the last node of basic block `pre`.
26- */
27- private predicate predBB ( BasicBlock bb , BasicBlock pre ) { succBB ( pre , bb ) }
28-
29- /** Holds if `bb` is an entry basic block. */
30- private predicate entryBB ( BasicBlock bb ) { bb .getFirstNode ( ) .isEntryNode ( ) }
31-
32- /** Holds if `bb` is an exit basic block. */
33- private predicate exitBB ( BasicBlock bb ) { bb .getLastNode ( ) .isExitNode ( ) }
34-
35- cached
36- private module Internal {
3732 /**
38- * Holds if `succ` is a control flow successor of `nd` within the same basic block.
33+ * Holds if `node` represents an entry node to be used when calculating
34+ * dominance.
3935 */
40- private predicate intraBBSucc ( ControlFlow:: Node nd , ControlFlow:: Node succ ) {
41- succ = nd .getASuccessor ( ) and
42- not startsBB ( succ )
43- }
36+ predicate nodeIsDominanceEntry ( Node node ) { node instanceof EntryNode }
4437
4538 /**
46- * Holds if `nd` is the `i`th node in basic block `bb`.
47- *
48- * In other words, `i` is the shortest distance from a node `bb`
49- * that starts a basic block to `nd` along the `intraBBSucc` relation.
39+ * Holds if `node` represents an exit node to be used when calculating
40+ * post dominance.
5041 */
51- cached
52- predicate bbIndex ( BasicBlock bb , ControlFlow:: Node nd , int i ) =
53- shortestDistances( startsBB / 1 , intraBBSucc / 2 ) ( bb , nd , i )
54-
55- cached
56- int bbLength ( BasicBlock bb ) { result = strictcount ( ControlFlow:: Node nd | bbIndex ( bb , nd , _) ) }
57-
58- cached
59- predicate reachableBB ( BasicBlock bb ) {
60- entryBB ( bb )
61- or
62- exists ( BasicBlock predBB | succBB ( predBB , bb ) | reachableBB ( predBB ) )
63- }
42+ predicate nodeIsPostDominanceExit ( Node node ) { node instanceof ExitNode }
6443}
6544
66- private import Internal
45+ private module BbImpl = BB :: Make < Location , Input > ;
6746
68- /** Holds if `dom` is an immediate dominator of `bb`. */
69- cached
70- private predicate bbIDominates ( BasicBlock dom , BasicBlock bb ) =
71- idominance( entryBB / 1 , succBB / 2 ) ( _, dom , bb )
72-
73- /** Holds if `dom` is an immediate post-dominator of `bb`. */
74- cached
75- private predicate bbIPostDominates ( BasicBlock dom , BasicBlock bb ) =
76- idominance( exitBB / 1 , predBB / 2 ) ( _, dom , bb )
77-
78- /**
79- * A basic block, that is, a maximal straight-line sequence of control flow nodes
80- * without branches or joins.
81- *
82- * At the database level, a basic block is represented by its first control flow node.
83- */
84- class BasicBlock extends TControlFlowNode {
85- BasicBlock ( ) { startsBB ( this ) }
47+ // import BbImpl
48+ class BasicBlock extends BbImpl:: BasicBlock {
49+ /** Gets an immediate successor of this basic block of a given type, if any. */
50+ BasicBlock getASuccessor ( SuccessorType t ) { result = super .getASuccessor ( t ) }
8651
8752 /** Gets a basic block succeeding this one. */
88- BasicBlock getASuccessor ( ) { succBB ( this , result ) }
53+ BasicBlock getASuccessor ( ) { result = this . getASuccessor ( _ ) }
8954
9055 /** Gets a basic block preceding this one. */
9156 BasicBlock getAPredecessor ( ) { result .getASuccessor ( ) = this }
9257
93- /** Gets a node in this block. */
94- ControlFlow:: Node getANode ( ) { result = this .getNode ( _) }
95-
96- /** Gets the node at the given position in this block. */
97- ControlFlow:: Node getNode ( int pos ) { bbIndex ( this , result , pos ) }
98-
99- /** Gets the first node in this block. */
100- ControlFlow:: Node getFirstNode ( ) { result = this }
101-
102- /** Gets the last node in this block. */
103- ControlFlow:: Node getLastNode ( ) { result = this .getNode ( this .length ( ) - 1 ) }
104-
105- /** Gets the length of this block. */
106- int length ( ) { result = bbLength ( this ) }
107-
10858 /** Gets the basic block that immediately dominates this basic block. */
109- ReachableBasicBlock getImmediateDominator ( ) { bbIDominates ( result , this ) }
59+ ReachableBasicBlock getImmediateDominator ( ) { result . immediatelyDominates ( this ) }
11060
11161 /** Gets the innermost function or file to which this basic block belongs. */
112- ControlFlow:: Root getRoot ( ) { result = this .getFirstNode ( ) .getRoot ( ) }
113-
114- /** Gets a textual representation of this basic block. */
115- string toString ( ) { result = "basic block" }
116-
117- /** Gets the source location for this element. */
118- Location getLocation ( ) { result = this .getFirstNode ( ) .getLocation ( ) }
119-
120- /**
121- * DEPRECATED: Use `getLocation()` instead.
122- *
123- * Holds if this basic block is at the specified location.
124- * The location spans column `startcolumn` of line `startline` to
125- * column `endcolumn` of line `endline` in file `filepath`.
126- * For more information, see
127- * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
128- */
129- deprecated predicate hasLocationInfo (
130- string filepath , int startline , int startcolumn , int endline , int endcolumn
131- ) {
132- this .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
133- }
62+ ControlFlow:: Root getRoot ( ) { result = this .getScope ( ) }
13463}
13564
136- /**
137- * An entry basic block, that is, a basic block whose first node is an entry node.
138- */
139- class EntryBasicBlock extends BasicBlock {
140- EntryBasicBlock ( ) { entryBB ( this ) }
65+ cached
66+ private predicate reachableBB ( BasicBlock bb ) {
67+ bb instanceof BbImpl :: EntryBasicBlock
68+ or
69+ exists ( BasicBlock predBB | predBB . getASuccessor ( ) = bb | reachableBB ( predBB ) )
14170}
14271
14372/**
14473 * A basic block that is reachable from an entry basic block.
14574 */
14675class ReachableBasicBlock extends BasicBlock {
14776 ReachableBasicBlock ( ) { reachableBB ( this ) }
148-
149- /**
150- * Holds if this basic block strictly dominates `bb`.
151- */
152- cached
153- predicate strictlyDominates ( ReachableBasicBlock bb ) { bbIDominates + ( this , bb ) }
154-
155- /**
156- * Holds if this basic block dominates `bb`.
157- *
158- * This predicate is reflexive: each reachable basic block dominates itself.
159- */
160- predicate dominates ( ReachableBasicBlock bb ) {
161- bb = this or
162- this .strictlyDominates ( bb )
163- }
164-
165- /**
166- * Holds if this basic block strictly post-dominates `bb`.
167- */
168- cached
169- predicate strictlyPostDominates ( ReachableBasicBlock bb ) { bbIPostDominates + ( this , bb ) }
170-
171- /**
172- * Holds if this basic block post-dominates `bb`.
173- *
174- * This predicate is reflexive: each reachable basic block post-dominates itself.
175- */
176- predicate postDominates ( ReachableBasicBlock bb ) {
177- bb = this or
178- this .strictlyPostDominates ( bb )
179- }
18077}
18178
18279/**
@@ -193,12 +90,5 @@ class ReachableJoinBlock extends ReachableBasicBlock {
19390 * who in turn attribute it to Ferrante et al., "The program dependence graph and
19491 * its use in optimization".
19592 */
196- predicate inDominanceFrontierOf ( ReachableBasicBlock b ) {
197- b = this .getAPredecessor ( ) and not b = this .getImmediateDominator ( )
198- or
199- exists ( ReachableBasicBlock prev | this .inDominanceFrontierOf ( prev ) |
200- b = prev .getImmediateDominator ( ) and
201- not b = this .getImmediateDominator ( )
202- )
203- }
93+ predicate inDominanceFrontierOf ( ReachableBasicBlock b ) { b .inDominanceFrontier ( this ) }
20494}
0 commit comments