Skip to content

Commit 7c9a606

Browse files
committed
C#: Get rid of ReadKind
1 parent 6ffeaf8 commit 7c9a606

File tree

3 files changed

+57
-100
lines changed

3 files changed

+57
-100
lines changed

csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,9 @@ module Ssa {
235235
final AssignableRead getAReadAtNode(ControlFlow::Node cfn) {
236236
exists(SourceVariable v, ControlFlow::BasicBlock bb, int i |
237237
SsaImpl::ssaDefReachesRead(v, this, bb, i) and
238+
SsaImpl::variableReadActual(bb, i, v) and
238239
cfn = bb.getNode(i) and
239-
cfn = result.getAControlFlowNode() and
240-
result = v.getAnAccess().(AssignableRead)
240+
result.getAControlFlowNode() = cfn
241241
)
242242
}
243243

csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll

Lines changed: 54 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,11 @@
55
import csharp
66
import SsaImplCommon
77

8-
/** A classification of variable reads. */
9-
private newtype TReadKind =
10-
/** An actual read. */
11-
ActualRead() or
12-
/**
13-
* A pseudo read for a `ref` or `out` variable at the end of the variable's enclosing
14-
* callable. A pseudo read is inserted to make assignments to `out`/`ref` variables
15-
* live, for example line 1 in
16-
*
17-
* ```csharp
18-
* void M(out int i) {
19-
* i = 0;
20-
* }
21-
* ```
22-
*/
23-
OutRefExitRead() or
24-
/**
25-
* A pseudo read for a captured variable at the end of the capturing
26-
* callable. A write to a captured variable needs to be live for the same reasons
27-
* as a write to a `ref` or `out` variable (see above).
28-
*/
29-
CapturedVarExitRead() or
30-
/**
31-
* A pseudo read for a captured variable via a call.
32-
*/
33-
CapturedVarCallRead() or
34-
/**
35-
* A pseudo read for a `ref` variable, just prior to an update of the referenced value.
36-
* A pseudo read is inserted to make assignments to the `ref` variable live, for example
37-
* line 2 in
38-
*
39-
* ```csharp
40-
* void M() {
41-
* ref int i = ref GetRef();
42-
* i = 0;
43-
* }
44-
* ```
45-
*
46-
* The pseudo read is inserted at the CFG node `i` on the left-hand side of the
47-
* assignment on line 3.
48-
*/
49-
RefReadBeforeWrite()
50-
51-
/** A classification of variable reads. */
52-
private class ReadKind extends TReadKind {
53-
string toString() {
54-
this = ActualRead() and
55-
result = "ActualRead"
56-
or
57-
this = OutRefExitRead() and
58-
result = "OutRefExitRead"
59-
or
60-
this = CapturedVarExitRead() and
61-
result = "CapturedVarExitRead"
62-
or
63-
this = CapturedVarCallRead() and
64-
result = "CapturedVarCallRead"
65-
or
66-
this = RefReadBeforeWrite() and
67-
result = "RefReadBeforeWrite"
68-
}
69-
70-
/** Holds if this kind represents a pseudo read. */
71-
predicate isPseudo() { this != ActualRead() }
8+
/**
9+
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
10+
*/
11+
predicate variableReadActual(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) {
12+
v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement()
7213
}
7314

7415
private module SourceVariableImpl {
@@ -183,22 +124,16 @@ private module SourceVariableImpl {
183124
}
184125

185126
/**
186-
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
187-
* The read is of kind `rk`.
127+
* Holds if a pseudo read for `ref` or `out` variable `v` happens at index `i`
128+
* in basic block `bb`. A pseudo read is inserted to make assignments to
129+
* `out`/`ref` variables live, for example line 1 in
188130
*
189-
* This excludes implicit reads via calls.
131+
* ```csharp
132+
* void M(out int i) {
133+
* i = 0;
134+
* }
135+
* ```
190136
*/
191-
predicate variableReadDirect(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, ReadKind rk) {
192-
v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement() and
193-
rk = ActualRead()
194-
or
195-
outRefExitRead(bb, i, v) and
196-
rk = OutRefExitRead()
197-
or
198-
refReadBeforeWrite(bb, i, v) and
199-
rk = RefReadBeforeWrite()
200-
}
201-
202137
predicate outRefExitRead(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) {
203138
exists(ControlFlow::Nodes::AnnotatedExitNode exit |
204139
exit.isNormal() and
@@ -215,7 +150,23 @@ private module SourceVariableImpl {
215150
)
216151
}
217152

218-
private predicate refReadBeforeWrite(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) {
153+
/**
154+
* Holds if a pseudo read for `ref` variable `v` happens at index `i` in basic
155+
* block `bb`, just prior to an update of the referenced value. A pseudo read
156+
* is inserted to make assignments to the `ref` variable live, for example
157+
* line 2 in
158+
*
159+
* ```csharp
160+
* void M() {
161+
* ref int i = ref GetRef();
162+
* i = 0;
163+
* }
164+
* ```
165+
*
166+
* The pseudo read is inserted at the CFG node `i` on the left-hand side of the
167+
* assignment on line 3.
168+
*/
169+
predicate refReadBeforeWrite(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) {
219170
exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv |
220171
def.getTarget() = lv and
221172
lv.isRef() and
@@ -812,10 +763,13 @@ private module CapturedVariableLivenessImpl {
812763
*/
813764
private predicate capturerReads(Callable c, LocalScopeVariable v) {
814765
exists(LocalScopeSourceVariable sv |
815-
variableReadDirect(_, _, sv, _) and
816766
c = sv.getEnclosingCallable() and
817767
v = sv.getAssignable() and
818768
v.getCallable() != c
769+
|
770+
variableReadActual(_, _, sv)
771+
or
772+
refReadBeforeWrite(_, _, sv)
819773
)
820774
}
821775

@@ -985,20 +939,25 @@ private module CapturedVariableLivenessImpl {
985939

986940
private import CapturedVariableLivenessImpl
987941

942+
private predicate variableReadPseudo(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) {
943+
outRefExitRead(bb, i, v)
944+
or
945+
refReadBeforeWrite(bb, i, v)
946+
or
947+
capturedReadOut(bb, i, v, _, _, _)
948+
or
949+
capturedReadIn(bb, i, v, _, _, _)
950+
}
951+
988952
/**
989953
* Holds if the `i`th of basic block `bb` reads source variable `v`.
990-
* The read is of kind `rk`.
991954
*
992955
* This includes implicit reads via calls.
993956
*/
994-
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, ReadKind rk) {
995-
variableReadDirect(bb, i, v, rk)
996-
or
997-
capturedReadOut(bb, i, v, _, _, _) and
998-
rk = CapturedVarExitRead()
957+
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) {
958+
variableReadActual(bb, i, v)
999959
or
1000-
capturedReadIn(bb, i, v, _, _, _) and
1001-
rk = CapturedVarCallRead()
960+
variableReadPseudo(bb, i, v)
1002961
}
1003962

1004963
cached
@@ -1119,7 +1078,7 @@ private module Cached {
11191078
capturedReadIn(_, _, v, edef.getSourceVariable(), c, additionalCalls) and
11201079
def = def0.getAnUltimateDefinition() and
11211080
ssaDefReachesRead(_, def0, bb, i) and
1122-
variableRead(bb, i, v, CapturedVarCallRead()) and
1081+
capturedReadIn(bb, i, v, _, _, _) and
11231082
c = bb.getNode(i)
11241083
)
11251084
}
@@ -1150,7 +1109,7 @@ private module Cached {
11501109
or
11511110
exists(ControlFlow::BasicBlock bb3, int i3 |
11521111
adjacentDefReaches(def, bb1, i1, bb3, i3) and
1153-
variableRead(bb3, i3, _, any(ReadKind rk | rk.isPseudo())) and
1112+
variableReadPseudo(bb3, i3, _) and
11541113
adjacentDefRead(def, bb3, i3, bb2, i2)
11551114
)
11561115
}
@@ -1160,7 +1119,7 @@ private module Cached {
11601119
Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2
11611120
) {
11621121
adjacentDefReaches(def, bb1, i1, bb2, i2) and
1163-
variableRead(bb2, i2, _, ActualRead())
1122+
variableReadActual(bb2, i2, _)
11641123
}
11651124

11661125
/**
@@ -1185,7 +1144,7 @@ private module Cached {
11851144
predicate adjacentReadPairSameVar(Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2) {
11861145
exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 |
11871146
cfn1 = bb1.getNode(i1) and
1188-
variableRead(bb1, i1, _, ActualRead()) and
1147+
variableReadActual(bb1, i1, _) and
11891148
adjacentDefActualRead(def, bb1, i1, bb2, i2) and
11901149
cfn2 = bb2.getNode(i2)
11911150
)
@@ -1195,7 +1154,7 @@ private module Cached {
11951154
Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2
11961155
) {
11971156
adjacentDefReaches(def, bb1, i1, bb2, i2) and
1198-
variableRead(bb2, i2, _, any(ReadKind rk | rk.isPseudo()))
1157+
variableReadPseudo(bb2, i2, _)
11991158
}
12001159

12011160
private predicate reachesLastRefRedef(
@@ -1212,7 +1171,7 @@ private module Cached {
12121171
cached
12131172
predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) {
12141173
reachesLastRefRedef(def, bb, i, next) and
1215-
not variableRead(bb, i, def.getSourceVariable(), any(ReadKind rk | rk.isPseudo()))
1174+
not variableReadPseudo(bb, i, def.getSourceVariable())
12161175
}
12171176

12181177
private predicate reachesLastRef(Definition def, ControlFlow::BasicBlock bb, int i) {
@@ -1228,7 +1187,7 @@ private module Cached {
12281187
predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) {
12291188
exists(ControlFlow::BasicBlock bb, int i |
12301189
reachesLastRef(def, bb, i) and
1231-
variableRead(bb, i, _, ActualRead()) and
1190+
variableReadActual(bb, i, _) and
12321191
cfn = bb.getNode(i)
12331192
)
12341193
}

csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,4 @@ class SourceVariable = SsaImpl::TSourceVariable;
1616

1717
predicate variableWrite = SsaImpl::variableWrite/4;
1818

19-
predicate variableRead(BasicBlock bb, int i, SourceVariable v) {
20-
SsaImpl::variableRead(bb, i, v, _)
21-
}
19+
predicate variableRead = SsaImpl::variableRead/3;

0 commit comments

Comments
 (0)