Skip to content

Commit 643efb3

Browse files
committed
Swift: Adapt to parameterized SSA implementation
1 parent 61b6764 commit 643efb3

File tree

3 files changed

+103
-97
lines changed

3 files changed

+103
-97
lines changed

swift/ql/lib/codeql/swift/dataflow/Ssa.qll

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,131 @@ cached
22
module Ssa {
33
private import swift
44
private import internal.SsaImplCommon as SsaImplCommon
5-
private import internal.SsaImplSpecific as SsaImplSpecific
65
private import codeql.swift.controlflow.CfgNodes
76
private import codeql.swift.controlflow.ControlFlowGraph
8-
private import codeql.swift.controlflow.BasicBlocks
7+
private import codeql.swift.controlflow.BasicBlocks as BasicBlocks
8+
9+
private module SsaInput implements SsaImplCommon::InputSig {
10+
private import internal.DataFlowPrivate
11+
private import codeql.swift.controlflow.ControlFlowGraph
12+
private import codeql.swift.controlflow.CfgNodes
13+
14+
class BasicBlock = BasicBlocks::BasicBlock;
15+
16+
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
17+
result = bb.getImmediateDominator()
18+
}
19+
20+
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
21+
22+
class ExitBasicBlock = BasicBlocks::ExitBasicBlock;
23+
24+
class SourceVariable = VarDecl;
25+
26+
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
27+
exists(AssignExpr assign |
28+
bb.getNode(i).getNode().asAstNode() = assign and
29+
assign.getDest() = v.getAnAccess() and
30+
certain = true
31+
)
32+
or
33+
exists(PatternBindingDecl decl, Pattern pattern |
34+
bb.getNode(i).getNode().asAstNode() = pattern and
35+
decl.getAPattern() = pattern and
36+
v.getParentPattern() = pattern and
37+
certain = true
38+
)
39+
or
40+
v instanceof ParamDecl and
41+
bb.getNode(i).getNode().asAstNode() = v and
42+
certain = true
43+
or
44+
// Mark the subexpression as a write of the local variable declared in the `TapExpr`.
45+
exists(TapExpr tap |
46+
v = tap.getVar() and
47+
bb.getNode(i).getNode().asAstNode() = tap.getSubExpr() and
48+
certain = true
49+
)
50+
}
51+
52+
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
53+
exists(DeclRefExpr ref |
54+
not isLValue(ref) and
55+
bb.getNode(i).getNode().asAstNode() = ref and
56+
v = ref.getDecl() and
57+
certain = true
58+
)
59+
or
60+
exists(InOutExpr expr |
61+
bb.getNode(i).getNode().asAstNode() = expr and
62+
expr.getSubExpr() = v.getAnAccess() and
63+
certain = true
64+
)
65+
or
66+
exists(ExitNode exit, AbstractFunctionDecl func |
67+
func.getAParam() = v or func.getSelfParam() = v
68+
|
69+
bb.getNode(i) = exit and
70+
modifiableParam(v) and
71+
bb.getScope() = func and
72+
certain = true
73+
)
74+
or
75+
// Mark the `TapExpr` as a read of the of the local variable.
76+
exists(TapExpr tap |
77+
v = tap.getVar() and
78+
bb.getNode(i).getNode().asAstNode() = tap and
79+
certain = true
80+
)
81+
}
82+
}
83+
84+
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
985

