Skip to content

Commit d55c6d2

Browse files
committed
Use shared basic blocks library
1 parent 8a59b16 commit d55c6d2

File tree

2 files changed

+46
-154
lines changed

2 files changed

+46
-154
lines changed

go/ql/lib/semmle/go/controlflow/BasicBlocks.qll

Lines changed: 44 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -4,179 +4,76 @@
44

55
import go
66
private 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
*/
14675
class 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
}

go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,4 +352,6 @@ module ControlFlow {
352352
}
353353
}
354354

355+
class ControlFlowNode = ControlFlow::Node;
356+
355357
class Write = ControlFlow::WriteNode;

0 commit comments

Comments
 (0)