@@ -4,19 +4,74 @@ import csharp
4
4
* Provides a simple SSA implementation for local scope variables.
5
5
*/
6
6
module BaseSsa {
7
- import basessa.SsaImplSpecific
8
- private import basessa.SsaImplCommon as SsaImpl
7
+ private import AssignableDefinitions
8
+ private import semmle.code.csharp.dataflow.internal.SsaImplCommon as SsaImplCommon
9
+
10
+ /**
11
+ * Holds if the `i`th node of basic block `bb` is assignable definition `def`,
12
+ * targeting local scope variable `v`.
13
+ */
14
+ private predicate definitionAt (
15
+ AssignableDefinition def , ControlFlow:: BasicBlock bb , int i , SsaInput:: SourceVariable v
16
+ ) {
17
+ bb .getNode ( i ) = def .getAControlFlowNode ( ) and
18
+ v = def .getTarget ( ) and
19
+ // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
20
+ not exists ( TupleAssignmentDefinition first , TupleAssignmentDefinition second | first = def |
21
+ second .getAssignment ( ) = first .getAssignment ( ) and
22
+ second .getEvaluationOrder ( ) > first .getEvaluationOrder ( ) and
23
+ second .getTarget ( ) = v
24
+ )
25
+ }
26
+
27
+ private module SsaInput implements SsaImplCommon:: InputSig {
28
+ class BasicBlock = ControlFlow:: BasicBlock ;
29
+
30
+ BasicBlock getImmediateBasicBlockDominator ( BasicBlock bb ) {
31
+ result = bb .getImmediateDominator ( )
32
+ }
33
+
34
+ BasicBlock getABasicBlockSuccessor ( BasicBlock bb ) { result = bb .getASuccessor ( ) }
35
+
36
+ class ExitBasicBlock = ControlFlow:: BasicBlocks:: ExitBlock ;
37
+
38
+ pragma [ noinline]
39
+ private Callable getAnAssigningCallable ( LocalScopeVariable v ) {
40
+ result = any ( AssignableDefinition def | def .getTarget ( ) = v ) .getEnclosingCallable ( )
41
+ }
42
+
43
+ class SourceVariable extends LocalScopeVariable {
44
+ SourceVariable ( ) { not getAnAssigningCallable ( this ) != getAnAssigningCallable ( this ) }
45
+ }
46
+
47
+ predicate variableWrite ( BasicBlock bb , int i , SourceVariable v , boolean certain ) {
48
+ exists ( AssignableDefinition def |
49
+ definitionAt ( def , bb , i , v ) and
50
+ if def .isCertain ( ) then certain = true else certain = false
51
+ )
52
+ }
53
+
54
+ predicate variableRead ( BasicBlock bb , int i , SourceVariable v , boolean certain ) {
55
+ exists ( AssignableRead read |
56
+ read .getAControlFlowNode ( ) = bb .getNode ( i ) and
57
+ read .getTarget ( ) = v and
58
+ certain = true
59
+ )
60
+ }
61
+ }
62
+
63
+ private module SsaImpl = SsaImplCommon:: Make< SsaInput > ;
9
64
10
65
class Definition extends SsaImpl:: Definition {
11
66
final AssignableRead getARead ( ) {
12
- exists ( BasicBlock bb , int i |
67
+ exists ( ControlFlow :: BasicBlock bb , int i |
13
68
SsaImpl:: ssaDefReachesRead ( _, this , bb , i ) and
14
69
result .getAControlFlowNode ( ) = bb .getNode ( i )
15
70
)
16
71
}
17
72
18
73
final AssignableDefinition getDefinition ( ) {
19
- exists ( BasicBlock bb , int i , SourceVariable v |
74
+ exists ( ControlFlow :: BasicBlock bb , int i , SsaInput :: SourceVariable v |
20
75
this .definesAt ( v , bb , i ) and
21
76
definitionAt ( result , bb , i , v )
22
77
)
0 commit comments