1086
cached
11-
class Definition extends SsaImplCommon::Definition {
87+
class Definition extends SsaImpl::Definition {
1288
cached
1389
Location getLocation() { none() }
1490

1591
cached
1692
ControlFlowNode getARead() {
17-
exists(VarDecl v, BasicBlock bb, int i |
18-
SsaImplCommon::ssaDefReachesRead(v, this, bb, i) and
19-
SsaImplSpecific::variableRead(bb, i, v, true) and
93+
exists(VarDecl v, SsaInput::BasicBlock bb, int i |
94+
SsaImpl::ssaDefReachesRead(v, this, bb, i) and
95+
SsaInput::variableRead(bb, i, v, true) and
2096
result = bb.getNode(i)
2197
)
2298
}
2399

24100
cached
25101
ControlFlowNode getAFirstRead() {
26-
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
102+
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
27103
this.definesAt(_, bb1, i1) and
28-
SsaImplCommon::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
104+
SsaImpl::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
29105
result = bb2.getNode(i2)
30106
)
31107
}
32108

33109
cached
34110
predicate adjacentReadPair(ControlFlowNode read1, ControlFlowNode read2) {
35-
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
111+
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
36112
read1 = bb1.getNode(i1) and
37-
SsaImplSpecific::variableRead(bb1, i1, _, true) and
38-
SsaImplCommon::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
113+
SsaInput::variableRead(bb1, i1, _, true) and
114+
SsaImpl::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
39115
read2 = bb2.getNode(i2)
40116
)
41117
}
42118

43119
cached
44-
predicate lastRefRedef(BasicBlock bb, int i, Definition next) {
45-
SsaImplCommon::lastRefRedef(this, bb, i, next)
120+
predicate lastRefRedef(SsaInput::BasicBlock bb, int i, Definition next) {
121+
SsaImpl::lastRefRedef(this, bb, i, next)
46122
}
47123
}
48124

49125
cached
50-
class WriteDefinition extends Definition, SsaImplCommon::WriteDefinition {
126+
class WriteDefinition extends Definition, SsaImpl::WriteDefinition {
51127
cached
52128
override Location getLocation() {
53-
exists(BasicBlock bb, int i |
129+
exists(SsaInput::BasicBlock bb, int i |
54130
this.definesAt(_, bb, i) and
55131
result = bb.getNode(i).getLocation()
56132
)
@@ -63,14 +139,16 @@ module Ssa {
63139
cached
64140
predicate assigns(CfgNode value) {
65141
exists(
66-
AssignExpr a, BasicBlock bb, int i // TODO: use CFG node for assignment expr
142+
AssignExpr a, SsaInput::BasicBlock bb, int i // TODO: use CFG node for assignment expr
67143
|
68144
this.definesAt(_, bb, i) and
69145
a = bb.getNode(i).getNode().asAstNode() and
70146
value.getNode().asAstNode() = a.getSource()
71147
)
72148
or
73-
exists(VarDecl var, BasicBlock bb, int blockIndex, PatternBindingDecl pbd, Expr init |
149+
exists(
150+
VarDecl var, SsaInput::BasicBlock bb, int blockIndex, PatternBindingDecl pbd, Expr init
151+
|
74152
this.definesAt(var, bb, blockIndex) and
75153
pbd.getAPattern() = bb.getNode(blockIndex).getNode().asAstNode() and
76154
init = var.getParentInitializer()
@@ -84,17 +162,19 @@ module Ssa {
84162
}
85163

86164
cached
87-
class PhiDefinition extends Definition, SsaImplCommon::PhiNode {
165+
class PhiDefinition extends Definition, SsaImpl::PhiNode {
88166
cached
89167
override Location getLocation() {
90-
exists(BasicBlock bb, int i |
168+
exists(SsaInput::BasicBlock bb, int i |
91169
this.definesAt(_, bb, i) and
92170
result = bb.getLocation()
93171
)
94172
}
95173

96174
cached
97-
Definition getPhiInput(BasicBlock bb) { SsaImplCommon::phiHasInputFromBlock(this, result, bb) }
175+
Definition getPhiInput(SsaInput::BasicBlock bb) {
176+
SsaImpl::phiHasInputFromBlock(this, result, bb)
177+
}
98178

99179
cached
100180
Definition getAPhiInput() { result = this.getPhiInput(_) }

swift/ql/lib/codeql/swift/dataflow/internal/SsaImplCommon.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
/** Provides the input specification of the SSA implementation. */
7-
signature module SsaInputSig {
7+
signature module InputSig {
88
/**
99
* A basic block, that is, a maximal straight-line sequence of control flow nodes
1010
* without branches or joins.
@@ -28,7 +28,7 @@ signature module SsaInputSig {
2828
* ```
2929
*
3030
* The basic block starting on line 2 is an immediate dominator of
31-
* the basic block online 4 (all paths from the entry point of `M`
31+
* the basic block on line 4 (all paths from the entry point of `M`
3232
* to `return s.Length;` must go through the null check.
3333
*/
3434
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb);
@@ -82,7 +82,7 @@ signature module SsaInputSig {
8282
* NB: If this predicate is exposed, it should be cached.
8383
* ```
8484
*/
85-
module Make<SsaInputSig Input> {
85+
module Make<InputSig Input> {
8686
private import Input
8787

8888
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) {

swift/ql/lib/codeql/swift/dataflow/internal/SsaImplSpecific.qll

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)