55import csharp
66import 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
7415private 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
986940private 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
1004963cached
@@ -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 }
0 commit comments