6
6
* Provides classes for working with static single assignment (SSA) form.
7
7
*/
8
8
module Ssa {
9
- private import semmle.code.powershell.Cfg
10
9
private import powershell
10
+ private import semmle.code.powershell.Cfg
11
11
private import internal.SsaImpl as SsaImpl
12
- private import CfgNodes
13
- private import ExprNodes
12
+ private import CfgNodes:: ExprNodes
14
13
15
14
/** A static single assignment (SSA) definition. */
16
15
class Definition extends SsaImpl:: Definition {
@@ -23,8 +22,10 @@ module Ssa {
23
22
exists ( BasicBlock bb , int i | this .definesAt ( _, bb , i ) | result = bb .getNode ( i ) )
24
23
}
25
24
26
- /** Gets a control-flow node that reads the value of this SSA definition. */
27
- final AstCfgNode getARead ( ) { result = SsaImpl:: getARead ( this ) }
25
+ /**
26
+ * Gets a control-flow node that reads the value of this SSA definition.
27
+ */
28
+ final VarReadAccessCfgNode getARead ( ) { result = SsaImpl:: getARead ( this ) }
28
29
29
30
/**
30
31
* Gets a first control-flow node that reads the value of this SSA definition.
@@ -38,16 +39,14 @@ module Ssa {
38
39
* That is, a read that can reach the end of the enclosing CFG scope, or another
39
40
* SSA definition for the source variable, without passing through any other read.
40
41
*/
41
- final VarReadAccessCfgNode getALastRead ( ) { SsaImpl:: lastRead ( this , result ) }
42
+ deprecated final VarReadAccessCfgNode getALastRead ( ) { SsaImpl:: lastRead ( this , result ) }
42
43
43
44
/**
44
45
* Holds if `read1` and `read2` are adjacent reads of this SSA definition.
45
46
* That is, `read2` can be reached from `read1` without passing through
46
47
* another read.
47
48
*/
48
- final predicate hasAdjacentReads (
49
- VarReadAccessCfgNode read1 , VarReadAccessCfgNode read2
50
- ) {
49
+ final predicate hasAdjacentReads ( VarReadAccessCfgNode read1 , VarReadAccessCfgNode read2 ) {
51
50
SsaImpl:: adjacentReadPair ( this , read1 , read2 )
52
51
}
53
52
@@ -91,7 +90,7 @@ module Ssa {
91
90
/**
92
91
* Holds if this SSA definition assigns `value` to the underlying variable.
93
92
*/
94
- predicate assigns ( CfgNodes:: StmtCfgNode value ) {
93
+ predicate assigns ( CfgNodes:: ExprCfgNode value ) {
95
94
exists ( CfgNodes:: StmtNodes:: AssignStmtCfgNode a , BasicBlock bb , int i |
96
95
this .definesAt ( _, bb , i ) and
97
96
a = bb .getNode ( i ) and
@@ -104,19 +103,19 @@ module Ssa {
104
103
final override Location getLocation ( ) { result = write .getLocation ( ) }
105
104
}
106
105
107
- class ParameterDefinition extends Definition , SsaImpl:: WriteDefinition {
108
- private Variable v ;
106
+ /**
107
+ * An SSA definition that corresponds to the value of `this` upon entry to a method.
108
+ */
109
+ class ThisDefinition extends Definition , SsaImpl:: WriteDefinition {
110
+ private ThisParameter v ;
109
111
110
- ParameterDefinition ( ) {
111
- exists ( BasicBlock bb , int i |
112
- this .definesAt ( v , bb , i ) and
113
- SsaImpl:: parameterWrite ( bb , i , v )
114
- )
115
- }
112
+ ThisDefinition ( ) { exists ( BasicBlock bb , int i | this .definesAt ( v , bb , i ) ) }
113
+
114
+ override ThisParameter getSourceVariable ( ) { result = v }
116
115
117
- final override string toString ( ) { result = "<parameter> " + v }
116
+ final override string toString ( ) { result = "self ( " + v . getDeclaringScope ( ) + ")" }
118
117
119
- final override Location getLocation ( ) { result = v .getLocation ( ) }
118
+ final override Location getLocation ( ) { result = this . getControlFlowNode ( ) .getLocation ( ) }
120
119
}
121
120
122
121
/**
@@ -138,7 +137,7 @@ module Ssa {
138
137
final override Location getLocation ( ) { result = this .getBasicBlock ( ) .getLocation ( ) }
139
138
}
140
139
141
- /** A phi node. */
140
+ /** phi node. */
142
141
class PhiNode extends Definition , SsaImpl:: PhiNode {
143
142
/** Gets an input of this phi node. */
144
143
final Definition getAnInput ( ) { this .hasInputFromBlock ( result , _) }
@@ -148,7 +147,20 @@ module Ssa {
148
147
inp = SsaImpl:: phiHasInputFromBlock ( this , bb )
149
148
}
150
149
151
- override string toString ( ) { result = "phi" }
150
+ private string getSplitString ( ) {
151
+ result = this .getBasicBlock ( ) .getFirstNode ( ) .( CfgNodes:: AstCfgNode ) .getSplitsString ( )
152
+ }
153
+
154
+ override string toString ( ) {
155
+ exists ( string prefix |
156
+ prefix = "[" + this .getSplitString ( ) + "] "
157
+ or
158
+ not exists ( this .getSplitString ( ) ) and
159
+ prefix = ""
160
+ |
161
+ result = prefix + "phi"
162
+ )
163
+ }
152
164
153
165
/**
154
166
* The location of a phi node is the same as the location of the first node
0 commit comments