mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #11198 from hvitved/ssa/expose-phi-reads
SSA: Expose phi-read nodes
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.internal.SsaImpl::Consistency
|
||||
import semmle.code.csharp.dataflow.internal.SsaImpl as Impl
|
||||
import Impl::Consistency
|
||||
import Ssa
|
||||
|
||||
class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
|
||||
@@ -10,6 +11,14 @@ class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
|
||||
}
|
||||
}
|
||||
|
||||
class MyRelevantDefinitionExt extends RelevantDefinitionExt, Impl::DefinitionExt {
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
query predicate localDeclWithSsaDef(LocalVariableDeclExpr d) {
|
||||
// Local variables in C# must be initialized before every use, so uninitialized
|
||||
// local variables should not have an SSA definition, as that would imply that
|
||||
|
||||
@@ -138,25 +138,6 @@ module Ssa {
|
||||
}
|
||||
}
|
||||
|
||||
private string getSplitString(Definition def) {
|
||||
exists(ControlFlow::BasicBlock bb, int i, ControlFlow::Node cfn |
|
||||
def.definesAt(_, bb, i) and
|
||||
result = cfn.(ControlFlow::Nodes::ElementNode).getSplitsString()
|
||||
|
|
||||
cfn = bb.getNode(i)
|
||||
or
|
||||
not exists(bb.getNode(i)) and
|
||||
cfn = bb.getFirstNode()
|
||||
)
|
||||
}
|
||||
|
||||
private string getToStringPrefix(Definition def) {
|
||||
result = "[" + getSplitString(def) + "] "
|
||||
or
|
||||
not exists(getSplitString(def)) and
|
||||
result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* A static single assignment (SSA) definition. Either an explicit variable
|
||||
* definition (`ExplicitDefinition`), an implicit variable definition
|
||||
@@ -521,8 +502,8 @@ module Ssa {
|
||||
|
||||
override string toString() {
|
||||
if this.getADefinition() instanceof AssignableDefinitions::ImplicitParameterDefinition
|
||||
then result = getToStringPrefix(this) + "SSA param(" + this.getSourceVariable() + ")"
|
||||
else result = getToStringPrefix(this) + "SSA def(" + this.getSourceVariable() + ")"
|
||||
then result = SsaImpl::getToStringPrefix(this) + "SSA param(" + this.getSourceVariable() + ")"
|
||||
else result = SsaImpl::getToStringPrefix(this) + "SSA def(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = ad.getLocation() }
|
||||
@@ -570,8 +551,12 @@ module Ssa {
|
||||
|
||||
override string toString() {
|
||||
if this.getSourceVariable().getAssignable() instanceof LocalScopeVariable
|
||||
then result = getToStringPrefix(this) + "SSA capture def(" + this.getSourceVariable() + ")"
|
||||
else result = getToStringPrefix(this) + "SSA entry def(" + this.getSourceVariable() + ")"
|
||||
then
|
||||
result =
|
||||
SsaImpl::getToStringPrefix(this) + "SSA capture def(" + this.getSourceVariable() + ")"
|
||||
else
|
||||
result =
|
||||
SsaImpl::getToStringPrefix(this) + "SSA entry def(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getCallable().getLocation() }
|
||||
@@ -612,7 +597,7 @@ module Ssa {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA call def(" + this.getSourceVariable() + ")"
|
||||
result = SsaImpl::getToStringPrefix(this) + "SSA call def(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getCall().getLocation() }
|
||||
@@ -640,7 +625,8 @@ module Ssa {
|
||||
final Definition getQualifierDefinition() { result = q }
|
||||
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA qualifier def(" + this.getSourceVariable() + ")"
|
||||
result =
|
||||
SsaImpl::getToStringPrefix(this) + "SSA qualifier def(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getQualifierDefinition().getLocation() }
|
||||
@@ -682,7 +668,7 @@ module Ssa {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA phi(" + this.getSourceVariable() + ")"
|
||||
result = SsaImpl::getToStringPrefix(this) + "SSA phi(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,7 +49,23 @@ private module SsaInput implements SsaImplCommon::InputSig {
|
||||
}
|
||||
}
|
||||
|
||||
import SsaImplCommon::Make<SsaInput>
|
||||
private import SsaImplCommon::Make<SsaInput> as Impl
|
||||
|
||||
class Definition = Impl::Definition;
|
||||
|
||||
class WriteDefinition = Impl::WriteDefinition;
|
||||
|
||||
class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
|
||||
|
||||
class PhiNode = Impl::PhiNode;
|
||||
|
||||
module Consistency = Impl::Consistency;
|
||||
|
||||
module ExposedForTestingOnly {
|
||||
predicate ssaDefReachesReadExt = Impl::ssaDefReachesReadExt/4;
|
||||
|
||||
predicate phiHasInputFromBlockExt = Impl::phiHasInputFromBlockExt/3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
|
||||
@@ -1072,7 +1088,7 @@ private predicate adjacentDefRead(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
|
||||
SsaInput::SourceVariable v
|
||||
) {
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
v = def.getSourceVariable()
|
||||
}
|
||||
|
||||
@@ -1088,7 +1104,7 @@ private predicate adjacentDefReachesRead(
|
||||
exists(SsaInput::BasicBlock bb3, int i3 |
|
||||
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
|
||||
SsaInput::variableRead(bb3, i3, _, false) and
|
||||
adjacentDefRead(def, bb3, i3, bb2, i2)
|
||||
Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1111,11 +1127,11 @@ private predicate adjacentDefReachesUncertainRead(
|
||||
/** Same as `lastRefRedef`, but skips uncertain reads. */
|
||||
pragma[nomagic]
|
||||
private predicate lastRefSkipUncertainReads(Definition def, SsaInput::BasicBlock bb, int i) {
|
||||
lastRef(def, bb, i) and
|
||||
Impl::lastRef(def, bb, i) and
|
||||
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb0, int i0 |
|
||||
lastRef(def, bb0, i0) and
|
||||
Impl::lastRef(def, bb0, i0) and
|
||||
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
|
||||
)
|
||||
}
|
||||
@@ -1237,7 +1253,7 @@ private module Cached {
|
||||
v = def.getSourceVariable() and
|
||||
capturedReadIn(_, _, v, edef.getSourceVariable(), c, additionalCalls) and
|
||||
def = def0.getAnUltimateDefinition() and
|
||||
ssaDefReachesRead(_, def0, bb, i) and
|
||||
Impl::ssaDefReachesRead(_, def0, bb, i) and
|
||||
capturedReadIn(bb, i, v, _, _, _) and
|
||||
c = bb.getNode(i)
|
||||
)
|
||||
@@ -1264,18 +1280,18 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate isLiveAtEndOfBlock(Definition def, ControlFlow::BasicBlock bb) {
|
||||
ssaDefReachesEndOfBlock(bb, def, _)
|
||||
Impl::ssaDefReachesEndOfBlock(bb, def, _)
|
||||
}
|
||||
|
||||
cached
|
||||
Definition phiHasInputFromBlock(PhiNode phi, ControlFlow::BasicBlock bb) {
|
||||
phiHasInputFromBlock(phi, result, bb)
|
||||
Definition phiHasInputFromBlock(Ssa::PhiNode phi, ControlFlow::BasicBlock bb) {
|
||||
Impl::phiHasInputFromBlock(phi, result, bb)
|
||||
}
|
||||
|
||||
cached
|
||||
AssignableRead getAReadAtNode(Definition def, ControlFlow::Node cfn) {
|
||||
exists(Ssa::SourceVariable v, ControlFlow::BasicBlock bb, int i |
|
||||
ssaDefReachesRead(v, def, bb, i) and
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
variableReadActual(bb, i, v) and
|
||||
cfn = bb.getNode(i) and
|
||||
result.getAControlFlowNode() = cfn
|
||||
@@ -1313,11 +1329,11 @@ private module Cached {
|
||||
/** Same as `lastRefRedef`, but skips uncertain reads. */
|
||||
cached
|
||||
predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) {
|
||||
lastRefRedef(def, bb, i, next) and
|
||||
Impl::lastRefRedef(def, bb, i, next) and
|
||||
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb0, int i0 |
|
||||
lastRefRedef(def, bb0, i0, next) and
|
||||
Impl::lastRefRedef(def, bb0, i0, next) and
|
||||
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
|
||||
)
|
||||
}
|
||||
@@ -1333,7 +1349,7 @@ private module Cached {
|
||||
|
||||
cached
|
||||
Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) {
|
||||
uncertainWriteDefinitionInput(def, result)
|
||||
Impl::uncertainWriteDefinitionInput(def, result)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -1343,10 +1359,57 @@ private module Cached {
|
||||
v = def.getSourceVariable() and
|
||||
p = v.getAssignable() and
|
||||
def = def0.getAnUltimateDefinition() and
|
||||
ssaDefReachesRead(_, def0, bb, i) and
|
||||
Impl::ssaDefReachesRead(_, def0, bb, i) and
|
||||
outRefExitRead(bb, i, v)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
private string getSplitString(DefinitionExt def) {
|
||||
exists(ControlFlow::BasicBlock bb, int i, ControlFlow::Node cfn |
|
||||
def.definesAt(_, bb, i, _) and
|
||||
result = cfn.(ControlFlow::Nodes::ElementNode).getSplitsString()
|
||||
|
|
||||
cfn = bb.getNode(i)
|
||||
or
|
||||
not exists(bb.getNode(i)) and
|
||||
cfn = bb.getFirstNode()
|
||||
)
|
||||
}
|
||||
|
||||
string getToStringPrefix(DefinitionExt def) {
|
||||
result = "[" + getSplitString(def) + "] "
|
||||
or
|
||||
not exists(getSplitString(def)) and
|
||||
result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* An extended static single assignment (SSA) definition.
|
||||
*
|
||||
* This is either a normal SSA definition (`Definition`) or a
|
||||
* phi-read node (`PhiReadNode`).
|
||||
*
|
||||
* Only intended for internal use.
|
||||
*/
|
||||
class DefinitionExt extends Impl::DefinitionExt {
|
||||
override string toString() { result = this.(Ssa::Definition).toString() }
|
||||
|
||||
/** Gets the location of this definition. */
|
||||
Location getLocation() { result = this.(Ssa::Definition).getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A phi-read node.
|
||||
*
|
||||
* Only intended for internal use.
|
||||
*/
|
||||
class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA phi read(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getBasicBlock().getLocation() }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,30 @@
|
||||
| DefUse.cs:63:9:63:14 | this.Field2 | DefUse.cs:80:30:80:31 | access to local variable x1 |
|
||||
| Fields.cs:65:24:65:32 | this.LoopField | Fields.cs:63:16:63:28 | this access |
|
||||
| Properties.cs:65:24:65:31 | this.LoopProp | Properties.cs:63:16:63:16 | access to parameter i |
|
||||
| Test.cs:78:13:78:13 | x | Test.cs:90:9:97:9 | if (...) ... |
|
||||
phiReadNode
|
||||
| DefUse.cs:80:30:80:31 | SSA phi read(this.Field2) | DefUse.cs:63:9:63:14 | this.Field2 |
|
||||
| Fields.cs:63:16:63:28 | SSA phi read(this.LoopField) | Fields.cs:65:24:65:32 | this.LoopField |
|
||||
| Patterns.cs:20:9:38:9 | SSA phi read(o) | Patterns.cs:7:16:7:16 | o |
|
||||
| Properties.cs:63:16:63:16 | SSA phi read(this.LoopProp) | Properties.cs:65:24:65:31 | this.LoopProp |
|
||||
| Test.cs:25:16:25:16 | SSA phi read(x) | Test.cs:8:13:8:13 | x |
|
||||
| Test.cs:90:9:97:9 | SSA phi read(x) | Test.cs:78:13:78:13 | x |
|
||||
| Test.cs:99:9:99:15 | SSA phi read(x) | Test.cs:78:13:78:13 | x |
|
||||
phiReadNodeRead
|
||||
| DefUse.cs:80:30:80:31 | SSA phi read(this.Field2) | DefUse.cs:63:9:63:14 | this.Field2 | DefUse.cs:80:37:80:42 | access to field Field2 |
|
||||
| Fields.cs:63:16:63:28 | SSA phi read(this.LoopField) | Fields.cs:65:24:65:32 | this.LoopField | Fields.cs:65:24:65:32 | access to field LoopField |
|
||||
| Patterns.cs:20:9:38:9 | SSA phi read(o) | Patterns.cs:7:16:7:16 | o | Patterns.cs:20:17:20:17 | access to local variable o |
|
||||
| Properties.cs:63:16:63:16 | SSA phi read(this.LoopProp) | Properties.cs:65:24:65:31 | this.LoopProp | Properties.cs:65:24:65:31 | access to property LoopProp |
|
||||
| Test.cs:25:16:25:16 | SSA phi read(x) | Test.cs:8:13:8:13 | x | Test.cs:25:16:25:16 | access to local variable x |
|
||||
| Test.cs:90:9:97:9 | SSA phi read(x) | Test.cs:78:13:78:13 | x | Test.cs:92:17:92:17 | access to local variable x |
|
||||
| Test.cs:90:9:97:9 | SSA phi read(x) | Test.cs:78:13:78:13 | x | Test.cs:96:17:96:17 | access to local variable x |
|
||||
| Test.cs:99:9:99:15 | SSA phi read(x) | Test.cs:78:13:78:13 | x | Test.cs:99:13:99:13 | access to local variable x |
|
||||
| Test.cs:99:9:99:15 | SSA phi read(x) | Test.cs:78:13:78:13 | x | Test.cs:104:17:104:17 | access to local variable x |
|
||||
phiReadInput
|
||||
| DefUse.cs:80:30:80:31 | SSA phi read(this.Field2) | DefUse.cs:63:9:63:18 | SSA def(this.Field2) |
|
||||
| DefUse.cs:80:30:80:31 | SSA phi read(this.Field2) | DefUse.cs:80:30:80:31 | SSA phi read(this.Field2) |
|
||||
| Fields.cs:63:16:63:28 | SSA phi read(this.LoopField) | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) |
|
||||
| Fields.cs:63:16:63:28 | SSA phi read(this.LoopField) | Fields.cs:63:16:63:28 | SSA phi read(this.LoopField) |
|
||||
| Patterns.cs:20:9:38:9 | SSA phi read(o) | Patterns.cs:7:16:7:23 | SSA def(o) |
|
||||
| Properties.cs:63:16:63:16 | SSA phi read(this.LoopProp) | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) |
|
||||
| Properties.cs:63:16:63:16 | SSA phi read(this.LoopProp) | Properties.cs:63:16:63:16 | SSA phi read(this.LoopProp) |
|
||||
| Test.cs:25:16:25:16 | SSA phi read(x) | Test.cs:24:9:24:15 | SSA phi(x) |
|
||||
| Test.cs:25:16:25:16 | SSA phi read(x) | Test.cs:25:16:25:16 | SSA phi read(x) |
|
||||
| Test.cs:90:9:97:9 | SSA phi read(x) | Test.cs:78:13:78:17 | SSA def(x) |
|
||||
| Test.cs:99:9:99:15 | SSA phi read(x) | Test.cs:90:9:97:9 | SSA phi read(x) |
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.internal.SsaImpl
|
||||
import ExposedForTestingOnly
|
||||
|
||||
from Ssa::SourceVariable v, ControlFlow::BasicBlock bb
|
||||
where phiReadExposedForTesting(bb, v)
|
||||
select v, bb
|
||||
query predicate phiReadNode(PhiReadNode phi, Ssa::SourceVariable v) { phi.getSourceVariable() = v }
|
||||
|
||||
query predicate phiReadNodeRead(PhiReadNode phi, Ssa::SourceVariable v, ControlFlow::Node read) {
|
||||
phi.getSourceVariable() = v and
|
||||
exists(ControlFlow::BasicBlock bb, int i |
|
||||
ssaDefReachesReadExt(v, phi, bb, i) and
|
||||
read = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
query predicate phiReadInput(PhiReadNode phi, DefinitionExt inp) {
|
||||
phiHasInputFromBlockExt(phi, inp, _)
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class Test
|
||||
{
|
||||
use(x);
|
||||
}
|
||||
// no phi_use for `x`, because actual use exists in the block
|
||||
// phi_use for `x`, even though there is an actual use in the block
|
||||
use(x);
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import codeql.ruby.dataflow.SSA
|
||||
import codeql.ruby.dataflow.internal.SsaImpl::Consistency
|
||||
import codeql.ruby.dataflow.internal.SsaImpl
|
||||
import Consistency
|
||||
|
||||
class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
|
||||
override predicate hasLocationInfo(
|
||||
@@ -8,3 +9,11 @@ class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
class MyRelevantDefinitionExt extends RelevantDefinitionExt, DefinitionExt {
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ private import codeql.ssa.Ssa as SsaImplCommon
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.CFG as Cfg
|
||||
private import codeql.ruby.controlflow.internal.ControlFlowGraphImplShared as ControlFlowGraphImplShared
|
||||
private import codeql.ruby.dataflow.SSA
|
||||
private import codeql.ruby.ast.Variable
|
||||
private import Cfg::CfgNodes::ExprNodes
|
||||
|
||||
@@ -61,7 +62,23 @@ private module SsaInput implements SsaImplCommon::InputSig {
|
||||
}
|
||||
}
|
||||
|
||||
import SsaImplCommon::Make<SsaInput>
|
||||
private import SsaImplCommon::Make<SsaInput> as Impl
|
||||
|
||||
class Definition = Impl::Definition;
|
||||
|
||||
class WriteDefinition = Impl::WriteDefinition;
|
||||
|
||||
class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
|
||||
|
||||
class PhiNode = Impl::PhiNode;
|
||||
|
||||
module Consistency = Impl::Consistency;
|
||||
|
||||
module ExposedForTestingOnly {
|
||||
predicate ssaDefReachesReadExt = Impl::ssaDefReachesReadExt/4;
|
||||
|
||||
predicate phiHasInputFromBlockExt = Impl::phiHasInputFromBlockExt/3;
|
||||
}
|
||||
|
||||
/** Holds if `v` is uninitialized at index `i` in entry block `bb`. */
|
||||
predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, LocalVariable v) {
|
||||
@@ -204,7 +221,7 @@ private predicate adjacentDefRead(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
|
||||
SsaInput::SourceVariable v
|
||||
) {
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
v = def.getSourceVariable()
|
||||
}
|
||||
|
||||
@@ -220,7 +237,7 @@ private predicate adjacentDefReachesRead(
|
||||
exists(SsaInput::BasicBlock bb3, int i3 |
|
||||
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
|
||||
SsaInput::variableRead(bb3, i3, _, false) and
|
||||
adjacentDefRead(def, bb3, i3, bb2, i2)
|
||||
Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -243,11 +260,11 @@ private predicate adjacentDefReachesUncertainRead(
|
||||
/** Same as `lastRefRedef`, but skips uncertain reads. */
|
||||
pragma[nomagic]
|
||||
private predicate lastRefSkipUncertainReads(Definition def, SsaInput::BasicBlock bb, int i) {
|
||||
lastRef(def, bb, i) and
|
||||
Impl::lastRef(def, bb, i) and
|
||||
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb0, int i0 |
|
||||
lastRef(def, bb0, i0) and
|
||||
Impl::lastRef(def, bb0, i0) and
|
||||
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
|
||||
)
|
||||
}
|
||||
@@ -304,7 +321,7 @@ private module Cached {
|
||||
cached
|
||||
VariableReadAccessCfgNode getARead(Definition def) {
|
||||
exists(LocalVariable v, Cfg::BasicBlock bb, int i |
|
||||
ssaDefReachesRead(v, def, bb, i) and
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
variableReadActual(bb, i, v) and
|
||||
result = bb.getNode(i)
|
||||
)
|
||||
@@ -315,7 +332,7 @@ private module Cached {
|
||||
Definition def, CallCfgNode call, LocalVariable v, Cfg::CfgScope scope
|
||||
) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
ssaDefReachesRead(v, def, bb, i) and
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
capturedCallRead(call, bb, i, v) and
|
||||
scope.getOuterCfgScope() = bb.getScope()
|
||||
)
|
||||
@@ -360,7 +377,7 @@ private module Cached {
|
||||
Definition def, LocalVariable v, Cfg::CfgScope scope
|
||||
) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
ssaDefReachesRead(v, def, bb, i) and
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
capturedExitRead(bb, i, v) and
|
||||
scope = bb.getScope().getOuterCfgScope*()
|
||||
)
|
||||
@@ -403,7 +420,7 @@ private module Cached {
|
||||
|
||||
cached
|
||||
Definition phiHasInputFromBlock(PhiNode phi, Cfg::BasicBlock bb) {
|
||||
phiHasInputFromBlock(phi, result, bb)
|
||||
Impl::phiHasInputFromBlock(phi, result, bb)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,19 +476,45 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate lastRefBeforeRedef(Definition def, Cfg::BasicBlock bb, int i, Definition next) {
|
||||
lastRefRedef(def, bb, i, next) and
|
||||
Impl::lastRefRedef(def, bb, i, next) and
|
||||
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb0, int i0 |
|
||||
lastRefRedef(def, bb0, i0, next) and
|
||||
Impl::lastRefRedef(def, bb0, i0, next) and
|
||||
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) {
|
||||
uncertainWriteDefinitionInput(def, result)
|
||||
Impl::uncertainWriteDefinitionInput(def, result)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
/**
|
||||
* An extended static single assignment (SSA) definition.
|
||||
*
|
||||
* This is either a normal SSA definition (`Definition`) or a
|
||||
* phi-read node (`PhiReadNode`).
|
||||
*
|
||||
* Only intended for internal use.
|
||||
*/
|
||||
class DefinitionExt extends Impl::DefinitionExt {
|
||||
override string toString() { result = this.(Ssa::Definition).toString() }
|
||||
|
||||
/** Gets the location of this definition. */
|
||||
Location getLocation() { result = this.(Ssa::Definition).getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A phi-read node.
|
||||
*
|
||||
* Only intended for internal use.
|
||||
*/
|
||||
class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
|
||||
override string toString() { result = "SSA phi read(" + this.getSourceVariable() + ")" }
|
||||
|
||||
override Location getLocation() { result = this.getBasicBlock().getLocation() }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| local_dataflow.rb:1:1:7:3 | self (foo) | local_dataflow.rb:3:8:3:10 | self |
|
||||
| local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:1:1:7:3 | self (foo) |
|
||||
| local_dataflow.rb:1:1:124:4 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self |
|
||||
| local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self |
|
||||
| local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a |
|
||||
| local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a |
|
||||
| local_dataflow.rb:2:3:2:7 | ... = ... | local_dataflow.rb:3:13:3:13 | b |
|
||||
@@ -279,3 +279,110 @@
|
||||
| local_dataflow.rb:123:8:123:20 | call to dup | local_dataflow.rb:123:8:123:45 | call to tap |
|
||||
| local_dataflow.rb:123:8:123:45 | call to tap | local_dataflow.rb:123:8:123:49 | call to dup |
|
||||
| local_dataflow.rb:123:26:123:45 | <captured> self | local_dataflow.rb:123:32:123:43 | self |
|
||||
| local_dataflow.rb:126:1:128:3 | self (use) | local_dataflow.rb:127:3:127:8 | self |
|
||||
| local_dataflow.rb:126:1:128:3 | self in use | local_dataflow.rb:126:1:128:3 | self (use) |
|
||||
| local_dataflow.rb:130:1:150:3 | self (use_use_madness) | local_dataflow.rb:132:6:132:11 | self |
|
||||
| local_dataflow.rb:130:1:150:3 | self in use_use_madness | local_dataflow.rb:130:1:150:3 | self (use_use_madness) |
|
||||
| local_dataflow.rb:131:3:131:8 | ... = ... | local_dataflow.rb:132:10:132:10 | x |
|
||||
| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... |
|
||||
| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... |
|
||||
| local_dataflow.rb:132:6:132:11 | [post] self | local_dataflow.rb:133:8:133:13 | self |
|
||||
| local_dataflow.rb:132:6:132:11 | self | local_dataflow.rb:133:8:133:13 | self |
|
||||
| local_dataflow.rb:132:10:132:10 | x | local_dataflow.rb:133:12:133:12 | x |
|
||||
| local_dataflow.rb:132:12:148:10 | then ... | local_dataflow.rb:132:3:149:5 | if ... |
|
||||
| local_dataflow.rb:133:8:133:13 | [post] self | local_dataflow.rb:133:18:133:23 | self |
|
||||
| local_dataflow.rb:133:8:133:13 | [post] self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:8:133:13 | call to use | local_dataflow.rb:133:8:133:23 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:133:8:133:13 | call to use | local_dataflow.rb:133:8:133:23 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:133:8:133:13 | self | local_dataflow.rb:133:18:133:23 | self |
|
||||
| local_dataflow.rb:133:8:133:13 | self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:12:133:12 | x | local_dataflow.rb:133:22:133:22 | x |
|
||||
| local_dataflow.rb:133:12:133:12 | x | local_dataflow.rb:134:11:134:11 | x |
|
||||
| local_dataflow.rb:133:18:133:23 | [post] self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:18:133:23 | [post] self | local_dataflow.rb:136:7:136:12 | self |
|
||||
| local_dataflow.rb:133:18:133:23 | call to use | local_dataflow.rb:133:8:133:23 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:133:18:133:23 | call to use | local_dataflow.rb:133:8:133:23 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:133:18:133:23 | self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:18:133:23 | self | local_dataflow.rb:136:7:136:12 | self |
|
||||
| local_dataflow.rb:133:22:133:22 | x | local_dataflow.rb:134:11:134:11 | x |
|
||||
| local_dataflow.rb:133:22:133:22 | x | local_dataflow.rb:136:11:136:11 | x |
|
||||
| local_dataflow.rb:133:24:134:12 | then ... | local_dataflow.rb:133:5:139:7 | if ... |
|
||||
| local_dataflow.rb:134:7:134:12 | [post] self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:134:7:134:12 | call to use | local_dataflow.rb:133:24:134:12 | then ... |
|
||||
| local_dataflow.rb:134:7:134:12 | self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:134:11:134:11 | x | local_dataflow.rb:141:13:141:13 | x |
|
||||
| local_dataflow.rb:135:5:138:9 | else ... | local_dataflow.rb:133:5:139:7 | if ... |
|
||||
| local_dataflow.rb:136:7:136:12 | [post] self | local_dataflow.rb:137:10:137:15 | self |
|
||||
| local_dataflow.rb:136:7:136:12 | self | local_dataflow.rb:137:10:137:15 | self |
|
||||
| local_dataflow.rb:136:11:136:11 | x | local_dataflow.rb:137:14:137:14 | x |
|
||||
| local_dataflow.rb:137:7:138:9 | if ... | local_dataflow.rb:135:5:138:9 | else ... |
|
||||
| local_dataflow.rb:137:10:137:15 | [post] self | local_dataflow.rb:137:21:137:26 | self |
|
||||
| local_dataflow.rb:137:10:137:15 | [post] self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:10:137:15 | call to use | local_dataflow.rb:137:10:137:26 | [false] ... && ... |
|
||||
| local_dataflow.rb:137:10:137:15 | call to use | local_dataflow.rb:137:10:137:26 | [true] ... && ... |
|
||||
| local_dataflow.rb:137:10:137:15 | self | local_dataflow.rb:137:21:137:26 | self |
|
||||
| local_dataflow.rb:137:10:137:15 | self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:14:137:14 | x | local_dataflow.rb:137:25:137:25 | x |
|
||||
| local_dataflow.rb:137:14:137:14 | x | local_dataflow.rb:141:13:141:13 | x |
|
||||
| local_dataflow.rb:137:20:137:26 | [false] ! ... | local_dataflow.rb:137:10:137:26 | [false] ... && ... |
|
||||
| local_dataflow.rb:137:20:137:26 | [true] ! ... | local_dataflow.rb:137:10:137:26 | [true] ... && ... |
|
||||
| local_dataflow.rb:137:21:137:26 | [post] self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:21:137:26 | self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:25:137:25 | x | local_dataflow.rb:141:13:141:13 | x |
|
||||
| local_dataflow.rb:141:8:141:14 | [false] ! ... | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:141:8:141:14 | [false] ! ... | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:141:8:141:14 | [true] ! ... | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:141:9:141:14 | [post] self | local_dataflow.rb:141:20:141:25 | self |
|
||||
| local_dataflow.rb:141:9:141:14 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:9:141:14 | self | local_dataflow.rb:141:20:141:25 | self |
|
||||
| local_dataflow.rb:141:9:141:14 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:13:141:13 | x | local_dataflow.rb:141:24:141:24 | x |
|
||||
| local_dataflow.rb:141:13:141:13 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:141:19:141:37 | [false] ( ... ) | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:141:19:141:37 | [true] ( ... ) | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:141:20:141:25 | [post] self | local_dataflow.rb:141:31:141:36 | self |
|
||||
| local_dataflow.rb:141:20:141:25 | [post] self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:20:141:25 | call to use | local_dataflow.rb:141:20:141:36 | [false] ... && ... |
|
||||
| local_dataflow.rb:141:20:141:25 | call to use | local_dataflow.rb:141:20:141:36 | [true] ... && ... |
|
||||
| local_dataflow.rb:141:20:141:25 | self | local_dataflow.rb:141:31:141:36 | self |
|
||||
| local_dataflow.rb:141:20:141:25 | self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:20:141:36 | [false] ... && ... | local_dataflow.rb:141:19:141:37 | [false] ( ... ) |
|
||||
| local_dataflow.rb:141:20:141:36 | [true] ... && ... | local_dataflow.rb:141:19:141:37 | [true] ( ... ) |
|
||||
| local_dataflow.rb:141:24:141:24 | x | local_dataflow.rb:141:35:141:35 | x |
|
||||
| local_dataflow.rb:141:24:141:24 | x | local_dataflow.rb:143:15:143:15 | x |
|
||||
| local_dataflow.rb:141:30:141:36 | [false] ! ... | local_dataflow.rb:141:20:141:36 | [false] ... && ... |
|
||||
| local_dataflow.rb:141:30:141:36 | [true] ! ... | local_dataflow.rb:141:20:141:36 | [true] ... && ... |
|
||||
| local_dataflow.rb:141:31:141:36 | [post] self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:31:141:36 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:31:141:36 | self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:31:141:36 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:35:141:35 | x | local_dataflow.rb:143:15:143:15 | x |
|
||||
| local_dataflow.rb:141:35:141:35 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:141:38:142:9 | then ... | local_dataflow.rb:141:5:145:7 | if ... |
|
||||
| local_dataflow.rb:142:7:142:9 | nil | local_dataflow.rb:141:38:142:9 | then ... |
|
||||
| local_dataflow.rb:143:5:144:16 | elsif ... | local_dataflow.rb:141:5:145:7 | if ... |
|
||||
| local_dataflow.rb:143:11:143:16 | [post] self | local_dataflow.rb:143:21:143:26 | self |
|
||||
| local_dataflow.rb:143:11:143:16 | [post] self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:11:143:16 | call to use | local_dataflow.rb:143:11:143:26 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:143:11:143:16 | call to use | local_dataflow.rb:143:11:143:26 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:143:11:143:16 | self | local_dataflow.rb:143:21:143:26 | self |
|
||||
| local_dataflow.rb:143:11:143:16 | self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:15:143:15 | x | local_dataflow.rb:143:25:143:25 | x |
|
||||
| local_dataflow.rb:143:15:143:15 | x | local_dataflow.rb:144:15:144:15 | x |
|
||||
| local_dataflow.rb:143:21:143:26 | [post] self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:21:143:26 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:143:21:143:26 | call to use | local_dataflow.rb:143:11:143:26 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:143:21:143:26 | call to use | local_dataflow.rb:143:11:143:26 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:143:21:143:26 | self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:21:143:26 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:143:25:143:25 | x | local_dataflow.rb:144:15:144:15 | x |
|
||||
| local_dataflow.rb:143:25:143:25 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:143:27:144:16 | then ... | local_dataflow.rb:143:5:144:16 | elsif ... |
|
||||
| local_dataflow.rb:144:11:144:16 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:144:11:144:16 | call to use | local_dataflow.rb:143:27:144:16 | then ... |
|
||||
| local_dataflow.rb:144:11:144:16 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:144:15:144:15 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:147:5:147:10 | [post] self | local_dataflow.rb:148:5:148:10 | self |
|
||||
| local_dataflow.rb:147:5:147:10 | self | local_dataflow.rb:148:5:148:10 | self |
|
||||
| local_dataflow.rb:147:9:147:9 | x | local_dataflow.rb:148:9:148:9 | x |
|
||||
| local_dataflow.rb:148:5:148:10 | call to use | local_dataflow.rb:132:12:148:10 | then ... |
|
||||
|
||||
@@ -19,6 +19,8 @@ ret
|
||||
| local_dataflow.rb:119:3:119:31 | call to sink |
|
||||
| local_dataflow.rb:123:3:123:50 | call to sink |
|
||||
| local_dataflow.rb:123:32:123:43 | call to puts |
|
||||
| local_dataflow.rb:127:3:127:8 | call to rand |
|
||||
| local_dataflow.rb:132:3:149:5 | if ... |
|
||||
arg
|
||||
| local_dataflow.rb:3:8:3:10 | self | local_dataflow.rb:3:8:3:10 | call to p | self |
|
||||
| local_dataflow.rb:3:10:3:10 | a | local_dataflow.rb:3:8:3:10 | call to p | position 0 |
|
||||
@@ -170,3 +172,61 @@ arg
|
||||
| local_dataflow.rb:123:26:123:45 | { ... } | local_dataflow.rb:123:8:123:45 | call to tap | block |
|
||||
| local_dataflow.rb:123:32:123:43 | self | local_dataflow.rb:123:32:123:43 | call to puts | self |
|
||||
| local_dataflow.rb:123:37:123:43 | "hello" | local_dataflow.rb:123:32:123:43 | call to puts | position 0 |
|
||||
| local_dataflow.rb:127:3:127:8 | self | local_dataflow.rb:127:3:127:8 | call to rand | self |
|
||||
| local_dataflow.rb:132:6:132:11 | self | local_dataflow.rb:132:6:132:11 | call to use | self |
|
||||
| local_dataflow.rb:132:10:132:10 | x | local_dataflow.rb:132:6:132:11 | call to use | position 0 |
|
||||
| local_dataflow.rb:133:8:133:13 | call to use | local_dataflow.rb:133:8:133:23 | [false] ... \|\| ... | self |
|
||||
| local_dataflow.rb:133:8:133:13 | call to use | local_dataflow.rb:133:8:133:23 | [true] ... \|\| ... | self |
|
||||
| local_dataflow.rb:133:8:133:13 | self | local_dataflow.rb:133:8:133:13 | call to use | self |
|
||||
| local_dataflow.rb:133:12:133:12 | x | local_dataflow.rb:133:8:133:13 | call to use | position 0 |
|
||||
| local_dataflow.rb:133:18:133:23 | call to use | local_dataflow.rb:133:8:133:23 | [false] ... \|\| ... | position 0 |
|
||||
| local_dataflow.rb:133:18:133:23 | call to use | local_dataflow.rb:133:8:133:23 | [true] ... \|\| ... | position 0 |
|
||||
| local_dataflow.rb:133:18:133:23 | self | local_dataflow.rb:133:18:133:23 | call to use | self |
|
||||
| local_dataflow.rb:133:22:133:22 | x | local_dataflow.rb:133:18:133:23 | call to use | position 0 |
|
||||
| local_dataflow.rb:134:7:134:12 | self | local_dataflow.rb:134:7:134:12 | call to use | self |
|
||||
| local_dataflow.rb:134:11:134:11 | x | local_dataflow.rb:134:7:134:12 | call to use | position 0 |
|
||||
| local_dataflow.rb:136:7:136:12 | self | local_dataflow.rb:136:7:136:12 | call to use | self |
|
||||
| local_dataflow.rb:136:11:136:11 | x | local_dataflow.rb:136:7:136:12 | call to use | position 0 |
|
||||
| local_dataflow.rb:137:10:137:15 | call to use | local_dataflow.rb:137:10:137:26 | [false] ... && ... | self |
|
||||
| local_dataflow.rb:137:10:137:15 | call to use | local_dataflow.rb:137:10:137:26 | [true] ... && ... | self |
|
||||
| local_dataflow.rb:137:10:137:15 | self | local_dataflow.rb:137:10:137:15 | call to use | self |
|
||||
| local_dataflow.rb:137:14:137:14 | x | local_dataflow.rb:137:10:137:15 | call to use | position 0 |
|
||||
| local_dataflow.rb:137:20:137:26 | [false] ! ... | local_dataflow.rb:137:10:137:26 | [false] ... && ... | position 0 |
|
||||
| local_dataflow.rb:137:20:137:26 | [true] ! ... | local_dataflow.rb:137:10:137:26 | [true] ... && ... | position 0 |
|
||||
| local_dataflow.rb:137:21:137:26 | call to use | local_dataflow.rb:137:20:137:26 | [false] ! ... | self |
|
||||
| local_dataflow.rb:137:21:137:26 | call to use | local_dataflow.rb:137:20:137:26 | [true] ! ... | self |
|
||||
| local_dataflow.rb:137:21:137:26 | self | local_dataflow.rb:137:21:137:26 | call to use | self |
|
||||
| local_dataflow.rb:137:25:137:25 | x | local_dataflow.rb:137:21:137:26 | call to use | position 0 |
|
||||
| local_dataflow.rb:141:8:141:14 | [false] ! ... | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... | self |
|
||||
| local_dataflow.rb:141:8:141:14 | [false] ! ... | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... | self |
|
||||
| local_dataflow.rb:141:8:141:14 | [true] ! ... | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... | self |
|
||||
| local_dataflow.rb:141:9:141:14 | call to use | local_dataflow.rb:141:8:141:14 | [false] ! ... | self |
|
||||
| local_dataflow.rb:141:9:141:14 | call to use | local_dataflow.rb:141:8:141:14 | [true] ! ... | self |
|
||||
| local_dataflow.rb:141:9:141:14 | self | local_dataflow.rb:141:9:141:14 | call to use | self |
|
||||
| local_dataflow.rb:141:13:141:13 | x | local_dataflow.rb:141:9:141:14 | call to use | position 0 |
|
||||
| local_dataflow.rb:141:19:141:37 | [false] ( ... ) | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... | position 0 |
|
||||
| local_dataflow.rb:141:19:141:37 | [true] ( ... ) | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... | position 0 |
|
||||
| local_dataflow.rb:141:20:141:25 | call to use | local_dataflow.rb:141:20:141:36 | [false] ... && ... | self |
|
||||
| local_dataflow.rb:141:20:141:25 | call to use | local_dataflow.rb:141:20:141:36 | [true] ... && ... | self |
|
||||
| local_dataflow.rb:141:20:141:25 | self | local_dataflow.rb:141:20:141:25 | call to use | self |
|
||||
| local_dataflow.rb:141:24:141:24 | x | local_dataflow.rb:141:20:141:25 | call to use | position 0 |
|
||||
| local_dataflow.rb:141:30:141:36 | [false] ! ... | local_dataflow.rb:141:20:141:36 | [false] ... && ... | position 0 |
|
||||
| local_dataflow.rb:141:30:141:36 | [true] ! ... | local_dataflow.rb:141:20:141:36 | [true] ... && ... | position 0 |
|
||||
| local_dataflow.rb:141:31:141:36 | call to use | local_dataflow.rb:141:30:141:36 | [false] ! ... | self |
|
||||
| local_dataflow.rb:141:31:141:36 | call to use | local_dataflow.rb:141:30:141:36 | [true] ! ... | self |
|
||||
| local_dataflow.rb:141:31:141:36 | self | local_dataflow.rb:141:31:141:36 | call to use | self |
|
||||
| local_dataflow.rb:141:35:141:35 | x | local_dataflow.rb:141:31:141:36 | call to use | position 0 |
|
||||
| local_dataflow.rb:143:11:143:16 | call to use | local_dataflow.rb:143:11:143:26 | [false] ... \|\| ... | self |
|
||||
| local_dataflow.rb:143:11:143:16 | call to use | local_dataflow.rb:143:11:143:26 | [true] ... \|\| ... | self |
|
||||
| local_dataflow.rb:143:11:143:16 | self | local_dataflow.rb:143:11:143:16 | call to use | self |
|
||||
| local_dataflow.rb:143:15:143:15 | x | local_dataflow.rb:143:11:143:16 | call to use | position 0 |
|
||||
| local_dataflow.rb:143:21:143:26 | call to use | local_dataflow.rb:143:11:143:26 | [false] ... \|\| ... | position 0 |
|
||||
| local_dataflow.rb:143:21:143:26 | call to use | local_dataflow.rb:143:11:143:26 | [true] ... \|\| ... | position 0 |
|
||||
| local_dataflow.rb:143:21:143:26 | self | local_dataflow.rb:143:21:143:26 | call to use | self |
|
||||
| local_dataflow.rb:143:25:143:25 | x | local_dataflow.rb:143:21:143:26 | call to use | position 0 |
|
||||
| local_dataflow.rb:144:11:144:16 | self | local_dataflow.rb:144:11:144:16 | call to use | self |
|
||||
| local_dataflow.rb:144:15:144:15 | x | local_dataflow.rb:144:11:144:16 | call to use | position 0 |
|
||||
| local_dataflow.rb:147:5:147:10 | self | local_dataflow.rb:147:5:147:10 | call to use | self |
|
||||
| local_dataflow.rb:147:9:147:9 | x | local_dataflow.rb:147:5:147:10 | call to use | position 0 |
|
||||
| local_dataflow.rb:148:5:148:10 | self | local_dataflow.rb:148:5:148:10 | call to use | self |
|
||||
| local_dataflow.rb:148:9:148:9 | x | local_dataflow.rb:148:5:148:10 | call to use | position 0 |
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
| file://:0:0:0:0 | parameter self of each(0) | file://:0:0:0:0 | [summary] read: argument self.any element in each(0) |
|
||||
| local_dataflow.rb:1:1:7:3 | self (foo) | local_dataflow.rb:3:8:3:10 | self |
|
||||
| local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:1:1:7:3 | self (foo) |
|
||||
| local_dataflow.rb:1:1:124:4 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self |
|
||||
| local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self |
|
||||
| local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a |
|
||||
| local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a |
|
||||
| local_dataflow.rb:2:3:2:7 | ... = ... | local_dataflow.rb:3:13:3:13 | b |
|
||||
@@ -354,3 +354,116 @@
|
||||
| local_dataflow.rb:123:8:123:20 | call to dup | local_dataflow.rb:123:8:123:45 | call to tap |
|
||||
| local_dataflow.rb:123:8:123:45 | call to tap | local_dataflow.rb:123:8:123:49 | call to dup |
|
||||
| local_dataflow.rb:123:26:123:45 | <captured> self | local_dataflow.rb:123:32:123:43 | self |
|
||||
| local_dataflow.rb:126:1:128:3 | self (use) | local_dataflow.rb:127:3:127:8 | self |
|
||||
| local_dataflow.rb:126:1:128:3 | self in use | local_dataflow.rb:126:1:128:3 | self (use) |
|
||||
| local_dataflow.rb:130:1:150:3 | self (use_use_madness) | local_dataflow.rb:132:6:132:11 | self |
|
||||
| local_dataflow.rb:130:1:150:3 | self in use_use_madness | local_dataflow.rb:130:1:150:3 | self (use_use_madness) |
|
||||
| local_dataflow.rb:131:3:131:8 | ... = ... | local_dataflow.rb:132:10:132:10 | x |
|
||||
| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... |
|
||||
| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... |
|
||||
| local_dataflow.rb:132:6:132:11 | [post] self | local_dataflow.rb:133:8:133:13 | self |
|
||||
| local_dataflow.rb:132:6:132:11 | self | local_dataflow.rb:133:8:133:13 | self |
|
||||
| local_dataflow.rb:132:10:132:10 | x | local_dataflow.rb:133:12:133:12 | x |
|
||||
| local_dataflow.rb:132:12:148:10 | then ... | local_dataflow.rb:132:3:149:5 | if ... |
|
||||
| local_dataflow.rb:133:8:133:13 | [post] self | local_dataflow.rb:133:18:133:23 | self |
|
||||
| local_dataflow.rb:133:8:133:13 | [post] self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:8:133:13 | call to use | local_dataflow.rb:133:8:133:23 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:133:8:133:13 | call to use | local_dataflow.rb:133:8:133:23 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:133:8:133:13 | self | local_dataflow.rb:133:18:133:23 | self |
|
||||
| local_dataflow.rb:133:8:133:13 | self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:12:133:12 | x | local_dataflow.rb:133:22:133:22 | x |
|
||||
| local_dataflow.rb:133:12:133:12 | x | local_dataflow.rb:134:11:134:11 | x |
|
||||
| local_dataflow.rb:133:18:133:23 | [post] self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:18:133:23 | [post] self | local_dataflow.rb:136:7:136:12 | self |
|
||||
| local_dataflow.rb:133:18:133:23 | call to use | local_dataflow.rb:133:8:133:23 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:133:18:133:23 | call to use | local_dataflow.rb:133:8:133:23 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:133:18:133:23 | self | local_dataflow.rb:134:7:134:12 | self |
|
||||
| local_dataflow.rb:133:18:133:23 | self | local_dataflow.rb:136:7:136:12 | self |
|
||||
| local_dataflow.rb:133:22:133:22 | x | local_dataflow.rb:134:11:134:11 | x |
|
||||
| local_dataflow.rb:133:22:133:22 | x | local_dataflow.rb:136:11:136:11 | x |
|
||||
| local_dataflow.rb:133:24:134:12 | then ... | local_dataflow.rb:133:5:139:7 | if ... |
|
||||
| local_dataflow.rb:134:7:134:12 | [post] self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:134:7:134:12 | call to use | local_dataflow.rb:133:24:134:12 | then ... |
|
||||
| local_dataflow.rb:134:7:134:12 | self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:134:11:134:11 | x | local_dataflow.rb:141:13:141:13 | x |
|
||||
| local_dataflow.rb:135:5:138:9 | else ... | local_dataflow.rb:133:5:139:7 | if ... |
|
||||
| local_dataflow.rb:136:7:136:12 | [post] self | local_dataflow.rb:137:10:137:15 | self |
|
||||
| local_dataflow.rb:136:7:136:12 | self | local_dataflow.rb:137:10:137:15 | self |
|
||||
| local_dataflow.rb:136:11:136:11 | x | local_dataflow.rb:137:14:137:14 | x |
|
||||
| local_dataflow.rb:137:7:138:9 | if ... | local_dataflow.rb:135:5:138:9 | else ... |
|
||||
| local_dataflow.rb:137:10:137:15 | [post] self | local_dataflow.rb:137:21:137:26 | self |
|
||||
| local_dataflow.rb:137:10:137:15 | [post] self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:10:137:15 | call to use | local_dataflow.rb:137:10:137:26 | [false] ... && ... |
|
||||
| local_dataflow.rb:137:10:137:15 | call to use | local_dataflow.rb:137:10:137:26 | [true] ... && ... |
|
||||
| local_dataflow.rb:137:10:137:15 | self | local_dataflow.rb:137:21:137:26 | self |
|
||||
| local_dataflow.rb:137:10:137:15 | self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:14:137:14 | x | local_dataflow.rb:137:25:137:25 | x |
|
||||
| local_dataflow.rb:137:14:137:14 | x | local_dataflow.rb:141:13:141:13 | x |
|
||||
| local_dataflow.rb:137:20:137:26 | [false] ! ... | local_dataflow.rb:137:10:137:26 | [false] ... && ... |
|
||||
| local_dataflow.rb:137:20:137:26 | [true] ! ... | local_dataflow.rb:137:10:137:26 | [true] ... && ... |
|
||||
| local_dataflow.rb:137:21:137:26 | [post] self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:21:137:26 | call to use | local_dataflow.rb:137:20:137:26 | [false] ! ... |
|
||||
| local_dataflow.rb:137:21:137:26 | call to use | local_dataflow.rb:137:20:137:26 | [true] ! ... |
|
||||
| local_dataflow.rb:137:21:137:26 | self | local_dataflow.rb:141:9:141:14 | self |
|
||||
| local_dataflow.rb:137:25:137:25 | x | local_dataflow.rb:141:13:141:13 | x |
|
||||
| local_dataflow.rb:141:8:141:14 | [false] ! ... | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:141:8:141:14 | [false] ! ... | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:141:8:141:14 | [true] ! ... | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:141:9:141:14 | [post] self | local_dataflow.rb:141:20:141:25 | self |
|
||||
| local_dataflow.rb:141:9:141:14 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:9:141:14 | call to use | local_dataflow.rb:141:8:141:14 | [false] ! ... |
|
||||
| local_dataflow.rb:141:9:141:14 | call to use | local_dataflow.rb:141:8:141:14 | [true] ! ... |
|
||||
| local_dataflow.rb:141:9:141:14 | self | local_dataflow.rb:141:20:141:25 | self |
|
||||
| local_dataflow.rb:141:9:141:14 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:13:141:13 | x | local_dataflow.rb:141:24:141:24 | x |
|
||||
| local_dataflow.rb:141:13:141:13 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:141:19:141:37 | [false] ( ... ) | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:141:19:141:37 | [true] ( ... ) | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:141:20:141:25 | [post] self | local_dataflow.rb:141:31:141:36 | self |
|
||||
| local_dataflow.rb:141:20:141:25 | [post] self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:20:141:25 | call to use | local_dataflow.rb:141:20:141:36 | [false] ... && ... |
|
||||
| local_dataflow.rb:141:20:141:25 | call to use | local_dataflow.rb:141:20:141:36 | [true] ... && ... |
|
||||
| local_dataflow.rb:141:20:141:25 | self | local_dataflow.rb:141:31:141:36 | self |
|
||||
| local_dataflow.rb:141:20:141:25 | self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:20:141:36 | [false] ... && ... | local_dataflow.rb:141:19:141:37 | [false] ( ... ) |
|
||||
| local_dataflow.rb:141:20:141:36 | [true] ... && ... | local_dataflow.rb:141:19:141:37 | [true] ( ... ) |
|
||||
| local_dataflow.rb:141:24:141:24 | x | local_dataflow.rb:141:35:141:35 | x |
|
||||
| local_dataflow.rb:141:24:141:24 | x | local_dataflow.rb:143:15:143:15 | x |
|
||||
| local_dataflow.rb:141:30:141:36 | [false] ! ... | local_dataflow.rb:141:20:141:36 | [false] ... && ... |
|
||||
| local_dataflow.rb:141:30:141:36 | [true] ! ... | local_dataflow.rb:141:20:141:36 | [true] ... && ... |
|
||||
| local_dataflow.rb:141:31:141:36 | [post] self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:31:141:36 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:31:141:36 | call to use | local_dataflow.rb:141:30:141:36 | [false] ! ... |
|
||||
| local_dataflow.rb:141:31:141:36 | call to use | local_dataflow.rb:141:30:141:36 | [true] ! ... |
|
||||
| local_dataflow.rb:141:31:141:36 | self | local_dataflow.rb:143:11:143:16 | self |
|
||||
| local_dataflow.rb:141:31:141:36 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:141:35:141:35 | x | local_dataflow.rb:143:15:143:15 | x |
|
||||
| local_dataflow.rb:141:35:141:35 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:141:38:142:9 | then ... | local_dataflow.rb:141:5:145:7 | if ... |
|
||||
| local_dataflow.rb:142:7:142:9 | nil | local_dataflow.rb:141:38:142:9 | then ... |
|
||||
| local_dataflow.rb:143:5:144:16 | elsif ... | local_dataflow.rb:141:5:145:7 | if ... |
|
||||
| local_dataflow.rb:143:11:143:16 | [post] self | local_dataflow.rb:143:21:143:26 | self |
|
||||
| local_dataflow.rb:143:11:143:16 | [post] self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:11:143:16 | call to use | local_dataflow.rb:143:11:143:26 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:143:11:143:16 | call to use | local_dataflow.rb:143:11:143:26 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:143:11:143:16 | self | local_dataflow.rb:143:21:143:26 | self |
|
||||
| local_dataflow.rb:143:11:143:16 | self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:15:143:15 | x | local_dataflow.rb:143:25:143:25 | x |
|
||||
| local_dataflow.rb:143:15:143:15 | x | local_dataflow.rb:144:15:144:15 | x |
|
||||
| local_dataflow.rb:143:21:143:26 | [post] self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:21:143:26 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:143:21:143:26 | call to use | local_dataflow.rb:143:11:143:26 | [false] ... \|\| ... |
|
||||
| local_dataflow.rb:143:21:143:26 | call to use | local_dataflow.rb:143:11:143:26 | [true] ... \|\| ... |
|
||||
| local_dataflow.rb:143:21:143:26 | self | local_dataflow.rb:144:11:144:16 | self |
|
||||
| local_dataflow.rb:143:21:143:26 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:143:25:143:25 | x | local_dataflow.rb:144:15:144:15 | x |
|
||||
| local_dataflow.rb:143:25:143:25 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:143:27:144:16 | then ... | local_dataflow.rb:143:5:144:16 | elsif ... |
|
||||
| local_dataflow.rb:144:11:144:16 | [post] self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:144:11:144:16 | call to use | local_dataflow.rb:143:27:144:16 | then ... |
|
||||
| local_dataflow.rb:144:11:144:16 | self | local_dataflow.rb:147:5:147:10 | self |
|
||||
| local_dataflow.rb:144:15:144:15 | x | local_dataflow.rb:147:9:147:9 | x |
|
||||
| local_dataflow.rb:147:5:147:10 | [post] self | local_dataflow.rb:148:5:148:10 | self |
|
||||
| local_dataflow.rb:147:5:147:10 | self | local_dataflow.rb:148:5:148:10 | self |
|
||||
| local_dataflow.rb:147:9:147:9 | x | local_dataflow.rb:148:9:148:9 | x |
|
||||
| local_dataflow.rb:148:5:148:10 | call to use | local_dataflow.rb:132:12:148:10 | then ... |
|
||||
|
||||
@@ -122,3 +122,29 @@ end
|
||||
def dup_tap
|
||||
sink(source(1).dup.tap { |x| puts "hello" }.dup) # $ hasValueFlow=1
|
||||
end
|
||||
|
||||
def use x
|
||||
rand()
|
||||
end
|
||||
|
||||
def use_use_madness
|
||||
x = ""
|
||||
if use(x)
|
||||
if use(x) || use(x)
|
||||
use(x)
|
||||
else
|
||||
use(x)
|
||||
if use(x) && !use(x)
|
||||
end
|
||||
end
|
||||
|
||||
if !use(x) || (use(x) && !use(x))
|
||||
nil
|
||||
elsif use(x) || use(x)
|
||||
use(x)
|
||||
end
|
||||
|
||||
use(x)
|
||||
use(x)
|
||||
end
|
||||
end
|
||||
@@ -38,6 +38,10 @@ parameterVariable
|
||||
| ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo |
|
||||
| ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a |
|
||||
| ssa.rb:66:15:66:15 | a | ssa.rb:66:15:66:15 | a |
|
||||
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 |
|
||||
parameterNoVariable
|
||||
| parameters.rb:45:22:45:22 | _ |
|
||||
parameterVariableNoAccess
|
||||
|
||||
@@ -164,6 +164,12 @@ definition
|
||||
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self |
|
||||
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured |
|
||||
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self |
|
||||
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x |
|
||||
read
|
||||
| class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self |
|
||||
| class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self |
|
||||
@@ -347,6 +353,18 @@ read
|
||||
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:84:6:86:8 | self |
|
||||
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
|
||||
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:85:10:85:22 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:92:7:92:8 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
|
||||
firstRead
|
||||
| class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self |
|
||||
| class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self |
|
||||
@@ -485,6 +503,18 @@ firstRead
|
||||
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:84:6:86:8 | self |
|
||||
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
|
||||
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:85:10:85:22 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:92:7:92:8 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
|
||||
lastRead
|
||||
| class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self |
|
||||
| class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self |
|
||||
@@ -624,6 +654,18 @@ lastRead
|
||||
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:84:6:86:8 | self |
|
||||
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
|
||||
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:85:10:85:22 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:92:7:92:8 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
|
||||
adjacentReads
|
||||
| class_variables.rb:26:1:29:3 | self (N) | class_variables.rb:26:1:29:3 | self | class_variables.rb:27:3:27:11 | self | class_variables.rb:28:3:28:7 | self |
|
||||
| instance_variables.rb:1:1:44:4 | self (instance_variables.rb) | instance_variables.rb:1:1:44:4 | self | instance_variables.rb:1:1:1:4 | self | instance_variables.rb:11:1:11:9 | self |
|
||||
@@ -674,6 +716,14 @@ adjacentReads
|
||||
| ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:39:8:39:9 | self | ssa.rb:41:3:41:13 | self |
|
||||
| ssa.rb:66:11:70:5 | <captured> captured | ssa.rb:65:3:65:10 | captured | ssa.rb:68:10:68:17 | captured | ssa.rb:69:5:69:12 | captured |
|
||||
| ssa.rb:66:11:70:5 | <captured> self | ssa.rb:64:1:72:3 | self | ssa.rb:67:5:67:10 | self | ssa.rb:68:5:68:17 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self | ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self | ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self | ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self | ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:101:10:101:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:101:10:101:10 | x |
|
||||
phi
|
||||
| parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | <uninitialized> |
|
||||
| parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:20 | ... = ... |
|
||||
@@ -689,3 +739,30 @@ phi
|
||||
| ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:45:3:45:7 | ... = ... |
|
||||
| ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:1:51:3 | <uninitialized> |
|
||||
| ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:14:49:19 | ... = ... |
|
||||
phiReadNode
|
||||
| parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name |
|
||||
| ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self |
|
||||
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:18:1:23:3 | self |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x |
|
||||
| ssa.rb:94:3:95:10 | SSA phi read(self) | ssa.rb:90:1:103:3 | self |
|
||||
| ssa.rb:94:3:95:10 | SSA phi read(x) | ssa.rb:91:3:91:3 | x |
|
||||
phiReadNodeRead
|
||||
| parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name | parameters.rb:26:8:26:11 | name |
|
||||
| ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self | ssa.rb:15:3:15:8 | self |
|
||||
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:18:1:23:3 | self | ssa.rb:20:5:20:10 | self |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
|
||||
phiReadInput
|
||||
| parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name |
|
||||
| ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self (m) |
|
||||
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:18:1:23:3 | self (m1) |
|
||||
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:19:9:19:9 | SSA phi read(self) |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self (m12) |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:94:3:95:10 | SSA phi read(self) |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:7 | ... = ... |
|
||||
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:94:3:95:10 | SSA phi read(x) |
|
||||
| ssa.rb:94:3:95:10 | SSA phi read(self) | ssa.rb:90:1:103:3 | self (m12) |
|
||||
| ssa.rb:94:3:95:10 | SSA phi read(x) | ssa.rb:91:3:91:7 | ... = ... |
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import codeql.ruby.AST
|
||||
import codeql.ruby.CFG
|
||||
import codeql.ruby.dataflow.SSA
|
||||
import codeql.ruby.dataflow.internal.SsaImpl
|
||||
import ExposedForTestingOnly
|
||||
|
||||
query predicate definition(Ssa::Definition def, Variable v) { def.getSourceVariable() = v }
|
||||
|
||||
@@ -24,3 +26,17 @@ query predicate adjacentReads(Ssa::Definition def, Variable v, CfgNode read1, Cf
|
||||
query predicate phi(Ssa::PhiNode phi, Variable v, Ssa::Definition input) {
|
||||
phi.getSourceVariable() = v and input = phi.getAnInput()
|
||||
}
|
||||
|
||||
query predicate phiReadNode(PhiReadNode phi, Variable v) { phi.getSourceVariable() = v }
|
||||
|
||||
query predicate phiReadNodeRead(PhiReadNode phi, Variable v, CfgNode read) {
|
||||
phi.getSourceVariable() = v and
|
||||
exists(BasicBlock bb, int i |
|
||||
ssaDefReachesReadExt(v, phi, bb, i) and
|
||||
read = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
query predicate phiReadInput(PhiReadNode phi, DefinitionExt inp) {
|
||||
phiHasInputFromBlockExt(phi, inp, _)
|
||||
}
|
||||
|
||||
@@ -85,4 +85,19 @@ def m11
|
||||
puts captured
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def m12(b1, b2, b3, b4)
|
||||
x = 0
|
||||
if (b1) then
|
||||
puts x
|
||||
elsif (b2) then
|
||||
puts x
|
||||
end
|
||||
# phi read for x
|
||||
if (b3) then
|
||||
puts x
|
||||
elsif (b4) then
|
||||
puts x
|
||||
end
|
||||
end
|
||||
@@ -279,6 +279,23 @@ variableAccess
|
||||
| ssa.rb:84:6:86:8 | self | ssa.rb:81:1:88:3 | self | ssa.rb:81:1:88:3 | m11 |
|
||||
| ssa.rb:85:10:85:22 | self | ssa.rb:81:1:88:3 | self | ssa.rb:81:1:88:3 | m11 |
|
||||
| ssa.rb:85:15:85:22 | captured | ssa.rb:82:3:82:10 | captured | ssa.rb:81:1:88:3 | m11 |
|
||||
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:92:7:92:8 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:93:5:93:10 | self | ssa.rb:90:1:103:3 | self | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:93:10:93:10 | x | ssa.rb:91:3:91:3 | x | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:94:10:94:11 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:95:5:95:10 | self | ssa.rb:90:1:103:3 | self | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:95:10:95:10 | x | ssa.rb:91:3:91:3 | x | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:98:7:98:8 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:99:5:99:10 | self | ssa.rb:90:1:103:3 | self | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:99:10:99:10 | x | ssa.rb:91:3:91:3 | x | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:100:10:100:11 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:101:5:101:10 | self | ssa.rb:90:1:103:3 | self | ssa.rb:90:1:103:3 | m12 |
|
||||
| ssa.rb:101:10:101:10 | x | ssa.rb:91:3:91:3 | x | ssa.rb:90:1:103:3 | m12 |
|
||||
explicitWrite
|
||||
| class_variables.rb:1:1:1:3 | @@x | class_variables.rb:1:1:1:8 | ... = ... |
|
||||
| class_variables.rb:19:3:19:5 | @@x | class_variables.rb:19:3:19:10 | ... = ... |
|
||||
@@ -349,6 +366,7 @@ explicitWrite
|
||||
| ssa.rb:69:5:69:12 | captured | ssa.rb:69:5:69:17 | ... = ... |
|
||||
| ssa.rb:75:3:75:10 | captured | ssa.rb:75:3:75:14 | ... = ... |
|
||||
| ssa.rb:82:3:82:10 | captured | ssa.rb:82:3:82:14 | ... = ... |
|
||||
| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:7 | ... = ... |
|
||||
implicitWrite
|
||||
| nested_scopes.rb:15:23:15:23 | a |
|
||||
| nested_scopes.rb:16:26:16:26 | x |
|
||||
@@ -390,6 +408,10 @@ implicitWrite
|
||||
| ssa.rb:53:8:53:10 | foo |
|
||||
| ssa.rb:64:8:64:8 | a |
|
||||
| ssa.rb:66:15:66:15 | a |
|
||||
| ssa.rb:90:9:90:10 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 |
|
||||
readAccess
|
||||
| class_variables.rb:3:1:3:5 | self |
|
||||
| class_variables.rb:3:3:3:5 | @@x |
|
||||
@@ -582,3 +604,15 @@ readAccess
|
||||
| ssa.rb:84:6:86:8 | self |
|
||||
| ssa.rb:85:10:85:22 | self |
|
||||
| ssa.rb:85:15:85:22 | captured |
|
||||
| ssa.rb:92:7:92:8 | b1 |
|
||||
| ssa.rb:93:5:93:10 | self |
|
||||
| ssa.rb:93:10:93:10 | x |
|
||||
| ssa.rb:94:10:94:11 | b2 |
|
||||
| ssa.rb:95:5:95:10 | self |
|
||||
| ssa.rb:95:10:95:10 | x |
|
||||
| ssa.rb:98:7:98:8 | b3 |
|
||||
| ssa.rb:99:5:99:10 | self |
|
||||
| ssa.rb:99:10:99:10 | x |
|
||||
| ssa.rb:100:10:100:11 | b4 |
|
||||
| ssa.rb:101:5:101:10 | self |
|
||||
| ssa.rb:101:10:101:10 | x |
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
| scopes.rb:43:2:43:4 | foo |
|
||||
| scopes.rb:46:5:46:8 | var2 |
|
||||
| ssa.rb:1:1:16:3 | self |
|
||||
| ssa.rb:1:1:88:3 | self |
|
||||
| ssa.rb:1:1:103:3 | self |
|
||||
| ssa.rb:1:7:1:7 | b |
|
||||
| ssa.rb:2:3:2:3 | i |
|
||||
| ssa.rb:18:1:23:3 | self |
|
||||
@@ -152,3 +152,9 @@
|
||||
| ssa.rb:75:3:75:10 | captured |
|
||||
| ssa.rb:81:1:88:3 | self |
|
||||
| ssa.rb:82:3:82:10 | captured |
|
||||
| ssa.rb:90:1:103:3 | self |
|
||||
| ssa.rb:90:9:90:10 | b1 |
|
||||
| ssa.rb:90:13:90:14 | b2 |
|
||||
| ssa.rb:90:17:90:18 | b3 |
|
||||
| ssa.rb:90:21:90:22 | b4 |
|
||||
| ssa.rb:91:3:91:3 | x |
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
| scopes.rb:37:1:39:3 | foo |
|
||||
| scopes.rb:41:1:49:3 | M |
|
||||
| ssa.rb:1:1:16:3 | m |
|
||||
| ssa.rb:1:1:88:3 | ssa.rb |
|
||||
| ssa.rb:1:1:103:3 | ssa.rb |
|
||||
| ssa.rb:18:1:23:3 | m1 |
|
||||
| ssa.rb:25:1:30:3 | m2 |
|
||||
| ssa.rb:26:3:28:5 | { ... } |
|
||||
@@ -75,3 +75,4 @@
|
||||
| ssa.rb:81:1:88:3 | m11 |
|
||||
| ssa.rb:83:7:87:5 | do ... end |
|
||||
| ssa.rb:84:10:86:8 | do ... end |
|
||||
| ssa.rb:90:1:103:3 | m12 |
|
||||
|
||||
@@ -264,8 +264,22 @@ module Make<InputSig Input> {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `bb` is in the dominance frontier of a block containing a
|
||||
* read of `v`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
|
||||
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
|
||||
lastRefIsRead(readbb, v)
|
||||
or
|
||||
exists(TPhiReadNode(v, readbb)) and
|
||||
not ref(readbb, _, v, _)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TDefinition =
|
||||
private newtype TDefinitionExt =
|
||||
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
|
||||
variableWrite(bb, i, v, _) and
|
||||
liveAfterWrite(bb, i, v)
|
||||
@@ -273,8 +287,16 @@ module Make<InputSig Input> {
|
||||
TPhiNode(SourceVariable v, BasicBlock bb) {
|
||||
inDefDominanceFrontier(bb, v) and
|
||||
liveAtEntry(bb, v)
|
||||
} or
|
||||
TPhiReadNode(SourceVariable v, BasicBlock bb) {
|
||||
inReadDominanceFrontier(bb, v) and
|
||||
liveAtEntry(bb, v) and
|
||||
// no need to create a phi-read if there is already a normal phi
|
||||
not any(PhiNode def).definesAt(v, bb, _)
|
||||
}
|
||||
|
||||
private class TDefinition = TWriteDef or TPhiNode;
|
||||
|
||||
private module SsaDefReaches {
|
||||
newtype TSsaRefKind =
|
||||
SsaActualRead() or
|
||||
@@ -283,6 +305,10 @@ module Make<InputSig Input> {
|
||||
|
||||
class SsaRead = SsaActualRead or SsaPhiRead;
|
||||
|
||||
class SsaDefExt = SsaDef or SsaPhiRead;
|
||||
|
||||
SsaDefExt ssaDefExt() { any() }
|
||||
|
||||
/**
|
||||
* A classification of SSA variable references into reads and definitions.
|
||||
*/
|
||||
@@ -307,98 +333,27 @@ module Make<InputSig Input> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `bb` is in the dominance frontier of a block containing a
|
||||
* read of `v`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
|
||||
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
|
||||
lastRefIsRead(readbb, v)
|
||||
or
|
||||
phiRead(readbb, v)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a phi-read node should be inserted for variable `v` at the beginning
|
||||
* of basic block `bb`.
|
||||
*
|
||||
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
|
||||
* instead of writes, and only if the dominance-frontier block does not already
|
||||
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
|
||||
* an internal implementation detail that is not exposed.
|
||||
*
|
||||
* The motivation for adding phi-reads is to improve performance of the use-use
|
||||
* calculation in cases where there is a large number of reads that can reach the
|
||||
* same join-point, and from there reach a large number of basic blocks. Example:
|
||||
*
|
||||
* ```cs
|
||||
* if (a)
|
||||
* use(x);
|
||||
* else if (b)
|
||||
* use(x);
|
||||
* else if (c)
|
||||
* use(x);
|
||||
* else if (d)
|
||||
* use(x);
|
||||
* // many more ifs ...
|
||||
*
|
||||
* // phi-read for `x` inserted here
|
||||
*
|
||||
* // program not mentioning `x`, with large basic block graph
|
||||
*
|
||||
* use(x);
|
||||
* ```
|
||||
*
|
||||
* Without phi-reads, the analysis has to replicate reachability for each of
|
||||
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
|
||||
* each conditional use of `x` to reach the basic block containing the phi-read
|
||||
* node for `x`, and only that basic block will have to compute reachability
|
||||
* through the remainder of the large program.
|
||||
*
|
||||
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
|
||||
* one SSA definition (without passing through another definition): Assume, for
|
||||
* the sake of contradiction, that there are two reaching definitions `def1` and
|
||||
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
|
||||
* dominating definition will prevent the other from reaching `phi-read`. So, at
|
||||
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
|
||||
* Then `def1` must go through one of its dominance-frontier blocks in order to
|
||||
* reach `phi-read`. However, such a block will always start with a (normal) phi
|
||||
* node, which contradicts reachability.
|
||||
*
|
||||
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
|
||||
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
|
||||
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
|
||||
* which contradicts reachability.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate phiRead(BasicBlock bb, SourceVariable v) {
|
||||
inReadDominanceFrontier(bb, v) and
|
||||
liveAtEntry(bb, v) and
|
||||
// only if there are no other references to `v` inside `bb`
|
||||
not ref(bb, _, v, _) and
|
||||
not exists(Definition def | def.definesAt(v, bb, _))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
|
||||
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
|
||||
* is `SsaDef()`).
|
||||
* either a read (when `k` is `SsaActualRead()`), an SSA definition (when `k`
|
||||
* is `SsaDef()`), or a phi-read (when `k` is `SsaPhiRead()`).
|
||||
*
|
||||
* Unlike `Liveness::ref`, this includes `phi` nodes.
|
||||
* Unlike `Liveness::ref`, this includes `phi` (read) nodes.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
|
||||
variableRead(bb, i, v, _) and
|
||||
k = SsaActualRead()
|
||||
or
|
||||
phiRead(bb, v) and
|
||||
i = -1 and
|
||||
k = SsaPhiRead()
|
||||
or
|
||||
any(Definition def).definesAt(v, bb, i) and
|
||||
k = SsaDef()
|
||||
any(DefinitionExt def).definesAt(v, bb, i, k)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `i`th node of basic block `bb` is a reference to `v`, and
|
||||
* this reference is not a phi-read.
|
||||
*/
|
||||
predicate ssaRefNonPhiRead(BasicBlock bb, int i, SourceVariable v) {
|
||||
ssaRef(bb, i, v, [SsaActualRead().(TSsaRefKind), SsaDef()])
|
||||
}
|
||||
|
||||
private newtype OrderedSsaRefIndex =
|
||||
@@ -445,37 +400,36 @@ module Make<InputSig Input> {
|
||||
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
|
||||
* basic block `bb`.
|
||||
*/
|
||||
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
|
||||
predicate ssaDefReachesRank(BasicBlock bb, DefinitionExt def, int rnk, SourceVariable v) {
|
||||
exists(int i |
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) and
|
||||
def.definesAt(v, bb, i)
|
||||
rnk = ssaRefRank(bb, i, v, ssaDefExt()) and
|
||||
def.definesAt(v, bb, i, _)
|
||||
)
|
||||
or
|
||||
ssaDefReachesRank(bb, def, rnk - 1, v) and
|
||||
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
|
||||
rnk = ssaRefRank(bb, _, v, SsaActualRead())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
|
||||
* basic block `bb`, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
|
||||
predicate ssaDefReachesReadWithinBlock(SourceVariable v, DefinitionExt def, BasicBlock bb, int i) {
|
||||
exists(int rnk |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
|
||||
rnk = ssaRefRank(bb, i, v, SsaActualRead())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
|
||||
v = def.getSourceVariable() and
|
||||
int ssaDefRank(DefinitionExt def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
|
||||
result = ssaRefRank(bb, i, v, k) and
|
||||
(
|
||||
ssaDefReachesRead(_, def, bb, i)
|
||||
ssaDefReachesReadExt(v, def, bb, i)
|
||||
or
|
||||
def.definesAt(_, bb, i)
|
||||
def.definesAt(v, bb, i, k)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -484,18 +438,38 @@ module Make<InputSig Input> {
|
||||
* last reference to `v` inside `bb`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
|
||||
predicate lastSsaRefExt(DefinitionExt def, SourceVariable v, BasicBlock bb, int i) {
|
||||
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
|
||||
}
|
||||
|
||||
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
|
||||
/** Gets a phi-read node into which `inp` is an input, if any. */
|
||||
pragma[nomagic]
|
||||
private DefinitionExt getAPhiReadOutput(DefinitionExt inp) {
|
||||
phiHasInputFromBlockExt(result.(PhiReadNode), inp, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
DefinitionExt getAnUltimateOutput(Definition def) { result = getAPhiReadOutput*(def) }
|
||||
|
||||
/**
|
||||
* Same as `lastSsaRefExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
|
||||
lastSsaRefExt(getAnUltimateOutput(def), v, bb, i) and
|
||||
ssaRefNonPhiRead(bb, i, v)
|
||||
}
|
||||
|
||||
predicate defOccursInBlock(DefinitionExt def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
|
||||
exists(ssaDefRank(def, v, bb, _, k))
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
|
||||
ssaDefReachesEndOfBlock(bb, def, _) and
|
||||
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
|
||||
private predicate ssaDefReachesThroughBlock(DefinitionExt def, BasicBlock bb) {
|
||||
exists(SourceVariable v |
|
||||
ssaDefReachesEndOfBlockExt(bb, def, v) and
|
||||
not defOccursInBlock(_, bb, v, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -503,85 +477,114 @@ module Make<InputSig Input> {
|
||||
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
|
||||
* predecessor of `bb2`, and the underlying variable for `def` is neither read
|
||||
* nor written in any block on the path between `bb1` and `bb2`.
|
||||
*
|
||||
* Phi reads are considered as normal reads for this predicate.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
||||
defOccursInBlock(def, bb1, _, _) and
|
||||
predicate varBlockReachesExt(DefinitionExt def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
|
||||
defOccursInBlock(def, bb1, v, _) and
|
||||
bb2 = getABasicBlockSuccessor(bb1)
|
||||
or
|
||||
exists(BasicBlock mid |
|
||||
varBlockReachesInclPhiRead(def, bb1, mid) and
|
||||
varBlockReachesExt(def, v, bb1, mid) and
|
||||
ssaDefReachesThroughBlock(def, mid) and
|
||||
bb2 = getABasicBlockSuccessor(mid)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
|
||||
varBlockReachesInclPhiRead(def, bb1, bb2) and
|
||||
defOccursInBlock(def, bb2, v, SsaPhiRead())
|
||||
private predicate phiReadStep(DefinitionExt def, PhiReadNode phi, BasicBlock bb1, BasicBlock bb2) {
|
||||
exists(SourceVariable v |
|
||||
varBlockReachesExt(pragma[only_bind_into](def), v, bb1, pragma[only_bind_into](bb2)) and
|
||||
phi.definesAt(v, bb2, _, _) and
|
||||
not ref(bb2, _, v, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
||||
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
|
||||
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
|
||||
private predicate varBlockReachesExclPhiRead(
|
||||
DefinitionExt def, SourceVariable v, BasicBlock bb1, BasicBlock bb2
|
||||
) {
|
||||
varBlockReachesExt(def, v, bb1, bb2) and
|
||||
ssaRefNonPhiRead(bb2, _, v)
|
||||
or
|
||||
exists(BasicBlock mid |
|
||||
varBlockReachesExclPhiRead(def, mid, bb2) and
|
||||
phiReadStep(def, _, bb1, mid)
|
||||
exists(PhiReadNode phi, BasicBlock mid |
|
||||
varBlockReachesExclPhiRead(phi, v, mid, bb2) and
|
||||
phiReadStep(def, phi, bb1, mid)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
|
||||
* the underlying variable `v` of `def` is accessed in basic block `bb2`
|
||||
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
|
||||
* `v` is neither read nor written in any block on the path between `bb1`
|
||||
* and `bb2`.
|
||||
* Same as `varBlockReachesExt`, but ignores phi-reads, and furthermore
|
||||
* `bb2` is restricted to blocks in which the underlying variable `v` of
|
||||
* `def` is referenced (either a read or a write).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
|
||||
varBlockReachesExclPhiRead(def, bb1, bb2) and
|
||||
not defOccursInBlock(def, bb1, _, SsaPhiRead())
|
||||
predicate varBlockReachesRef(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
|
||||
varBlockReachesExclPhiRead(getAnUltimateOutput(def), v, bb1, bb2) and
|
||||
ssaRefNonPhiRead(bb1, _, v)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate defAdjacentReadExt(DefinitionExt def, BasicBlock bb1, BasicBlock bb2, int i2) {
|
||||
exists(SourceVariable v |
|
||||
varBlockReachesExt(def, v, bb1, bb2) and
|
||||
ssaRefRank(bb2, i2, v, SsaActualRead()) = 1
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
|
||||
varBlockReaches(def, bb1, bb2) and
|
||||
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
|
||||
exists(SourceVariable v | varBlockReachesRef(def, v, bb1, bb2) |
|
||||
ssaRefRank(bb2, i2, v, SsaActualRead()) = 1
|
||||
or
|
||||
ssaRefRank(bb2, _, v, SsaPhiRead()) = 1 and
|
||||
ssaRefRank(bb2, i2, v, SsaActualRead()) = 2
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
|
||||
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
|
||||
* `bb` can reach a transitive successor `bb2` where `def` is no longer live,
|
||||
* and `v` is neither read nor written in any block on the path between `bb`
|
||||
* and `bb2`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
|
||||
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
|
||||
predicate varBlockReachesExitExt(DefinitionExt def, BasicBlock bb) {
|
||||
exists(BasicBlock bb2 | varBlockReachesExt(def, _, bb, bb2) |
|
||||
not defOccursInBlock(def, bb2, _, _) and
|
||||
not ssaDefReachesEndOfBlock(bb2, def, _)
|
||||
)
|
||||
or
|
||||
exists(BasicBlock mid |
|
||||
varBlockReachesExit(def, mid) and
|
||||
phiReadStep(def, _, bb, mid)
|
||||
not ssaDefReachesEndOfBlockExt(bb2, def, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
predicate phiReadExposedForTesting = phiRead/2;
|
||||
pragma[nomagic]
|
||||
private predicate varBlockReachesExitExclPhiRead(DefinitionExt def, BasicBlock bb) {
|
||||
exists(BasicBlock bb2, SourceVariable v |
|
||||
varBlockReachesExt(def, v, bb, bb2) and
|
||||
not defOccursInBlock(def, bb2, _, _) and
|
||||
not ssaDefReachesEndOfBlockExt(bb2, def, _) and
|
||||
not any(PhiReadNode phi).definesAt(v, bb2, _, _)
|
||||
)
|
||||
or
|
||||
exists(PhiReadNode phi, BasicBlock bb2 |
|
||||
varBlockReachesExitExclPhiRead(phi, bb2) and
|
||||
phiReadStep(def, phi, bb, bb2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `varBlockReachesExitExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
|
||||
varBlockReachesExitExclPhiRead(getAnUltimateOutput(def), bb)
|
||||
}
|
||||
}
|
||||
|
||||
private import SsaDefReaches
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate liveThrough(BasicBlock bb, SourceVariable v) {
|
||||
private predicate liveThroughExt(BasicBlock bb, SourceVariable v) {
|
||||
liveAtExit(bb, v) and
|
||||
not ssaRef(bb, _, v, SsaDef())
|
||||
not ssaRef(bb, _, v, ssaDefExt())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -592,7 +595,7 @@ module Make<InputSig Input> {
|
||||
* SSA definition of `v`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
|
||||
predicate ssaDefReachesEndOfBlockExt(BasicBlock bb, DefinitionExt def, SourceVariable v) {
|
||||
exists(int last |
|
||||
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
|
||||
ssaDefReachesRank(bb, def, last, v) and
|
||||
@@ -605,8 +608,31 @@ module Make<InputSig Input> {
|
||||
// the node. If two definitions dominate a node then one must dominate the
|
||||
// other, so therefore the definition of _closest_ is given by the dominator
|
||||
// tree. Thus, reaching definitions can be calculated in terms of dominance.
|
||||
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
|
||||
liveThrough(bb, pragma[only_bind_into](v))
|
||||
ssaDefReachesEndOfBlockExt(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
|
||||
liveThroughExt(bb, pragma[only_bind_into](v))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate phiReadReachesEndOfBlock(BasicBlock pred, BasicBlock bb, SourceVariable v) {
|
||||
exists(PhiReadNode phi |
|
||||
ssaDefReachesEndOfBlockExt(bb, phi, v) and
|
||||
pred = getImmediateBasicBlockDominator(phi.getBasicBlock())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Same as `ssaDefReachesEndOfBlockExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
|
||||
ssaDefReachesEndOfBlockExt(bb, def, v)
|
||||
or
|
||||
exists(BasicBlock mid |
|
||||
ssaDefReachesEndOfBlock(mid, def, v) and
|
||||
phiReadReachesEndOfBlock(mid, bb, v)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -623,20 +649,50 @@ module Make<InputSig Input> {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Holds if `inp` is an input to the phi (read) node `phi` along the edge originating in `bb`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate phiHasInputFromBlockExt(DefinitionExt phi, DefinitionExt inp, BasicBlock bb) {
|
||||
exists(SourceVariable v, BasicBlock bbDef |
|
||||
phi.definesAt(v, bbDef, _, _) and
|
||||
getABasicBlockPredecessor(bbDef) = bb and
|
||||
ssaDefReachesEndOfBlockExt(bb, inp, v)
|
||||
|
|
||||
phi instanceof PhiNode or
|
||||
phi instanceof PhiReadNode
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
|
||||
* basic block `bb`, without crossing another SSA definition of `v`. The read
|
||||
* is of kind `rk`.
|
||||
* basic block `bb`, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate ssaDefReachesReadExt(SourceVariable v, DefinitionExt def, BasicBlock bb, int i) {
|
||||
ssaDefReachesReadWithinBlock(v, def, bb, i)
|
||||
or
|
||||
ssaRef(bb, i, v, SsaActualRead()) and
|
||||
ssaDefReachesEndOfBlockExt(getABasicBlockPredecessor(bb), def, v) and
|
||||
not ssaDefReachesReadWithinBlock(v, _, bb, i)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Same as `ssaDefReachesReadExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
|
||||
ssaDefReachesReadWithinBlock(v, def, bb, i)
|
||||
or
|
||||
ssaRef(bb, i, v, any(SsaRead k)) and
|
||||
ssaRef(bb, i, v, SsaActualRead()) and
|
||||
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
|
||||
not ssaDefReachesReadWithinBlock(v, _, bb, i)
|
||||
not exists(Definition other | ssaDefReachesReadWithinBlock(v, other, bb, i))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -647,14 +703,32 @@ module Make<InputSig Input> {
|
||||
* path between them without any read of `def`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
|
||||
predicate adjacentDefReadExt(
|
||||
DefinitionExt def, SourceVariable v, BasicBlock bb1, int i1, BasicBlock bb2, int i2
|
||||
) {
|
||||
exists(int rnk |
|
||||
rnk = ssaDefRank(def, _, bb1, i1, _) and
|
||||
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
|
||||
variableRead(bb1, i2, _, _) and
|
||||
rnk = ssaDefRank(def, v, bb1, i1, _) and
|
||||
rnk + 1 = ssaDefRank(def, v, bb1, i2, SsaActualRead()) and
|
||||
variableRead(bb1, i2, v, _) and
|
||||
bb2 = bb1
|
||||
)
|
||||
or
|
||||
lastSsaRefExt(def, v, bb1, i1) and
|
||||
defAdjacentReadExt(def, bb1, bb2, i2)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Same as `adjacentDefReadExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
|
||||
exists(SourceVariable v |
|
||||
adjacentDefReadExt(getAnUltimateOutput(def), v, bb1, i1, bb2, i2) and
|
||||
ssaRefNonPhiRead(bb1, i1, v)
|
||||
)
|
||||
or
|
||||
lastSsaRef(def, _, bb1, i1) and
|
||||
defAdjacentRead(def, bb1, bb2, i2)
|
||||
}
|
||||
@@ -704,19 +778,41 @@ module Make<InputSig Input> {
|
||||
* without passing through another read or write.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate lastRefRedefExt(
|
||||
DefinitionExt def, SourceVariable v, BasicBlock bb, int i, DefinitionExt next
|
||||
) {
|
||||
// Next reference to `v` inside `bb` is a write
|
||||
exists(int rnk, int j |
|
||||
rnk = ssaDefRank(def, v, bb, i, _) and
|
||||
next.definesAt(v, bb, j, _) and
|
||||
rnk + 1 = ssaRefRank(bb, j, v, ssaDefExt())
|
||||
)
|
||||
or
|
||||
// Can reach a write using one or more steps
|
||||
lastSsaRefExt(def, v, bb, i) and
|
||||
exists(BasicBlock bb2 |
|
||||
varBlockReachesExt(def, v, bb, bb2) and
|
||||
1 = ssaDefRank(next, v, bb2, _, ssaDefExt())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Same as `lastRefRedefExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
|
||||
exists(SourceVariable v |
|
||||
// Next reference to `v` inside `bb` is a write
|
||||
exists(int rnk, int j |
|
||||
rnk = ssaDefRank(def, v, bb, i, _) and
|
||||
next.definesAt(v, bb, j) and
|
||||
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
|
||||
)
|
||||
or
|
||||
// Can reach a write using one or more steps
|
||||
lastRefRedefExt(getAnUltimateOutput(def), v, bb, i, next) and
|
||||
ssaRefNonPhiRead(bb, i, v)
|
||||
)
|
||||
or
|
||||
// Can reach a write using one or more steps
|
||||
exists(SourceVariable v |
|
||||
lastSsaRef(def, v, bb, i) and
|
||||
exists(BasicBlock bb2 |
|
||||
varBlockReaches(def, bb, bb2) and
|
||||
varBlockReachesRef(def, v, bb, bb2) and
|
||||
1 = ssaDefRank(next, v, bb2, _, SsaDef())
|
||||
)
|
||||
)
|
||||
@@ -770,6 +866,25 @@ module Make<InputSig Input> {
|
||||
* another read.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate lastRefExt(DefinitionExt def, BasicBlock bb, int i) {
|
||||
// Can reach another definition
|
||||
lastRefRedefExt(def, _, bb, i, _)
|
||||
or
|
||||
exists(SourceVariable v | lastSsaRefExt(def, v, bb, i) |
|
||||
// Can reach exit directly
|
||||
bb instanceof ExitBasicBlock
|
||||
or
|
||||
// Can reach a block using one or more steps, where `def` is no longer live
|
||||
varBlockReachesExitExt(def, bb)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: If this predicate is exposed, it should be cached.
|
||||
*
|
||||
* Same as `lastRefExt`, but ignores phi-reads.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate lastRef(Definition def, BasicBlock bb, int i) {
|
||||
// Can reach another definition
|
||||
lastRefRedef(def, bb, i, _)
|
||||
@@ -819,7 +934,7 @@ module Make<InputSig Input> {
|
||||
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
|
||||
|
||||
/** Gets a textual representation of this SSA definition. */
|
||||
string toString() { none() }
|
||||
string toString() { result = "SSA def(" + this.getSourceVariable() + ")" }
|
||||
}
|
||||
|
||||
/** An SSA definition that corresponds to a write. */
|
||||
@@ -829,13 +944,11 @@ module Make<InputSig Input> {
|
||||
private int i;
|
||||
|
||||
WriteDefinition() { this = TWriteDef(v, bb, i) }
|
||||
|
||||
override string toString() { result = "WriteDef" }
|
||||
}
|
||||
|
||||
/** A phi node. */
|
||||
class PhiNode extends Definition, TPhiNode {
|
||||
override string toString() { result = "Phi" }
|
||||
override string toString() { result = "SSA phi(" + this.getSourceVariable() + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -851,6 +964,120 @@ module Make<InputSig Input> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An extended static single assignment (SSA) definition.
|
||||
*
|
||||
* This is either a normal SSA definition (`Definition`) or a
|
||||
* phi-read node (`PhiReadNode`).
|
||||
*/
|
||||
class DefinitionExt extends TDefinitionExt {
|
||||
/** Gets the source variable underlying this SSA definition. */
|
||||
SourceVariable getSourceVariable() { this.definesAt(result, _, _, _) }
|
||||
|
||||
/**
|
||||
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
|
||||
* Phi nodes are considered to be at index `-1`, while normal variable writes
|
||||
* are at the index of the control flow node they wrap.
|
||||
*/
|
||||
final predicate definesAt(SourceVariable v, BasicBlock bb, int i, SsaRefKind kind) {
|
||||
this.(Definition).definesAt(v, bb, i) and
|
||||
kind = SsaDef()
|
||||
or
|
||||
this = TPhiReadNode(v, bb) and i = -1 and kind = SsaPhiRead()
|
||||
}
|
||||
|
||||
/** Gets the basic block to which this SSA definition belongs. */
|
||||
final BasicBlock getBasicBlock() { this.definesAt(_, result, _, _) }
|
||||
|
||||
/** Gets a textual representation of this SSA definition. */
|
||||
string toString() { result = this.(Definition).toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A phi-read node.
|
||||
*
|
||||
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
|
||||
* instead of writes, and only if the dominance-frontier block does not already
|
||||
* contain a normal phi node.
|
||||
*
|
||||
* The motivation for adding phi-reads is to improve performance of the use-use
|
||||
* calculation in cases where there is a large number of reads that can reach the
|
||||
* same join-point, and from there reach a large number of basic blocks. Example:
|
||||
*
|
||||
* ```cs
|
||||
* if (a)
|
||||
* use(x);
|
||||
* else if (b)
|
||||
* use(x);
|
||||
* else if (c)
|
||||
* use(x);
|
||||
* else if (d)
|
||||
* use(x);
|
||||
* // many more ifs ...
|
||||
*
|
||||
* // phi-read for `x` inserted here
|
||||
*
|
||||
* // program not mentioning `x`, with large basic block graph
|
||||
*
|
||||
* use(x);
|
||||
* ```
|
||||
*
|
||||
* Without phi-reads, the analysis has to replicate reachability for each of
|
||||
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
|
||||
* each conditional use of `x` to reach the basic block containing the phi-read
|
||||
* node for `x`, and only that basic block will have to compute reachability
|
||||
* through the remainder of the large program.
|
||||
*
|
||||
* Another motivation for phi-reads is when a large number of reads can reach
|
||||
* another large number of reads:
|
||||
*
|
||||
* ```cs
|
||||
* if (a)
|
||||
* use(x);
|
||||
* else if (b)
|
||||
* use(x);
|
||||
* else if (c)
|
||||
* use(x);
|
||||
* else if (d)
|
||||
* use(x);
|
||||
* // many more ifs ...
|
||||
*
|
||||
* // phi-read for `x` inserted here
|
||||
*
|
||||
* if (a)
|
||||
* use(x);
|
||||
* else if (b)
|
||||
* use(x);
|
||||
* else if (c)
|
||||
* use(x);
|
||||
* else if (d)
|
||||
* use(x);
|
||||
* // many more ifs ...
|
||||
* ```
|
||||
*
|
||||
* Without phi-reads, one needs to add `n*m` data-flow edges (assuming `n` reads
|
||||
* before the phi-read and `m` reads after the phi-read), whereas if we include
|
||||
* phi-reads in the data-flow graph, we only need to add `n+m` edges.
|
||||
*
|
||||
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
|
||||
* one SSA definition (without passing through another definition): Assume, for
|
||||
* the sake of contradiction, that there are two reaching definitions `def1` and
|
||||
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
|
||||
* dominating definition will prevent the other from reaching `phi-read`. So, at
|
||||
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
|
||||
* Then `def1` must go through one of its dominance-frontier blocks in order to
|
||||
* reach `phi-read`. However, such a block will always start with a (normal) phi
|
||||
* node, which contradicts reachability.
|
||||
*
|
||||
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
|
||||
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
|
||||
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
|
||||
* which contradicts reachability.
|
||||
*/
|
||||
class PhiReadNode extends DefinitionExt, TPhiReadNode {
|
||||
override string toString() { result = "SSA phi read(" + this.getSourceVariable() + ")" }
|
||||
}
|
||||
|
||||
/** Provides a set of consistency queries. */
|
||||
module Consistency {
|
||||
/** A definition that is relevant for the consistency queries. */
|
||||
@@ -861,18 +1088,40 @@ module Make<InputSig Input> {
|
||||
);
|
||||
}
|
||||
|
||||
/** A definition that is relevant for the consistency queries. */
|
||||
abstract class RelevantDefinitionExt extends DefinitionExt {
|
||||
/** Override this predicate to ensure locations in consistency results. */
|
||||
abstract predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
);
|
||||
}
|
||||
|
||||
/** Holds if a read can be reached from multiple definitions. */
|
||||
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
|
||||
ssaDefReachesRead(v, def, bb, i) and
|
||||
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
|
||||
}
|
||||
|
||||
/** Holds if a read can be reached from multiple definitions. */
|
||||
query predicate nonUniqueDefExt(
|
||||
RelevantDefinitionExt def, SourceVariable v, BasicBlock bb, int i
|
||||
) {
|
||||
ssaDefReachesReadExt(v, def, bb, i) and
|
||||
not exists(unique(DefinitionExt def0 | ssaDefReachesReadExt(v, def0, bb, i)))
|
||||
}
|
||||
|
||||
/** Holds if a read cannot be reached from a definition. */
|
||||
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
|
||||
variableRead(bb, i, v, _) and
|
||||
not ssaDefReachesRead(v, _, bb, i)
|
||||
}
|
||||
|
||||
/** Holds if a read cannot be reached from a definition. */
|
||||
query predicate readWithoutDefExt(SourceVariable v, BasicBlock bb, int i) {
|
||||
variableRead(bb, i, v, _) and
|
||||
not ssaDefReachesReadExt(v, _, bb, i)
|
||||
}
|
||||
|
||||
/** Holds if a definition cannot reach a read. */
|
||||
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
|
||||
v = def.getSourceVariable() and
|
||||
@@ -881,6 +1130,14 @@ module Make<InputSig Input> {
|
||||
not uncertainWriteDefinitionInput(_, def)
|
||||
}
|
||||
|
||||
/** Holds if a definition cannot reach a read. */
|
||||
query predicate deadDefExt(RelevantDefinitionExt def, SourceVariable v) {
|
||||
v = def.getSourceVariable() and
|
||||
not ssaDefReachesReadExt(_, def, _, _) and
|
||||
not phiHasInputFromBlockExt(_, def, _) and
|
||||
not uncertainWriteDefinitionInput(_, def)
|
||||
}
|
||||
|
||||
/** Holds if a read is not dominated by a definition. */
|
||||
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
|
||||
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
|
||||
@@ -892,5 +1149,19 @@ module Make<InputSig Input> {
|
||||
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a read is not dominated by a definition. */
|
||||
query predicate notDominatedByDefExt(
|
||||
RelevantDefinitionExt def, SourceVariable v, BasicBlock bb, int i
|
||||
) {
|
||||
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef, _) |
|
||||
ssaDefReachesReadWithinBlock(v, def, bb, i) and
|
||||
(bb != bbDef or i < iDef)
|
||||
or
|
||||
ssaDefReachesReadExt(v, def, bb, i) and
|
||||
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
|
||||
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,199 +1,199 @@
|
||||
| test.swift:6:9:6:13 | WriteDef | test.swift:7:15:7:15 | t1 |
|
||||
| test.swift:6:19:6:26 | call to source() | test.swift:6:9:6:13 | WriteDef |
|
||||
| test.swift:6:9:6:13 | SSA def(t1) | test.swift:7:15:7:15 | t1 |
|
||||
| test.swift:6:19:6:26 | call to source() | test.swift:6:9:6:13 | SSA def(t1) |
|
||||
| test.swift:7:15:7:15 | t1 | test.swift:8:10:8:10 | t1 |
|
||||
| test.swift:8:5:8:10 | WriteDef | test.swift:10:15:10:15 | t2 |
|
||||
| test.swift:8:10:8:10 | t1 | test.swift:8:5:8:10 | WriteDef |
|
||||
| test.swift:8:5:8:10 | SSA def(t2) | test.swift:10:15:10:15 | t2 |
|
||||
| test.swift:8:10:8:10 | t1 | test.swift:8:5:8:10 | SSA def(t2) |
|
||||
| test.swift:8:10:8:10 | t1 | test.swift:9:15:9:15 | t1 |
|
||||
| test.swift:9:15:9:15 | t1 | test.swift:11:8:11:8 | t1 |
|
||||
| test.swift:12:9:12:14 | WriteDef | test.swift:13:19:13:19 | t2 |
|
||||
| test.swift:12:14:12:14 | 0 | test.swift:12:9:12:14 | WriteDef |
|
||||
| test.swift:15:5:15:5 | Phi | test.swift:15:15:15:15 | t2 |
|
||||
| test.swift:17:5:17:10 | WriteDef | test.swift:21:15:21:15 | t1 |
|
||||
| test.swift:17:10:17:10 | 0 | test.swift:17:5:17:10 | WriteDef |
|
||||
| test.swift:29:18:29:21 | WriteDef | test.swift:30:15:30:15 | x |
|
||||
| test.swift:29:18:29:21 | x | test.swift:29:18:29:21 | WriteDef |
|
||||
| test.swift:29:26:29:29 | WriteDef | test.swift:31:15:31:15 | y |
|
||||
| test.swift:29:26:29:29 | y | test.swift:29:26:29:29 | WriteDef |
|
||||
| test.swift:42:16:42:19 | WriteDef | test.swift:45:8:45:8 | b |
|
||||
| test.swift:42:16:42:19 | b | test.swift:42:16:42:19 | WriteDef |
|
||||
| test.swift:43:9:43:13 | WriteDef | test.swift:46:13:46:13 | t1 |
|
||||
| test.swift:43:19:43:26 | call to source() | test.swift:43:9:43:13 | WriteDef |
|
||||
| test.swift:46:9:46:13 | WriteDef | test.swift:50:5:50:5 | Phi |
|
||||
| test.swift:46:13:46:13 | t1 | test.swift:46:9:46:13 | WriteDef |
|
||||
| test.swift:48:9:48:13 | WriteDef | test.swift:50:5:50:5 | Phi |
|
||||
| test.swift:48:13:48:13 | 1 | test.swift:48:9:48:13 | WriteDef |
|
||||
| test.swift:50:5:50:5 | Phi | test.swift:50:15:50:15 | t |
|
||||
| test.swift:54:5:54:18 | WriteDef | test.swift:53:1:56:1 | arg[return] |
|
||||
| test.swift:54:11:54:18 | call to source() | test.swift:54:5:54:18 | WriteDef |
|
||||
| test.swift:59:9:59:12 | WriteDef | test.swift:60:15:60:15 | x |
|
||||
| test.swift:59:18:59:18 | 0 | test.swift:59:9:59:12 | WriteDef |
|
||||
| test.swift:12:9:12:14 | SSA def(t2) | test.swift:13:19:13:19 | t2 |
|
||||
| test.swift:12:14:12:14 | 0 | test.swift:12:9:12:14 | SSA def(t2) |
|
||||
| test.swift:15:5:15:5 | SSA phi(t2) | test.swift:15:15:15:15 | t2 |
|
||||
| test.swift:17:5:17:10 | SSA def(t1) | test.swift:21:15:21:15 | t1 |
|
||||
| test.swift:17:10:17:10 | 0 | test.swift:17:5:17:10 | SSA def(t1) |
|
||||
| test.swift:29:18:29:21 | SSA def(x) | test.swift:30:15:30:15 | x |
|
||||
| test.swift:29:18:29:21 | x | test.swift:29:18:29:21 | SSA def(x) |
|
||||
| test.swift:29:26:29:29 | SSA def(y) | test.swift:31:15:31:15 | y |
|
||||
| test.swift:29:26:29:29 | y | test.swift:29:26:29:29 | SSA def(y) |
|
||||
| test.swift:42:16:42:19 | SSA def(b) | test.swift:45:8:45:8 | b |
|
||||
| test.swift:42:16:42:19 | b | test.swift:42:16:42:19 | SSA def(b) |
|
||||
| test.swift:43:9:43:13 | SSA def(t1) | test.swift:46:13:46:13 | t1 |
|
||||
| test.swift:43:19:43:26 | call to source() | test.swift:43:9:43:13 | SSA def(t1) |
|
||||
| test.swift:46:9:46:13 | SSA def(t) | test.swift:50:5:50:5 | SSA phi(t) |
|
||||
| test.swift:46:13:46:13 | t1 | test.swift:46:9:46:13 | SSA def(t) |
|
||||
| test.swift:48:9:48:13 | SSA def(t) | test.swift:50:5:50:5 | SSA phi(t) |
|
||||
| test.swift:48:13:48:13 | 1 | test.swift:48:9:48:13 | SSA def(t) |
|
||||
| test.swift:50:5:50:5 | SSA phi(t) | test.swift:50:15:50:15 | t |
|
||||
| test.swift:54:5:54:18 | SSA def(arg) | test.swift:53:1:56:1 | arg[return] |
|
||||
| test.swift:54:11:54:18 | call to source() | test.swift:54:5:54:18 | SSA def(arg) |
|
||||
| test.swift:59:9:59:12 | SSA def(x) | test.swift:60:15:60:15 | x |
|
||||
| test.swift:59:18:59:18 | 0 | test.swift:59:9:59:12 | SSA def(x) |
|
||||
| test.swift:60:15:60:15 | x | test.swift:61:23:61:23 | x |
|
||||
| test.swift:61:22:61:23 | &... | test.swift:62:15:62:15 | x |
|
||||
| test.swift:61:22:61:23 | [post] &... | test.swift:62:15:62:15 | x |
|
||||
| test.swift:61:23:61:23 | x | test.swift:61:22:61:23 | &... |
|
||||
| test.swift:65:16:65:28 | WriteDef | test.swift:66:21:66:21 | arg1 |
|
||||
| test.swift:65:16:65:28 | arg1 | test.swift:65:16:65:28 | WriteDef |
|
||||
| test.swift:65:33:65:45 | WriteDef | test.swift:67:12:67:12 | arg2 |
|
||||
| test.swift:65:33:65:45 | arg2 | test.swift:65:33:65:45 | WriteDef |
|
||||
| test.swift:66:9:66:15 | WriteDef | test.swift:68:12:68:12 | temp |
|
||||
| test.swift:66:21:66:21 | arg1 | test.swift:66:9:66:15 | WriteDef |
|
||||
| test.swift:67:5:67:12 | WriteDef | test.swift:65:1:70:1 | arg1[return] |
|
||||
| test.swift:67:12:67:12 | arg2 | test.swift:67:5:67:12 | WriteDef |
|
||||
| test.swift:68:5:68:12 | WriteDef | test.swift:65:1:70:1 | arg2[return] |
|
||||
| test.swift:68:12:68:12 | temp | test.swift:68:5:68:12 | WriteDef |
|
||||
| test.swift:73:9:73:12 | WriteDef | test.swift:75:22:75:22 | x |
|
||||
| test.swift:73:18:73:25 | call to source() | test.swift:73:9:73:12 | WriteDef |
|
||||
| test.swift:74:9:74:12 | WriteDef | test.swift:75:32:75:32 | y |
|
||||
| test.swift:74:18:74:18 | 0 | test.swift:74:9:74:12 | WriteDef |
|
||||
| test.swift:65:16:65:28 | SSA def(arg1) | test.swift:66:21:66:21 | arg1 |
|
||||
| test.swift:65:16:65:28 | arg1 | test.swift:65:16:65:28 | SSA def(arg1) |
|
||||
| test.swift:65:33:65:45 | SSA def(arg2) | test.swift:67:12:67:12 | arg2 |
|
||||
| test.swift:65:33:65:45 | arg2 | test.swift:65:33:65:45 | SSA def(arg2) |
|
||||
| test.swift:66:9:66:15 | SSA def(temp) | test.swift:68:12:68:12 | temp |
|
||||
| test.swift:66:21:66:21 | arg1 | test.swift:66:9:66:15 | SSA def(temp) |
|
||||
| test.swift:67:5:67:12 | SSA def(arg1) | test.swift:65:1:70:1 | arg1[return] |
|
||||
| test.swift:67:12:67:12 | arg2 | test.swift:67:5:67:12 | SSA def(arg1) |
|
||||
| test.swift:68:5:68:12 | SSA def(arg2) | test.swift:65:1:70:1 | arg2[return] |
|
||||
| test.swift:68:12:68:12 | temp | test.swift:68:5:68:12 | SSA def(arg2) |
|
||||
| test.swift:73:9:73:12 | SSA def(x) | test.swift:75:22:75:22 | x |
|
||||
| test.swift:73:18:73:25 | call to source() | test.swift:73:9:73:12 | SSA def(x) |
|
||||
| test.swift:74:9:74:12 | SSA def(y) | test.swift:75:32:75:32 | y |
|
||||
| test.swift:74:18:74:18 | 0 | test.swift:74:9:74:12 | SSA def(y) |
|
||||
| test.swift:75:21:75:22 | &... | test.swift:76:15:76:15 | x |
|
||||
| test.swift:75:21:75:22 | [post] &... | test.swift:76:15:76:15 | x |
|
||||
| test.swift:75:22:75:22 | x | test.swift:75:21:75:22 | &... |
|
||||
| test.swift:75:31:75:32 | &... | test.swift:77:15:77:15 | y |
|
||||
| test.swift:75:31:75:32 | [post] &... | test.swift:77:15:77:15 | y |
|
||||
| test.swift:75:32:75:32 | y | test.swift:75:31:75:32 | &... |
|
||||
| test.swift:81:5:81:18 | WriteDef | test.swift:80:1:82:1 | arg[return] |
|
||||
| test.swift:81:11:81:18 | call to source() | test.swift:81:5:81:18 | WriteDef |
|
||||
| test.swift:84:1:91:1 | Phi | test.swift:84:1:91:1 | arg[return] |
|
||||
| test.swift:84:48:84:54 | WriteDef | test.swift:85:8:85:8 | bool |
|
||||
| test.swift:84:48:84:54 | bool | test.swift:84:48:84:54 | WriteDef |
|
||||
| test.swift:86:9:86:22 | WriteDef | test.swift:84:1:91:1 | Phi |
|
||||
| test.swift:86:15:86:22 | call to source() | test.swift:86:9:86:22 | WriteDef |
|
||||
| test.swift:89:9:89:22 | WriteDef | test.swift:84:1:91:1 | Phi |
|
||||
| test.swift:89:15:89:22 | call to source() | test.swift:89:9:89:22 | WriteDef |
|
||||
| test.swift:93:17:93:23 | WriteDef | test.swift:104:50:104:50 | bool |
|
||||
| test.swift:93:17:93:23 | bool | test.swift:93:17:93:23 | WriteDef |
|
||||
| test.swift:95:13:95:16 | WriteDef | test.swift:96:19:96:19 | x |
|
||||
| test.swift:95:22:95:22 | 0 | test.swift:95:13:95:16 | WriteDef |
|
||||
| test.swift:81:5:81:18 | SSA def(arg) | test.swift:80:1:82:1 | arg[return] |
|
||||
| test.swift:81:11:81:18 | call to source() | test.swift:81:5:81:18 | SSA def(arg) |
|
||||
| test.swift:84:1:91:1 | SSA phi(arg) | test.swift:84:1:91:1 | arg[return] |
|
||||
| test.swift:84:48:84:54 | SSA def(bool) | test.swift:85:8:85:8 | bool |
|
||||
| test.swift:84:48:84:54 | bool | test.swift:84:48:84:54 | SSA def(bool) |
|
||||
| test.swift:86:9:86:22 | SSA def(arg) | test.swift:84:1:91:1 | SSA phi(arg) |
|
||||
| test.swift:86:15:86:22 | call to source() | test.swift:86:9:86:22 | SSA def(arg) |
|
||||
| test.swift:89:9:89:22 | SSA def(arg) | test.swift:84:1:91:1 | SSA phi(arg) |
|
||||
| test.swift:89:15:89:22 | call to source() | test.swift:89:9:89:22 | SSA def(arg) |
|
||||
| test.swift:93:17:93:23 | SSA def(bool) | test.swift:104:50:104:50 | bool |
|
||||
| test.swift:93:17:93:23 | bool | test.swift:93:17:93:23 | SSA def(bool) |
|
||||
| test.swift:95:13:95:16 | SSA def(x) | test.swift:96:19:96:19 | x |
|
||||
| test.swift:95:22:95:22 | 0 | test.swift:95:13:95:16 | SSA def(x) |
|
||||
| test.swift:96:19:96:19 | x | test.swift:97:40:97:40 | x |
|
||||
| test.swift:97:39:97:40 | &... | test.swift:98:19:98:19 | x |
|
||||
| test.swift:97:39:97:40 | [post] &... | test.swift:98:19:98:19 | x |
|
||||
| test.swift:97:40:97:40 | x | test.swift:97:39:97:40 | &... |
|
||||
| test.swift:102:13:102:16 | WriteDef | test.swift:103:19:103:19 | x |
|
||||
| test.swift:102:22:102:22 | 0 | test.swift:102:13:102:16 | WriteDef |
|
||||
| test.swift:102:13:102:16 | SSA def(x) | test.swift:103:19:103:19 | x |
|
||||
| test.swift:102:22:102:22 | 0 | test.swift:102:13:102:16 | SSA def(x) |
|
||||
| test.swift:103:19:103:19 | x | test.swift:104:41:104:41 | x |
|
||||
| test.swift:104:40:104:41 | &... | test.swift:105:19:105:19 | x |
|
||||
| test.swift:104:40:104:41 | [post] &... | test.swift:105:19:105:19 | x |
|
||||
| test.swift:104:41:104:41 | x | test.swift:104:40:104:41 | &... |
|
||||
| test.swift:109:9:109:14 | WriteDef | test.swift:110:12:110:12 | arg |
|
||||
| test.swift:109:9:109:14 | arg | test.swift:109:9:109:14 | WriteDef |
|
||||
| test.swift:113:14:113:19 | WriteDef | test.swift:114:19:114:19 | arg |
|
||||
| test.swift:113:14:113:19 | arg | test.swift:113:14:113:19 | WriteDef |
|
||||
| test.swift:113:24:113:41 | WriteDef | test.swift:114:12:114:12 | lambda |
|
||||
| test.swift:113:24:113:41 | lambda | test.swift:113:24:113:41 | WriteDef |
|
||||
| test.swift:118:9:118:12 | WriteDef | test.swift:119:31:119:31 | x |
|
||||
| test.swift:118:18:118:25 | call to source() | test.swift:118:9:118:12 | WriteDef |
|
||||
| test.swift:119:9:119:12 | WriteDef | test.swift:120:15:120:15 | y |
|
||||
| test.swift:119:18:119:44 | call to forward(arg:lambda:) | test.swift:119:9:119:12 | WriteDef |
|
||||
| test.swift:122:9:122:12 | WriteDef | test.swift:126:15:126:15 | z |
|
||||
| test.swift:122:18:125:6 | call to forward(arg:lambda:) | test.swift:122:9:122:12 | WriteDef |
|
||||
| test.swift:123:10:123:13 | WriteDef | test.swift:124:16:124:16 | i |
|
||||
| test.swift:123:10:123:13 | i | test.swift:123:10:123:13 | WriteDef |
|
||||
| test.swift:128:9:128:16 | WriteDef | test.swift:132:15:132:15 | clean |
|
||||
| test.swift:128:22:131:6 | call to forward(arg:lambda:) | test.swift:128:9:128:16 | WriteDef |
|
||||
| test.swift:141:9:141:9 | WriteDef | test.swift:145:15:145:15 | lambda2 |
|
||||
| test.swift:141:19:144:5 | { ... } | test.swift:141:9:141:9 | WriteDef |
|
||||
| test.swift:142:10:142:13 | WriteDef | test.swift:143:16:143:16 | i |
|
||||
| test.swift:142:10:142:13 | i | test.swift:142:10:142:13 | WriteDef |
|
||||
| test.swift:147:9:147:9 | WriteDef | test.swift:151:15:151:15 | lambdaSource |
|
||||
| test.swift:147:24:150:5 | { ... } | test.swift:147:9:147:9 | WriteDef |
|
||||
| test.swift:109:9:109:14 | SSA def(arg) | test.swift:110:12:110:12 | arg |
|
||||
| test.swift:109:9:109:14 | arg | test.swift:109:9:109:14 | SSA def(arg) |
|
||||
| test.swift:113:14:113:19 | SSA def(arg) | test.swift:114:19:114:19 | arg |
|
||||
| test.swift:113:14:113:19 | arg | test.swift:113:14:113:19 | SSA def(arg) |
|
||||
| test.swift:113:24:113:41 | SSA def(lambda) | test.swift:114:12:114:12 | lambda |
|
||||
| test.swift:113:24:113:41 | lambda | test.swift:113:24:113:41 | SSA def(lambda) |
|
||||
| test.swift:118:9:118:12 | SSA def(x) | test.swift:119:31:119:31 | x |
|
||||
| test.swift:118:18:118:25 | call to source() | test.swift:118:9:118:12 | SSA def(x) |
|
||||
| test.swift:119:9:119:12 | SSA def(y) | test.swift:120:15:120:15 | y |
|
||||
| test.swift:119:18:119:44 | call to forward(arg:lambda:) | test.swift:119:9:119:12 | SSA def(y) |
|
||||
| test.swift:122:9:122:12 | SSA def(z) | test.swift:126:15:126:15 | z |
|
||||
| test.swift:122:18:125:6 | call to forward(arg:lambda:) | test.swift:122:9:122:12 | SSA def(z) |
|
||||
| test.swift:123:10:123:13 | SSA def(i) | test.swift:124:16:124:16 | i |
|
||||
| test.swift:123:10:123:13 | i | test.swift:123:10:123:13 | SSA def(i) |
|
||||
| test.swift:128:9:128:16 | SSA def(clean) | test.swift:132:15:132:15 | clean |
|
||||
| test.swift:128:22:131:6 | call to forward(arg:lambda:) | test.swift:128:9:128:16 | SSA def(clean) |
|
||||
| test.swift:141:9:141:9 | SSA def(lambda2) | test.swift:145:15:145:15 | lambda2 |
|
||||
| test.swift:141:19:144:5 | { ... } | test.swift:141:9:141:9 | SSA def(lambda2) |
|
||||
| test.swift:142:10:142:13 | SSA def(i) | test.swift:143:16:143:16 | i |
|
||||
| test.swift:142:10:142:13 | i | test.swift:142:10:142:13 | SSA def(i) |
|
||||
| test.swift:147:9:147:9 | SSA def(lambdaSource) | test.swift:151:15:151:15 | lambdaSource |
|
||||
| test.swift:147:24:150:5 | { ... } | test.swift:147:9:147:9 | SSA def(lambdaSource) |
|
||||
| test.swift:151:15:151:15 | lambdaSource | test.swift:159:16:159:16 | lambdaSource |
|
||||
| test.swift:153:9:153:9 | WriteDef | test.swift:157:5:157:5 | lambdaSink |
|
||||
| test.swift:153:22:156:5 | { ... } | test.swift:153:9:153:9 | WriteDef |
|
||||
| test.swift:154:10:154:13 | WriteDef | test.swift:155:19:155:19 | i |
|
||||
| test.swift:154:10:154:13 | i | test.swift:154:10:154:13 | WriteDef |
|
||||
| test.swift:153:9:153:9 | SSA def(lambdaSink) | test.swift:157:5:157:5 | lambdaSink |
|
||||
| test.swift:153:22:156:5 | { ... } | test.swift:153:9:153:9 | SSA def(lambdaSink) |
|
||||
| test.swift:154:10:154:13 | SSA def(i) | test.swift:155:19:155:19 | i |
|
||||
| test.swift:154:10:154:13 | i | test.swift:154:10:154:13 | SSA def(i) |
|
||||
| test.swift:157:5:157:5 | lambdaSink | test.swift:159:5:159:5 | lambdaSink |
|
||||
| test.swift:162:7:162:7 | WriteDef | test.swift:162:7:162:7 | self[return] |
|
||||
| test.swift:162:7:162:7 | self | test.swift:162:7:162:7 | WriteDef |
|
||||
| test.swift:163:7:163:7 | self | test.swift:163:7:163:7 | WriteDef |
|
||||
| test.swift:163:7:163:7 | self | test.swift:163:7:163:7 | WriteDef |
|
||||
| test.swift:163:7:163:7 | self | test.swift:163:7:163:7 | WriteDef |
|
||||
| test.swift:163:7:163:7 | value | test.swift:163:7:163:7 | WriteDef |
|
||||
| test.swift:165:3:165:3 | WriteDef | test.swift:166:5:166:5 | self |
|
||||
| test.swift:165:3:165:3 | self | test.swift:165:3:165:3 | WriteDef |
|
||||
| test.swift:162:7:162:7 | SSA def(self) | test.swift:162:7:162:7 | self[return] |
|
||||
| test.swift:162:7:162:7 | self | test.swift:162:7:162:7 | SSA def(self) |
|
||||
| test.swift:163:7:163:7 | self | test.swift:163:7:163:7 | SSA def(self) |
|
||||
| test.swift:163:7:163:7 | self | test.swift:163:7:163:7 | SSA def(self) |
|
||||
| test.swift:163:7:163:7 | self | test.swift:163:7:163:7 | SSA def(self) |
|
||||
| test.swift:163:7:163:7 | value | test.swift:163:7:163:7 | SSA def(value) |
|
||||
| test.swift:165:3:165:3 | SSA def(self) | test.swift:166:5:166:5 | self |
|
||||
| test.swift:165:3:165:3 | self | test.swift:165:3:165:3 | SSA def(self) |
|
||||
| test.swift:166:5:166:5 | [post] self | test.swift:165:3:167:3 | self[return] |
|
||||
| test.swift:166:5:166:5 | self | test.swift:165:3:167:3 | self[return] |
|
||||
| test.swift:169:8:169:8 | WriteDef | test.swift:170:5:170:5 | self |
|
||||
| test.swift:169:8:169:8 | self | test.swift:169:8:169:8 | WriteDef |
|
||||
| test.swift:169:12:169:22 | WriteDef | test.swift:170:9:170:9 | value |
|
||||
| test.swift:169:12:169:22 | value | test.swift:169:12:169:22 | WriteDef |
|
||||
| test.swift:169:8:169:8 | SSA def(self) | test.swift:170:5:170:5 | self |
|
||||
| test.swift:169:8:169:8 | self | test.swift:169:8:169:8 | SSA def(self) |
|
||||
| test.swift:169:12:169:22 | SSA def(value) | test.swift:170:9:170:9 | value |
|
||||
| test.swift:169:12:169:22 | value | test.swift:169:12:169:22 | SSA def(value) |
|
||||
| test.swift:170:5:170:5 | [post] self | test.swift:169:3:171:3 | self[return] |
|
||||
| test.swift:170:5:170:5 | self | test.swift:169:3:171:3 | self[return] |
|
||||
| test.swift:173:8:173:8 | WriteDef | test.swift:174:12:174:12 | self |
|
||||
| test.swift:173:8:173:8 | self | test.swift:173:8:173:8 | WriteDef |
|
||||
| test.swift:173:8:173:8 | SSA def(self) | test.swift:174:12:174:12 | self |
|
||||
| test.swift:173:8:173:8 | self | test.swift:173:8:173:8 | SSA def(self) |
|
||||
| test.swift:174:12:174:12 | [post] self | test.swift:173:3:175:3 | self[return] |
|
||||
| test.swift:174:12:174:12 | self | test.swift:173:3:175:3 | self[return] |
|
||||
| test.swift:179:7:179:7 | WriteDef | test.swift:180:3:180:3 | a |
|
||||
| test.swift:179:11:179:13 | call to init() | test.swift:179:7:179:7 | WriteDef |
|
||||
| test.swift:179:7:179:7 | SSA def(a) | test.swift:180:3:180:3 | a |
|
||||
| test.swift:179:11:179:13 | call to init() | test.swift:179:7:179:7 | SSA def(a) |
|
||||
| test.swift:180:3:180:3 | [post] a | test.swift:181:13:181:13 | a |
|
||||
| test.swift:180:3:180:3 | a | test.swift:181:13:181:13 | a |
|
||||
| test.swift:184:7:184:7 | WriteDef | test.swift:184:7:184:7 | self[return] |
|
||||
| test.swift:184:7:184:7 | self | test.swift:184:7:184:7 | WriteDef |
|
||||
| test.swift:185:7:185:7 | self | test.swift:185:7:185:7 | WriteDef |
|
||||
| test.swift:185:7:185:7 | self | test.swift:185:7:185:7 | WriteDef |
|
||||
| test.swift:185:7:185:7 | self | test.swift:185:7:185:7 | WriteDef |
|
||||
| test.swift:185:7:185:7 | value | test.swift:185:7:185:7 | WriteDef |
|
||||
| test.swift:187:3:187:3 | WriteDef | test.swift:188:5:188:5 | self |
|
||||
| test.swift:187:3:187:3 | self | test.swift:187:3:187:3 | WriteDef |
|
||||
| test.swift:184:7:184:7 | SSA def(self) | test.swift:184:7:184:7 | self[return] |
|
||||
| test.swift:184:7:184:7 | self | test.swift:184:7:184:7 | SSA def(self) |
|
||||
| test.swift:185:7:185:7 | self | test.swift:185:7:185:7 | SSA def(self) |
|
||||
| test.swift:185:7:185:7 | self | test.swift:185:7:185:7 | SSA def(self) |
|
||||
| test.swift:185:7:185:7 | self | test.swift:185:7:185:7 | SSA def(self) |
|
||||
| test.swift:185:7:185:7 | value | test.swift:185:7:185:7 | SSA def(value) |
|
||||
| test.swift:187:3:187:3 | SSA def(self) | test.swift:188:5:188:5 | self |
|
||||
| test.swift:187:3:187:3 | self | test.swift:187:3:187:3 | SSA def(self) |
|
||||
| test.swift:188:5:188:5 | [post] self | test.swift:187:3:189:3 | self[return] |
|
||||
| test.swift:188:5:188:5 | self | test.swift:187:3:189:3 | self[return] |
|
||||
| test.swift:193:7:193:7 | WriteDef | test.swift:194:3:194:3 | b |
|
||||
| test.swift:193:11:193:13 | call to init() | test.swift:193:7:193:7 | WriteDef |
|
||||
| test.swift:193:7:193:7 | SSA def(b) | test.swift:194:3:194:3 | b |
|
||||
| test.swift:193:11:193:13 | call to init() | test.swift:193:7:193:7 | SSA def(b) |
|
||||
| test.swift:194:3:194:3 | [post] b | test.swift:195:13:195:13 | b |
|
||||
| test.swift:194:3:194:3 | b | test.swift:195:13:195:13 | b |
|
||||
| test.swift:199:7:199:7 | WriteDef | test.swift:200:3:200:3 | a |
|
||||
| test.swift:199:11:199:13 | call to init() | test.swift:199:7:199:7 | WriteDef |
|
||||
| test.swift:199:7:199:7 | SSA def(a) | test.swift:200:3:200:3 | a |
|
||||
| test.swift:199:11:199:13 | call to init() | test.swift:199:7:199:7 | SSA def(a) |
|
||||
| test.swift:200:3:200:3 | [post] a | test.swift:201:13:201:13 | a |
|
||||
| test.swift:200:3:200:3 | a | test.swift:201:13:201:13 | a |
|
||||
| test.swift:205:7:205:7 | WriteDef | test.swift:206:3:206:3 | a |
|
||||
| test.swift:205:11:205:13 | call to init() | test.swift:205:7:205:7 | WriteDef |
|
||||
| test.swift:205:7:205:7 | SSA def(a) | test.swift:206:3:206:3 | a |
|
||||
| test.swift:205:11:205:13 | call to init() | test.swift:205:7:205:7 | SSA def(a) |
|
||||
| test.swift:206:3:206:3 | [post] a | test.swift:207:13:207:13 | a |
|
||||
| test.swift:206:3:206:3 | a | test.swift:207:13:207:13 | a |
|
||||
| test.swift:211:7:211:7 | WriteDef | test.swift:212:3:212:3 | a |
|
||||
| test.swift:211:11:211:13 | call to init() | test.swift:211:7:211:7 | WriteDef |
|
||||
| test.swift:211:7:211:7 | SSA def(a) | test.swift:212:3:212:3 | a |
|
||||
| test.swift:211:11:211:13 | call to init() | test.swift:211:7:211:7 | SSA def(a) |
|
||||
| test.swift:212:3:212:3 | [post] a | test.swift:213:13:213:13 | a |
|
||||
| test.swift:212:3:212:3 | a | test.swift:213:13:213:13 | a |
|
||||
| test.swift:217:7:217:7 | WriteDef | test.swift:218:3:218:3 | b |
|
||||
| test.swift:217:11:217:13 | call to init() | test.swift:217:7:217:7 | WriteDef |
|
||||
| test.swift:217:7:217:7 | SSA def(b) | test.swift:218:3:218:3 | b |
|
||||
| test.swift:217:11:217:13 | call to init() | test.swift:217:7:217:7 | SSA def(b) |
|
||||
| test.swift:218:3:218:3 | [post] b | test.swift:219:13:219:13 | b |
|
||||
| test.swift:218:3:218:3 | b | test.swift:219:13:219:13 | b |
|
||||
| test.swift:222:7:222:7 | WriteDef | test.swift:222:7:222:7 | self[return] |
|
||||
| test.swift:222:7:222:7 | WriteDef | test.swift:222:7:222:7 | self[return] |
|
||||
| test.swift:222:7:222:7 | self | test.swift:222:7:222:7 | WriteDef |
|
||||
| test.swift:222:7:222:7 | self | test.swift:222:7:222:7 | WriteDef |
|
||||
| test.swift:223:7:223:7 | self | test.swift:223:7:223:7 | WriteDef |
|
||||
| test.swift:224:5:224:5 | WriteDef | test.swift:224:5:226:5 | self[return] |
|
||||
| test.swift:224:5:224:5 | self | test.swift:224:5:224:5 | WriteDef |
|
||||
| test.swift:227:5:227:5 | WriteDef | test.swift:227:5:229:5 | self[return] |
|
||||
| test.swift:227:5:227:5 | self | test.swift:227:5:227:5 | WriteDef |
|
||||
| test.swift:234:7:234:7 | WriteDef | test.swift:235:13:235:13 | a |
|
||||
| test.swift:234:11:234:31 | call to init() | test.swift:234:7:234:7 | WriteDef |
|
||||
| test.swift:222:7:222:7 | SSA def(self) | test.swift:222:7:222:7 | self[return] |
|
||||
| test.swift:222:7:222:7 | SSA def(self) | test.swift:222:7:222:7 | self[return] |
|
||||
| test.swift:222:7:222:7 | self | test.swift:222:7:222:7 | SSA def(self) |
|
||||
| test.swift:222:7:222:7 | self | test.swift:222:7:222:7 | SSA def(self) |
|
||||
| test.swift:223:7:223:7 | self | test.swift:223:7:223:7 | SSA def(self) |
|
||||
| test.swift:224:5:224:5 | SSA def(self) | test.swift:224:5:226:5 | self[return] |
|
||||
| test.swift:224:5:224:5 | self | test.swift:224:5:224:5 | SSA def(self) |
|
||||
| test.swift:227:5:227:5 | SSA def(self) | test.swift:227:5:229:5 | self[return] |
|
||||
| test.swift:227:5:227:5 | self | test.swift:227:5:227:5 | SSA def(self) |
|
||||
| test.swift:234:7:234:7 | SSA def(a) | test.swift:235:13:235:13 | a |
|
||||
| test.swift:234:11:234:31 | call to init() | test.swift:234:7:234:7 | SSA def(a) |
|
||||
| test.swift:235:13:235:13 | [post] a | test.swift:237:3:237:3 | a |
|
||||
| test.swift:235:13:235:13 | a | test.swift:237:3:237:3 | a |
|
||||
| test.swift:237:3:237:3 | [post] a | test.swift:238:13:238:13 | a |
|
||||
| test.swift:237:3:237:3 | a | test.swift:238:13:238:13 | a |
|
||||
| test.swift:242:9:242:9 | self | test.swift:242:9:242:9 | WriteDef |
|
||||
| test.swift:242:9:242:9 | self | test.swift:242:9:242:9 | WriteDef |
|
||||
| test.swift:242:9:242:9 | self | test.swift:242:9:242:9 | WriteDef |
|
||||
| test.swift:242:9:242:9 | value | test.swift:242:9:242:9 | WriteDef |
|
||||
| test.swift:243:9:243:9 | WriteDef | test.swift:243:18:243:18 | self |
|
||||
| test.swift:243:9:243:9 | self | test.swift:243:9:243:9 | WriteDef |
|
||||
| test.swift:242:9:242:9 | self | test.swift:242:9:242:9 | SSA def(self) |
|
||||
| test.swift:242:9:242:9 | self | test.swift:242:9:242:9 | SSA def(self) |
|
||||
| test.swift:242:9:242:9 | self | test.swift:242:9:242:9 | SSA def(self) |
|
||||
| test.swift:242:9:242:9 | value | test.swift:242:9:242:9 | SSA def(value) |
|
||||
| test.swift:243:9:243:9 | SSA def(self) | test.swift:243:18:243:18 | self |
|
||||
| test.swift:243:9:243:9 | self | test.swift:243:9:243:9 | SSA def(self) |
|
||||
| test.swift:243:18:243:18 | [post] self | test.swift:243:9:243:42 | self[return] |
|
||||
| test.swift:243:18:243:18 | self | test.swift:243:9:243:42 | self[return] |
|
||||
| test.swift:246:5:246:5 | WriteDef | test.swift:247:9:247:9 | self |
|
||||
| test.swift:246:5:246:5 | self | test.swift:246:5:246:5 | WriteDef |
|
||||
| test.swift:246:5:246:5 | SSA def(self) | test.swift:247:9:247:9 | self |
|
||||
| test.swift:246:5:246:5 | self | test.swift:246:5:246:5 | SSA def(self) |
|
||||
| test.swift:247:9:247:9 | [post] self | test.swift:246:5:248:5 | self[return] |
|
||||
| test.swift:247:9:247:9 | self | test.swift:246:5:248:5 | self[return] |
|
||||
| test.swift:252:23:252:23 | value | test.swift:252:23:252:23 | WriteDef |
|
||||
| test.swift:263:9:263:9 | WriteDef | test.swift:264:15:264:15 | x |
|
||||
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:263:9:263:9 | WriteDef |
|
||||
| test.swift:252:23:252:23 | value | test.swift:252:23:252:23 | SSA def(value) |
|
||||
| test.swift:263:9:263:9 | SSA def(x) | test.swift:264:15:264:15 | x |
|
||||
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:263:9:263:9 | SSA def(x) |
|
||||
| test.swift:264:15:264:15 | x | test.swift:264:15:264:16 | ...! |
|
||||
| test.swift:264:15:264:15 | x | test.swift:266:15:266:15 | x |
|
||||
| test.swift:266:15:266:15 | x | test.swift:266:15:266:16 | ...? |
|
||||
| test.swift:266:15:266:15 | x | test.swift:267:15:267:15 | x |
|
||||
| test.swift:266:15:266:25 | call to signum() | test.swift:266:15:266:25 | OptionalEvaluationExpr |
|
||||
| test.swift:267:15:267:15 | x | test.swift:268:16:268:16 | x |
|
||||
| test.swift:277:9:277:9 | WriteDef | test.swift:279:15:279:15 | t1 |
|
||||
| test.swift:277:14:277:26 | (...) | test.swift:277:9:277:9 | WriteDef |
|
||||
| test.swift:277:9:277:9 | SSA def(t1) | test.swift:279:15:279:15 | t1 |
|
||||
| test.swift:277:14:277:26 | (...) | test.swift:277:9:277:9 | SSA def(t1) |
|
||||
| test.swift:279:15:279:15 | t1 | test.swift:280:15:280:15 | t1 |
|
||||
| test.swift:280:15:280:15 | [post] t1 | test.swift:281:15:281:15 | t1 |
|
||||
| test.swift:280:15:280:15 | t1 | test.swift:281:15:281:15 | t1 |
|
||||
@@ -211,17 +211,17 @@
|
||||
| test.swift:291:15:291:15 | t1 | test.swift:292:15:292:15 | t1 |
|
||||
| test.swift:292:15:292:15 | [post] t1 | test.swift:293:15:293:15 | t1 |
|
||||
| test.swift:292:15:292:15 | t1 | test.swift:293:15:293:15 | t1 |
|
||||
| test.swift:297:9:297:9 | WriteDef | test.swift:298:14:298:14 | t1 |
|
||||
| test.swift:297:14:297:45 | (...) | test.swift:297:9:297:9 | WriteDef |
|
||||
| test.swift:298:9:298:9 | WriteDef | test.swift:305:15:305:15 | t2 |
|
||||
| test.swift:298:14:298:14 | t1 | test.swift:298:9:298:9 | WriteDef |
|
||||
| test.swift:297:9:297:9 | SSA def(t1) | test.swift:298:14:298:14 | t1 |
|
||||
| test.swift:297:14:297:45 | (...) | test.swift:297:9:297:9 | SSA def(t1) |
|
||||
| test.swift:298:9:298:9 | SSA def(t2) | test.swift:305:15:305:15 | t2 |
|
||||
| test.swift:298:14:298:14 | t1 | test.swift:298:9:298:9 | SSA def(t2) |
|
||||
| test.swift:298:14:298:14 | t1 | test.swift:299:21:299:21 | t1 |
|
||||
| test.swift:299:9:299:17 | WriteDef | test.swift:309:15:309:15 | a |
|
||||
| test.swift:299:9:299:17 | WriteDef | test.swift:310:15:310:15 | b |
|
||||
| test.swift:299:9:299:17 | WriteDef | test.swift:311:15:311:15 | c |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:299:9:299:17 | WriteDef |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:299:9:299:17 | WriteDef |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:299:9:299:17 | WriteDef |
|
||||
| test.swift:299:9:299:17 | SSA def(a) | test.swift:309:15:309:15 | a |
|
||||
| test.swift:299:9:299:17 | SSA def(b) | test.swift:310:15:310:15 | b |
|
||||
| test.swift:299:9:299:17 | SSA def(c) | test.swift:311:15:311:15 | c |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:299:9:299:17 | SSA def(a) |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:299:9:299:17 | SSA def(b) |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:299:9:299:17 | SSA def(c) |
|
||||
| test.swift:299:21:299:21 | t1 | test.swift:301:15:301:15 | t1 |
|
||||
| test.swift:301:15:301:15 | t1 | test.swift:302:15:302:15 | t1 |
|
||||
| test.swift:302:15:302:15 | [post] t1 | test.swift:303:15:303:15 | t1 |
|
||||
|
||||
Reference in New Issue
Block a user