Skip to content

Commit 4d05b6a

Browse files
committed
Shared: Address review comments for shared basic block library
1 parent 8b20b0d commit 4d05b6a

File tree

7 files changed

+96
-85
lines changed

7 files changed

+96
-85
lines changed

csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ private module CfgInput implements CfgShared::InputSig<Location> {
9696
t instanceof ST::SuccessorTypes::ExitSuccessor
9797
}
9898

99-
predicate idOfAstNode(AstNode node, int id) { node.getId() = id }
99+
int idOfAstNode(AstNode node) { result = node.getId() }
100100

101-
predicate idOfCfgScope(CfgScope node, int id) { idOfAstNode(node, id) }
101+
int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) }
102102
}
103103

104104
private module CfgSplittingInput implements CfgShared::SplittingInputSig<Location, CfgInput> {

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ private import codeql.ruby.AST
44
private import codeql.ruby.ast.internal.AST
55
private import codeql.ruby.ast.internal.TreeSitter
66
private import codeql.ruby.controlflow.ControlFlowGraph
7-
private import codeql.ruby.controlflow.ControlFlowGraph as Cfg
87
private import internal.ControlFlowGraphImpl as CfgImpl
98
private import CfgNodes
109
private import SuccessorTypes
11-
private import codeql.controlflow.BasicBlock as BB
1210
private import CfgImpl::BasicBlocks as BasicBlocksImpl
1311

1412
/**

ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ private module CfgInput implements CfgShared::InputSig<Location> {
6565

6666
private predicate idOf(Ruby::AstNode node, int id) = equivalenceRelation(id/2)(node, id)
6767

68-
predicate idOfAstNode(AstNode node, int id) { idOf(AstInternal::toGeneratedInclSynth(node), id) }
68+
int idOfAstNode(AstNode node) { idOf(AstInternal::toGeneratedInclSynth(node), result) }
6969

70-
predicate idOfCfgScope(CfgScope node, int id) { idOfAstNode(node, id) }
70+
int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) }
7171
}
7272

7373
private module CfgSplittingInput implements CfgShared::SplittingInputSig<Location, CfgInput> {

rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,9 @@ private module CfgInput implements InputSig<Location> {
5656
private predicate idOfDbAstNode(Raw::AstNode x, int y) = equivalenceRelation(id/2)(x, y)
5757

5858
// TODO: does not work if fresh ipa entities (`ipa: on:`) turn out to be first of the block
59-
predicate idOfAstNode(AstNode node, int id) {
60-
idOfDbAstNode(Synth::convertAstNodeToRaw(node), id)
61-
}
59+
int idOfAstNode(AstNode node) { idOfDbAstNode(Synth::convertAstNodeToRaw(node), result) }
6260

63-
predicate idOfCfgScope(CfgScope node, int id) { idOfAstNode(node, id) }
61+
int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) }
6462
}
6563

6664
private module CfgSplittingInput implements SplittingInputSig<Location, CfgInput> {

shared/controlflow/codeql/controlflow/BasicBlock.qll

Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
/**
2-
* This modules provides an implementation of a basic block class based based
3-
* on a control flow graph implementation.
2+
* This modules provides an implementation of a basic block class based on a
3+
* control flow graph implementation.
44
*
55
* INTERNAL use only. This is an experimental API subject to change without
66
* notice.
77
*/
88

9+
private import codeql.util.Location
10+
911
/** Provides the language-specific input specification. */
10-
signature module InputSig {
12+
signature module InputSig<LocationSig Location> {
1113
class SuccessorType;
1214

1315
/** Hold if `t` represents a conditional successor type. */
@@ -16,21 +18,31 @@ signature module InputSig {
1618
/** The class of control flow nodes. */
1719
class Node {
1820
string toString();
21+
22+
/** Gets the location of this control flow node. */
23+
Location getLocation();
1924
}
2025

26+
/** Gets an immediate successor of this node. */
2127
Node nodeGetASuccessor(Node node, SuccessorType t);
2228

23-
/** Holds if `node` is the beginning of an entry basic block. */
24-
predicate nodeIsEntry(Node node);
29+
/**
30+
* Holds if `node` represents an entry node to be used when calculating
31+
* dominance.
32+
*/
33+
predicate nodeIsDominanceEntry(Node node);
2534

26-
/** Holds if `node` is the beginning of an entry basic block. */
27-
predicate nodeIsExit(Node node);
35+
/**
36+
* Holds if `node` represents an exit node to be used when calculating
37+
* post dominance.
38+
*/
39+
predicate nodeIsPostDominanceExit(Node node);
2840
}
2941

3042
/**
3143
* Provides a basic block construction on top of a control flow graph.
3244
*/
33-
module Make<InputSig Input> {
45+
module Make<LocationSig Location, InputSig<Location> Input> {
3446
private import Input
3547

3648
final class BasicBlock = BasicBlockImpl;
@@ -42,13 +54,17 @@ module Make<InputSig Input> {
4254
/** Holds if this node has more than one predecessor. */
4355
private predicate nodeIsJoin(Node node) { strictcount(nodeGetAPredecessor(node, _)) > 1 }
4456

57+
/** Holds if this node has more than one successor. */
4558
private predicate nodeIsBranch(Node node) { strictcount(nodeGetASuccessor(node, _)) > 1 }
4659

4760
/**
4861
* A basic block, that is, a maximal straight-line sequence of control flow nodes
4962
* without branches or joins.
5063
*/
5164
private class BasicBlockImpl extends TBasicBlockStart {
65+
/** Gets the location of this basic block. */
66+
Location getLocation() { result = this.getFirstNode().getLocation() }
67+
5268
/** Gets an immediate successor of this basic block, if any. */
5369
BasicBlock getASuccessor() { result = this.getASuccessor(_) }
5470

@@ -64,6 +80,7 @@ module Make<InputSig Input> {
6480
BasicBlock getAPredecessor(SuccessorType t) { result.getASuccessor(t) = this }
6581

6682
/** Gets the control flow node at a specific (zero-indexed) position in this basic block. */
83+
cached
6784
Node getNode(int pos) { bbIndex(this.getFirstNode(), result, pos) }
6885

6986
/** Gets a control flow node in this basic block. */
@@ -166,52 +183,6 @@ module Make<InputSig Input> {
166183
cached
167184
newtype TBasicBlock = TBasicBlockStart(Node cfn) { startsBB(cfn) }
168185

169-
/** Holds if `cfn` starts a new basic block. */
170-
private predicate startsBB(Node cfn) {
171-
not exists(nodeGetAPredecessor(cfn, _)) and exists(nodeGetASuccessor(cfn, _))
172-
or
173-
nodeIsJoin(cfn)
174-
or
175-
nodeIsBranch(nodeGetAPredecessor(cfn, _))
176-
or
177-
// In cases such as
178-
//
179-
// ```rb
180-
// if x or y
181-
// foo
182-
// else
183-
// bar
184-
// ```
185-
//
186-
// we have a CFG that looks like
187-
//
188-
// x --false--> [false] x or y --false--> bar
189-
// \ |
190-
// --true--> y --false--
191-
// \
192-
// --true--> [true] x or y --true--> foo
193-
//
194-
// and we want to ensure that both `foo` and `bar` start a new basic block.
195-
exists(nodeGetAPredecessor(cfn, any(SuccessorType s | successorTypeIsCondition(s))))
196-
}
197-
198-
/**
199-
* Holds if `succ` is a control flow successor of `pred` within
200-
* the same basic block.
201-
*/
202-
private predicate intraBBSucc(Node pred, Node succ) {
203-
succ = nodeGetASuccessor(pred, _) and
204-
not startsBB(succ)
205-
}
206-
207-
/**
208-
* Holds if `bbStart` is the first node in a basic block and `cfn` is the
209-
* `i`th node in the same basic block.
210-
*/
211-
cached
212-
predicate bbIndex(Node bbStart, Node cfn, int i) =
213-
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
214-
215186
/**
216187
* Holds if the first node of basic block `succ` is a control flow
217188
* successor of the last node of basic block `pred`.
@@ -227,7 +198,7 @@ module Make<InputSig Input> {
227198
private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
228199

229200
/** Holds if `bb` is an exit basic block that represents normal exit. */
230-
private predicate exitBB(BasicBlock bb) { nodeIsExit(bb.getANode()) }
201+
private predicate exitBB(BasicBlock bb) { nodeIsPostDominanceExit(bb.getANode()) }
231202

232203
/** Holds if `dom` is an immediate post-dominator of `bb`. */
233204
cached
@@ -237,6 +208,51 @@ module Make<InputSig Input> {
237208

238209
private import Cached
239210

211+
/** Holds if `cfn` starts a new basic block. */
212+
private predicate startsBB(Node cfn) {
213+
not exists(nodeGetAPredecessor(cfn, _)) and exists(nodeGetASuccessor(cfn, _))
214+
or
215+
nodeIsJoin(cfn)
216+
or
217+
nodeIsBranch(nodeGetAPredecessor(cfn, _))
218+
or
219+
// In cases such as
220+
//
221+
// ```rb
222+
// if x or y
223+
// foo
224+
// else
225+
// bar
226+
// ```
227+
//
228+
// we have a CFG that looks like
229+
//
230+
// x --false--> [false] x or y --false--> bar
231+
// \ |
232+
// --true--> y --false--
233+
// \
234+
// --true--> [true] x or y --true--> foo
235+
//
236+
// and we want to ensure that both `foo` and `bar` start a new basic block.
237+
exists(nodeGetAPredecessor(cfn, any(SuccessorType s | successorTypeIsCondition(s))))
238+
}
239+
240+
/**
241+
* Holds if `succ` is a control flow successor of `pred` within
242+
* the same basic block.
243+
*/
244+
predicate intraBBSucc(Node pred, Node succ) {
245+
succ = nodeGetASuccessor(pred, _) and
246+
not startsBB(succ)
247+
}
248+
249+
/**
250+
* Holds if `bbStart` is the first node in a basic block and `cfn` is the
251+
* `i`th node in the same basic block.
252+
*/
253+
private predicate bbIndex(Node bbStart, Node cfn, int i) =
254+
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
255+
240256
/** Holds if `bb` is an entry basic block. */
241-
private predicate entryBB(BasicBlock bb) { nodeIsEntry(bb.getFirstNode()) }
257+
private predicate entryBB(BasicBlock bb) { nodeIsDominanceEntry(bb.getFirstNode()) }
242258
}

shared/controlflow/codeql/controlflow/Cfg.qll

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ signature module InputSig<LocationSig Location> {
8383
* basic block.
8484
*/
8585
bindingset[node]
86-
default predicate idOfAstNode(AstNode node, int id) { none() }
86+
int idOfAstNode(AstNode node);
8787

8888
/**
8989
* Gets an `id` of `scope`. This is used to order the predecessors of a join
9090
* basic block.
9191
*/
9292
bindingset[scope]
93-
default predicate idOfCfgScope(CfgScope scope, int id) { none() }
93+
int idOfCfgScope(CfgScope scope);
9494
}
9595

9696
/** Provides input needed for CFG splitting. */
@@ -1537,7 +1537,7 @@ module MakeWithSplitting<
15371537

15381538
private class NodeAlias = Node;
15391539

1540-
private module BasicBlockInputSig implements BB::InputSig {
1540+
private module BasicBlockInputSig implements BB::InputSig<Location> {
15411541
class SuccessorType = Input::SuccessorType;
15421542

15431543
predicate successorTypeIsCondition = Input::successorTypeIsCondition/1;
@@ -1546,30 +1546,26 @@ module MakeWithSplitting<
15461546

15471547
Node nodeGetASuccessor(Node node, SuccessorType t) { result = node.getASuccessor(t) }
15481548

1549-
predicate nodeIsEntry(Node node) { node instanceof EntryNode }
1549+
predicate nodeIsDominanceEntry(Node node) { node instanceof EntryNode }
15501550

1551-
predicate nodeIsExit(Node node) { node.(AnnotatedExitNode).isNormal() }
1551+
predicate nodeIsPostDominanceExit(Node node) { node.(AnnotatedExitNode).isNormal() }
15521552
}
15531553

1554-
private module BasicBlockImpl = BB::Make<BasicBlockInputSig>;
1554+
private module BasicBlockImpl = BB::Make<Location, BasicBlockInputSig>;
15551555

15561556
/**
15571557
* A basic block, that is, a maximal straight-line sequence of control flow nodes
15581558
* without branches or joins.
15591559
*/
15601560
final class BasicBlock extends BasicBlockImpl::BasicBlock {
1561-
// We extend `BasicBlockImpl::BasicBlock` to add the `getScope` and
1562-
// `getLocation`.
1561+
// We extend `BasicBlockImpl::BasicBlock` to add the `getScope`.
15631562
/** Gets the scope of this basic block. */
15641563
CfgScope getScope() {
15651564
if this instanceof EntryBasicBlock
15661565
then result = this.getFirstNode().getScope()
15671566
else result = this.getAPredecessor().getScope()
15681567
}
15691568

1570-
/** Gets the location of this basic block. */
1571-
Location getLocation() { result = this.getFirstNode().getLocation() }
1572-
15731569
/** Gets an immediate successor of this basic block, if any. */
15741570
BasicBlock getASuccessor() { result = super.getASuccessor() }
15751571

@@ -1678,10 +1674,13 @@ module MakeWithSplitting<
16781674
}
16791675

16801676
private module JoinBlockPredecessors {
1681-
int getId(JoinPredecessorBasicBlock jbp) {
1682-
idOfAstNode(jbp.getFirstNode().(AstCfgNode).getAstNode(), result)
1677+
predicate hasIdAndKind(JoinPredecessorBasicBlock jbp, int id, int kind) {
1678+
id = idOfCfgScope(jbp.(EntryBasicBlock).getScope()) and
1679+
kind = 0
16831680
or
1684-
idOfCfgScope(jbp.(EntryBasicBlock).getScope(), result)
1681+
not jbp instanceof EntryBasicBlock and
1682+
id = idOfAstNode(jbp.getFirstNode().(AstCfgNode).getAstNode()) and
1683+
kind = 1
16851684
}
16861685

16871686
string getSplitString(JoinPredecessorBasicBlock jbp) {
@@ -1699,10 +1698,10 @@ module MakeWithSplitting<
16991698
cached
17001699
JoinPredecessorBasicBlock getJoinBlockPredecessor(JoinBasicBlock jb, int i) {
17011700
result =
1702-
rank[i + 1](JoinPredecessorBasicBlock jbp |
1703-
jbp = jb.getAPredecessor()
1701+
rank[i + 1](JoinPredecessorBasicBlock jbp, int id, int kind |
1702+
jbp = jb.getAPredecessor() and JoinBlockPredecessors::hasIdAndKind(jbp, id, kind)
17041703
|
1705-
jbp order by JoinBlockPredecessors::getId(jbp), JoinBlockPredecessors::getSplitString(jbp)
1704+
jbp order by id, kind, JoinBlockPredecessors::getSplitString(jbp)
17061705
)
17071706
}
17081707

swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplSpecific.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ module CfgInput implements InputSig<Location> {
106106
result = n.(FuncDeclElement).getAst()
107107
}
108108

109-
predicate idOfAstNode(AstNode node, int id) { idOf(projectToAst(node), id) }
109+
int idOfAstNode(AstNode node) { idOf(projectToAst(node), result) }
110110

111-
predicate idOfCfgScope(CfgScope node, int id) { idOf(node, id) }
111+
int idOfCfgScope(CfgScope node) { idOf(node, result) }
112112
}
113113

114114
private module CfgSplittingInput implements SplittingInputSig<Location, CfgInput> {

0 commit comments

Comments
 (0)