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+ /** A delineated part of the AST with its own CFG. */
12+ class CfgScope = ControlFlow::Root;
13+
14+ /** The class of control flow nodes. */
15+ class Node = ControlFlowNode;
16+
17+ /** Gets the CFG scope in which this node occurs. */
18+ CfgScope nodeGetCfgScope(Node node) { node.getRoot() = result }
19+
20+ /** Gets an immediate successor of this node. */
21+ Node nodeGetASuccessor(Node node, SuccessorType t) {
22+ result = node.getASuccessor() and
23+ (
24+ not result instanceof ControlFlow::ConditionGuardNode and t instanceof DirectSuccessor
25+ or
26+ t.(BooleanSuccessor).getValue() = result.(ControlFlow::ConditionGuardNode).getOutcome()
27+ )
28+ }
729
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 {
3730 /**
38- * Holds if `succ` is a control flow successor of `nd` within the same basic block.
31+ * Holds if `node` represents an entry node to be used when calculating
32+ * dominance.
3933 */
40- private predicate intraBBSucc(ControlFlow::Node nd, ControlFlow::Node succ) {
41- succ = nd.getASuccessor() and
42- not startsBB(succ)
43- }
34+ predicate nodeIsDominanceEntry(Node node) { node instanceof EntryNode }
4435
4536 /**
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.
37+ * Holds if `node` represents an exit node to be used when calculating
38+ * post dominance.
5039 */
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- }
40+ predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
6441}
6542
66- private import Internal
43+ private module BbImpl = BB::Make<Location, Input>;
6744
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) }
45+ class BasicBlock extends BbImpl::BasicBlock {
46+ /** Gets an immediate successor of this basic block of a given type, if any. */
47+ BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
8648
8749 /** Gets a basic block succeeding this one. */
88- BasicBlock getASuccessor() { succBB(this, result) }
50+ BasicBlock getASuccessor() { result = this.getASuccessor(_ ) }
8951
9052 /** Gets a basic block preceding this one. */
9153 BasicBlock getAPredecessor() { result.getASuccessor() = this }
9254
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-
10855 /** Gets the basic block that immediately dominates this basic block. */
109- ReachableBasicBlock getImmediateDominator() { bbIDominates( result, this) }
56+ ReachableBasicBlock getImmediateDominator() { result.immediatelyDominates( this) }
11057
11158 /** 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- }
59+ ControlFlow::Root getRoot() { result = this.getScope() }
13460}
13561
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) }
62+ cached
63+ private predicate reachableBB(BasicBlock bb) {
64+ bb instanceof BbImpl::EntryBasicBlock
65+ or
66+ exists(BasicBlock predBB | predBB.getASuccessor() = bb | reachableBB(predBB))
14167}
14268
14369/**
14470 * A basic block that is reachable from an entry basic block.
14571 */
14672class ReachableBasicBlock extends BasicBlock {
14773 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- }
18074}
18175
18276/**
@@ -193,12 +87,5 @@ class ReachableJoinBlock extends ReachableBasicBlock {
19387 * who in turn attribute it to Ferrante et al., "The program dependence graph and
19488 * its use in optimization".
19589 */
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- }
90+ predicate inDominanceFrontierOf(ReachableBasicBlock b) { b.inDominanceFrontier(this) }
20491}
0 commit comments