Skip to content

Commit 8725bf0

Browse files
committed
C#: Update Base SSA library to use parameterized module
1 parent f553001 commit 8725bf0

File tree

4 files changed

+59
-851
lines changed

4 files changed

+59
-851
lines changed

config/identical-files.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@
463463
"SSA C#": [
464464
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
465465
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll",
466-
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
467466
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
468467
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll",
469468
"swift/ql/lib/codeql/swift/dataflow/internal/SsaImplCommon.qll"

csharp/ql/lib/semmle/code/csharp/dataflow/internal/BaseSSA.qll

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,74 @@ import csharp
44
* Provides a simple SSA implementation for local scope variables.
55
*/
66
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>;
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

Comments
 (0)