@@ -14,15 +14,15 @@ private class GvnKindExpr extends GvnKind, TGvnKindExpr {
1414
1515 GvnKindExpr ( ) { this = TGvnKindExpr ( kind ) }
1616
17- override string toString ( ) { result = "Expr(" + kind . toString ( ) + ")" }
17+ override string toString ( ) { result = "Expr(" + kind + ")" }
1818}
1919
2020private class GvnKindStmt extends GvnKind , TGvnKindStmt {
2121 private int kind ;
2222
2323 GvnKindStmt ( ) { this = TGvnKindStmt ( kind ) }
2424
25- override string toString ( ) { result = "Stmt(" + kind . toString ( ) + ")" }
25+ override string toString ( ) { result = "Stmt(" + kind + ")" }
2626}
2727
2828private class GvnKindDeclaration extends GvnKind , TGvnKindDeclaration {
@@ -32,9 +32,7 @@ private class GvnKindDeclaration extends GvnKind, TGvnKindDeclaration {
3232
3333 GvnKindDeclaration ( ) { this = TGvnKindDeclaration ( kind , isTargetThis , d ) }
3434
35- override string toString ( ) {
36- result = "Expr(" + kind .toString ( ) + ")," + isTargetThis + "," + d .toString ( )
37- }
35+ override string toString ( ) { result = "Expr(" + kind + ")," + isTargetThis + "," + d }
3836}
3937
4038/** Gets the declaration referenced by the expression `e`, if any. */
@@ -46,62 +44,56 @@ private Declaration referenceAttribute(Expr e) {
4644 result = e .( Access ) .getTarget ( )
4745}
4846
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`. */
5048private boolean isTargetThis ( Expr e ) {
5149 result = true and e .( MemberAccess ) .targetIsThisInstance ( )
5250 or
5351 result = false and not e .( MemberAccess ) .targetIsThisInstance ( )
5452}
5553
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 {
6962 /** Gets the string representation of this global value number. */
70- abstract string toString ( ) ;
63+ string toString ( ) { none ( ) }
7164}
7265
7366private class ConstantGvn extends Gvn , TConstantGvn {
7467 override string toString ( ) { this = TConstantGvn ( result ) }
7568}
7669
77- private class GvnBase extends Gvn , TGvnBase {
70+ private class GvnNil extends Gvn , TGvnNil {
7871 private GvnKind kind ;
7972
80- GvnBase ( ) { this = TGvnBase ( kind ) }
73+ GvnNil ( ) { this = TGvnNil ( kind ) }
8174
8275 override string toString ( ) { result = "(kind:" + kind + ")" }
8376}
8477
85- private class GvnStruct extends Gvn , TGvnStruct {
78+ private class GvnCons extends Gvn , TGvnCons {
8679 private Gvn head ;
8780 private Gvn tail ;
8881
89- GvnStruct ( ) { this = TGvnStruct ( head , tail ) }
82+ GvnCons ( ) { this = TGvnCons ( head , tail ) }
9083
91- override string toString ( ) { result = "(" + head . toString ( ) + " :: " + tail . toString ( ) + ")" }
84+ override string toString ( ) { result = "(" + head + " :: " + tail + ")" }
9285}
9386
9487pragma [ 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 , _)
10192}
10293
10394/**
10495 * Gets the `GvnKind` of the element `cfe`.
96+ *
10597 * In case `cfe` is a reference attribute, we encode the entire declaration and whether
10698 * the target is semantically equivalent to `this`.
10799 */
@@ -111,18 +103,24 @@ private GvnKind getGvnKind(ControlFlowElement cfe) {
111103 result = TGvnKindDeclaration ( kind , isTargetThis , d )
112104 )
113105 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+ )
116114}
117115
118- private Gvn gvnConstructed ( ControlFlowElement cfe , GvnKind kind , int index ) {
116+ private Gvn toGvn ( ControlFlowElement cfe , GvnKind kind , int index ) {
119117 kind = getGvnKind ( cfe ) and
120- result = TGvnBase ( kind ) and
118+ result = TGvnNil ( kind ) and
121119 index = - 1
122120 or
123121 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 )
126124 )
127125}
128126
@@ -147,16 +145,14 @@ private ControlFlowElement getRankedChild(ControlFlowElement cfe, int rnk) {
147145}
148146
149147pragma [ noinline]
150- private Gvn gvnChild ( ControlFlowElement cfe , int index ) {
148+ private Gvn toGvnChild ( ControlFlowElement cfe , int index ) {
151149 result = toGvn ( getRankedChild ( cfe , index ) )
152150}
153151
154152pragma [ 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 )
160156}
161157
162158cached
@@ -171,30 +167,33 @@ private module Cached {
171167 )
172168 }
173169
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- */
179170 cached
180171 newtype TGvn =
181172 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+ }
184187}
185188
186189private import Cached
187190
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 ) ) )
198197}
199198
200199/**
@@ -227,12 +226,6 @@ abstract class StructuralComparisonConfiguration extends string {
227226 */
228227 abstract predicate candidate ( ControlFlowElement x , ControlFlowElement y ) ;
229228
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-
236229 /**
237230 * Holds if elements `x` and `y` structurally equal. `x` and `y` must be
238231 * flagged as candidates for structural equality, that is,
@@ -284,12 +277,6 @@ module Internal {
284277 */
285278 abstract predicate candidate ( ControlFlowElement x , ControlFlowElement y ) ;
286279
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-
293280 /**
294281 * Holds if elements `x` and `y` structurally equal. `x` and `y` must be
295282 * flagged as candidates for structural equality, that is,
0 commit comments