@@ -14,15 +14,15 @@ private class GvnKindExpr extends GvnKind, TGvnKindExpr {
14
14
15
15
GvnKindExpr ( ) { this = TGvnKindExpr ( kind ) }
16
16
17
- override string toString ( ) { result = "Expr(" + kind . toString ( ) + ")" }
17
+ override string toString ( ) { result = "Expr(" + kind + ")" }
18
18
}
19
19
20
20
private class GvnKindStmt extends GvnKind , TGvnKindStmt {
21
21
private int kind ;
22
22
23
23
GvnKindStmt ( ) { this = TGvnKindStmt ( kind ) }
24
24
25
- override string toString ( ) { result = "Stmt(" + kind . toString ( ) + ")" }
25
+ override string toString ( ) { result = "Stmt(" + kind + ")" }
26
26
}
27
27
28
28
private class GvnKindDeclaration extends GvnKind , TGvnKindDeclaration {
@@ -32,9 +32,7 @@ private class GvnKindDeclaration extends GvnKind, TGvnKindDeclaration {
32
32
33
33
GvnKindDeclaration ( ) { this = TGvnKindDeclaration ( kind , isTargetThis , d ) }
34
34
35
- override string toString ( ) {
36
- result = "Expr(" + kind .toString ( ) + ")," + isTargetThis + "," + d .toString ( )
37
- }
35
+ override string toString ( ) { result = "Expr(" + kind + ")," + isTargetThis + "," + d }
38
36
}
39
37
40
38
/** Gets the declaration referenced by the expression `e`, if any. */
@@ -46,62 +44,56 @@ private Declaration referenceAttribute(Expr e) {
46
44
result = e .( Access ) .getTarget ( )
47
45
}
48
46
49
- /** Returns true iff the target of the expression `e` is `this`. */
47
+ /** Gets a Boolean indicating whether the target of the expression `e` is `this`. */
50
48
private boolean isTargetThis ( Expr e ) {
51
49
result = true and e .( MemberAccess ) .targetIsThisInstance ( )
52
50
or
53
51
result = false and not e .( MemberAccess ) .targetIsThisInstance ( )
54
52
}
55
53
56
- /** Gets the AST node kind of element `cfe` wrapped in the `GvnKind` type. */
57
- private GvnKind getKind ( ControlFlowElement cfe ) {
58
- exists ( int kind |
59
- expressions ( cfe , kind , _) and
60
- result = TGvnKindExpr ( kind )
61
- or
62
- statements ( cfe , kind ) and
63
- result = TGvnKindStmt ( kind )
64
- )
65
- }
66
-
67
- /** The global value number of a control flow element. */
68
- abstract class Gvn extends TGvn {
54
+ /**
55
+ * A global value number (GVN) for a control flow element.
56
+ *
57
+ * GVNs are used to map control flow elements to a representation that
58
+ * omits location information, that is, two elements that are structurally
59
+ * equal will be mapped to the same GVN.
60
+ */
61
+ class Gvn extends TGvn {
69
62
/** Gets the string representation of this global value number. */
70
- abstract string toString ( ) ;
63
+ string toString ( ) { none ( ) }
71
64
}
72
65
73
66
private class ConstantGvn extends Gvn , TConstantGvn {
74
67
override string toString ( ) { this = TConstantGvn ( result ) }
75
68
}
76
69
77
- private class GvnBase extends Gvn , TGvnBase {
70
+ private class GvnNil extends Gvn , TGvnNil {
78
71
private GvnKind kind ;
79
72
80
- GvnBase ( ) { this = TGvnBase ( kind ) }
73
+ GvnNil ( ) { this = TGvnNil ( kind ) }
81
74
82
75
override string toString ( ) { result = "(kind:" + kind + ")" }
83
76
}
84
77
85
- private class GvnStruct extends Gvn , TGvnStruct {
78
+ private class GvnCons extends Gvn , TGvnCons {
86
79
private Gvn head ;
87
80
private Gvn tail ;
88
81
89
- GvnStruct ( ) { this = TGvnStruct ( head , tail ) }
82
+ GvnCons ( ) { this = TGvnCons ( head , tail ) }
90
83
91
- override string toString ( ) { result = "(" + head . toString ( ) + " :: " + tail . toString ( ) + ")" }
84
+ override string toString ( ) { result = "(" + head + " :: " + tail + ")" }
92
85
}
93
86
94
87
pragma [ noinline]
95
- private predicate gvnKindDeclaration (
96
- ControlFlowElement cfe , int kind , boolean isTargetThis , Declaration d
97
- ) {
98
- isTargetThis = isTargetThis ( cfe ) and
99
- d = referenceAttribute ( cfe ) and
100
- expressions ( cfe , kind , _)
88
+ private predicate gvnKindDeclaration ( Expr e , int kind , boolean isTargetThis , Declaration d ) {
89
+ isTargetThis = isTargetThis ( e ) and
90
+ d = referenceAttribute ( e ) and
91
+ expressions ( e , kind , _)
101
92
}
102
93
103
94
/**
104
95
* Gets the `GvnKind` of the element `cfe`.
96
+ *
105
97
* In case `cfe` is a reference attribute, we encode the entire declaration and whether
106
98
* the target is semantically equivalent to `this`.
107
99
*/
@@ -111,18 +103,24 @@ private GvnKind getGvnKind(ControlFlowElement cfe) {
111
103
result = TGvnKindDeclaration ( kind , isTargetThis , d )
112
104
)
113
105
or
114
- not exists ( referenceAttribute ( cfe ) ) and
115
- result = getKind ( cfe )
106
+ exists ( int kind |
107
+ not exists ( referenceAttribute ( cfe ) ) and
108
+ expressions ( cfe , kind , _) and
109
+ result = TGvnKindExpr ( kind )
110
+ or
111
+ statements ( cfe , kind ) and
112
+ result = TGvnKindStmt ( kind )
113
+ )
116
114
}
117
115
118
- private Gvn gvnConstructed ( ControlFlowElement cfe , GvnKind kind , int index ) {
116
+ private Gvn toGvn ( ControlFlowElement cfe , GvnKind kind , int index ) {
119
117
kind = getGvnKind ( cfe ) and
120
- result = TGvnBase ( kind ) and
118
+ result = TGvnNil ( kind ) and
121
119
index = - 1
122
120
or
123
121
exists ( Gvn head , Gvn tail |
124
- gvnConstructedStruct ( cfe , kind , index , head , tail ) and
125
- result = TGvnStruct ( head , tail )
122
+ toGvnCons ( cfe , kind , index , head , tail ) and
123
+ result = TGvnCons ( head , tail )
126
124
)
127
125
}
128
126
@@ -147,16 +145,14 @@ private ControlFlowElement getRankedChild(ControlFlowElement cfe, int rnk) {
147
145
}
148
146
149
147
pragma [ noinline]
150
- private Gvn gvnChild ( ControlFlowElement cfe , int index ) {
148
+ private Gvn toGvnChild ( ControlFlowElement cfe , int index ) {
151
149
result = toGvn ( getRankedChild ( cfe , index ) )
152
150
}
153
151
154
152
pragma [ noinline]
155
- private predicate gvnConstructedStruct (
156
- ControlFlowElement cfe , GvnKind kind , int index , Gvn head , Gvn tail
157
- ) {
158
- tail = gvnConstructed ( cfe , kind , index - 1 ) and
159
- head = gvnChild ( cfe , index )
153
+ private predicate toGvnCons ( ControlFlowElement cfe , GvnKind kind , int index , Gvn head , Gvn tail ) {
154
+ tail = toGvn ( cfe , kind , index - 1 ) and
155
+ head = toGvnChild ( cfe , index )
160
156
}
161
157
162
158
cached
@@ -171,30 +167,33 @@ private module Cached {
171
167
)
172
168
}
173
169
174
- /**
175
- * Type for containing the global value number of a control flow element.
176
- * A global value number, can either be a constant, a kind or a structure containing multiple global value numbers.
177
- * The construction of the type produces a list like structure.
178
- */
179
170
cached
180
171
newtype TGvn =
181
172
TConstantGvn ( string s ) { s = any ( Expr e ) .getValue ( ) } or
182
- TGvnBase ( GvnKind gkind ) or
183
- TGvnStruct ( Gvn head , Gvn tail ) { gvnConstructedStruct ( _, _, _, head , tail ) }
173
+ TGvnNil ( GvnKind gkind ) or
174
+ TGvnCons ( Gvn head , Gvn tail ) { toGvnCons ( _, _, _, head , tail ) }
175
+
176
+ /** Gets the global value number of the element `cfe`. */
177
+ cached
178
+ Gvn toGvnCached ( ControlFlowElement cfe ) {
179
+ result = TConstantGvn ( cfe .( Expr ) .getValue ( ) )
180
+ or
181
+ not exists ( cfe .( Expr ) .getValue ( ) ) and
182
+ exists ( GvnKind kind , int index |
183
+ result = toGvn ( cfe , kind , index - 1 ) and
184
+ index = getNumberOfActualChildren ( cfe )
185
+ )
186
+ }
184
187
}
185
188
186
189
private import Cached
187
190
188
- /** Gets the global value number of the element `cfe` */
189
- cached
190
- Gvn toGvn ( ControlFlowElement cfe ) {
191
- result = TConstantGvn ( cfe .( Expr ) .getValue ( ) )
192
- or
193
- not exists ( cfe .( Expr ) .getValue ( ) ) and
194
- exists ( GvnKind kind , int index |
195
- result = gvnConstructed ( cfe , kind , index - 1 ) and
196
- index = getNumberOfActualChildren ( cfe )
197
- )
191
+ predicate toGvn = toGvnCached / 1 ;
192
+
193
+ pragma [ inline]
194
+ private predicate sameGvn ( ControlFlowElement x , ControlFlowElement y ) {
195
+ pragma [ only_bind_into ] ( toGvn ( pragma [ only_bind_out ] ( x ) ) ) =
196
+ pragma [ only_bind_into ] ( toGvn ( pragma [ only_bind_out ] ( y ) ) )
198
197
}
199
198
200
199
/**
@@ -227,12 +226,6 @@ abstract class StructuralComparisonConfiguration extends string {
227
226
*/
228
227
abstract predicate candidate ( ControlFlowElement x , ControlFlowElement y ) ;
229
228
230
- pragma [ inline]
231
- private predicate sameGvn ( ControlFlowElement x , ControlFlowElement y ) {
232
- pragma [ only_bind_into ] ( toGvn ( pragma [ only_bind_out ] ( x ) ) ) =
233
- pragma [ only_bind_into ] ( toGvn ( pragma [ only_bind_out ] ( y ) ) )
234
- }
235
-
236
229
/**
237
230
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
238
231
* flagged as candidates for structural equality, that is,
@@ -284,12 +277,6 @@ module Internal {
284
277
*/
285
278
abstract predicate candidate ( ControlFlowElement x , ControlFlowElement y ) ;
286
279
287
- pragma [ inline]
288
- private predicate sameGvn ( ControlFlowElement x , ControlFlowElement y ) {
289
- pragma [ only_bind_into ] ( toGvn ( pragma [ only_bind_out ] ( x ) ) ) =
290
- pragma [ only_bind_into ] ( toGvn ( pragma [ only_bind_out ] ( y ) ) )
291
- }
292
-
293
280
/**
294
281
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
295
282
* flagged as candidates for structural equality, that is,
0 commit comments