@@ -4,19 +4,74 @@ import csharp
44 * Provides a simple SSA implementation for local scope variables.
55 */
66module 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 > ;
964
1065 class Definition extends SsaImpl:: Definition {
1166 final AssignableRead getARead ( ) {
12- exists ( BasicBlock bb , int i |
67+ exists ( ControlFlow :: BasicBlock bb , int i |
1368 SsaImpl:: ssaDefReachesRead ( _, this , bb , i ) and
1469 result .getAControlFlowNode ( ) = bb .getNode ( i )
1570 )
1671 }
1772
1873 final AssignableDefinition getDefinition ( ) {
19- exists ( BasicBlock bb , int i , SourceVariable v |
74+ exists ( ControlFlow :: BasicBlock bb , int i , SsaInput :: SourceVariable v |
2075 this .definesAt ( v , bb , i ) and
2176 definitionAt ( result , bb , i , v )
2277 )
0 commit comments