[FIR] Rename edge kinds of control flow graph
This commit is contained in:
@@ -29,17 +29,17 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addJustKindEdge(from: CFGNode<*>, to: CFGNode<*>, kind: EdgeKind, propagateDeadness: Boolean, edgeExists: Boolean) {
|
private fun addJustKindEdge(from: CFGNode<*>, to: CFGNode<*>, kind: EdgeKind, propagateDeadness: Boolean, edgeExists: Boolean) {
|
||||||
if (kind != EdgeKind.Simple) {
|
if (kind != EdgeKind.Forward) {
|
||||||
val fromToKind = from._outgoingEdges[to] ?: runIf(edgeExists) { EdgeKind.Simple }
|
val fromToKind = from._outgoingEdges[to] ?: runIf(edgeExists) { EdgeKind.Forward }
|
||||||
merge(kind, fromToKind)?.let {
|
merge(kind, fromToKind)?.let {
|
||||||
from._outgoingEdges[to] = it
|
from._outgoingEdges[to] = it
|
||||||
} ?: from._outgoingEdges.remove(to)
|
} ?: from._outgoingEdges.remove(to)
|
||||||
val toFromKind = to._incomingEdges[from] ?: runIf(edgeExists) { EdgeKind.Simple }
|
val toFromKind = to._incomingEdges[from] ?: runIf(edgeExists) { EdgeKind.Forward }
|
||||||
merge(kind, toFromKind)?.let {
|
merge(kind, toFromKind)?.let {
|
||||||
to._incomingEdges[from] = it
|
to._incomingEdges[from] = it
|
||||||
} ?: to._incomingEdges.remove(from)
|
} ?: to._incomingEdges.remove(from)
|
||||||
}
|
}
|
||||||
if (propagateDeadness && kind == EdgeKind.Dead) {
|
if (propagateDeadness && kind == EdgeKind.DeadForward) {
|
||||||
to.isDead = true
|
to.isDead = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,9 +48,9 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
|
|||||||
return when {
|
return when {
|
||||||
second == null -> first
|
second == null -> first
|
||||||
first == second -> first
|
first == second -> first
|
||||||
first == EdgeKind.Dead || second == EdgeKind.Dead -> EdgeKind.Dead
|
first == EdgeKind.DeadForward || second == EdgeKind.DeadForward -> EdgeKind.DeadForward
|
||||||
first == EdgeKind.DeadBack || second == EdgeKind.DeadBack -> EdgeKind.DeadBack
|
first == EdgeKind.DeadBackward || second == EdgeKind.DeadBackward -> EdgeKind.DeadBackward
|
||||||
first == EdgeKind.Simple || second == EdgeKind.Simple -> null
|
first == EdgeKind.Forward || second == EdgeKind.Forward -> null
|
||||||
first.usedInDfa xor second.usedInDfa -> null
|
first.usedInDfa xor second.usedInDfa -> null
|
||||||
else -> throw IllegalStateException()
|
else -> throw IllegalStateException()
|
||||||
}
|
}
|
||||||
@@ -86,8 +86,8 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
|
|||||||
val previousNodes: List<CFGNode<*>> get() = _previousNodes
|
val previousNodes: List<CFGNode<*>> get() = _previousNodes
|
||||||
val followingNodes: List<CFGNode<*>> get() = _followingNodes
|
val followingNodes: List<CFGNode<*>> get() = _followingNodes
|
||||||
|
|
||||||
private val _incomingEdges = mutableMapOf<CFGNode<*>, EdgeKind>().withDefault { EdgeKind.Simple }
|
private val _incomingEdges = mutableMapOf<CFGNode<*>, EdgeKind>().withDefault { EdgeKind.Forward }
|
||||||
private val _outgoingEdges = mutableMapOf<CFGNode<*>, EdgeKind>().withDefault { EdgeKind.Simple }
|
private val _outgoingEdges = mutableMapOf<CFGNode<*>, EdgeKind>().withDefault { EdgeKind.Forward }
|
||||||
|
|
||||||
val incomingEdges: Map<CFGNode<*>, EdgeKind> get() = _incomingEdges
|
val incomingEdges: Map<CFGNode<*>, EdgeKind> get() = _incomingEdges
|
||||||
val outgoingEdges: Map<CFGNode<*>, EdgeKind> get() = _outgoingEdges
|
val outgoingEdges: Map<CFGNode<*>, EdgeKind> get() = _outgoingEdges
|
||||||
@@ -97,7 +97,7 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
|
|||||||
protected set
|
protected set
|
||||||
|
|
||||||
internal fun updateDeadStatus() {
|
internal fun updateDeadStatus() {
|
||||||
isDead = incomingEdges.size == previousNodes.size && incomingEdges.values.all { it == EdgeKind.Dead }
|
isDead = incomingEdges.size == previousNodes.size && incomingEdges.values.all { it == EdgeKind.DeadForward }
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R
|
abstract fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R
|
||||||
|
|||||||
+6
-6
@@ -91,12 +91,12 @@ enum class EdgeKind(
|
|||||||
val isBack: Boolean,
|
val isBack: Boolean,
|
||||||
val isDead: Boolean
|
val isDead: Boolean
|
||||||
) {
|
) {
|
||||||
Simple(usedInDfa = true, usedInCfa = true, isBack = false, isDead = false),
|
Forward(usedInDfa = true, usedInCfa = true, isBack = false, isDead = false),
|
||||||
Dead(usedInDfa = false, usedInCfa = true, isBack = false, isDead = true),
|
DeadForward(usedInDfa = false, usedInCfa = true, isBack = false, isDead = true),
|
||||||
Cfg(usedInDfa = false, usedInCfa = true, isBack = false, isDead = false),
|
DfgForward(usedInDfa = true, usedInCfa = false, isBack = false, isDead = false),
|
||||||
Dfg(usedInDfa = true, usedInCfa = false, isBack = false, isDead = false),
|
CfgForward(usedInDfa = false, usedInCfa = true, isBack = false, isDead = false),
|
||||||
Back(usedInDfa = false, usedInCfa = true, isBack = true, isDead = false),
|
CfgBackward(usedInDfa = false, usedInCfa = true, isBack = true, isDead = false),
|
||||||
DeadBack(usedInDfa = false, usedInCfa = true, isBack = true, isDead = true)
|
DeadBackward(usedInDfa = false, usedInCfa = true, isBack = true, isDead = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
|||||||
+23
-23
@@ -166,7 +166,7 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (previousNode != null) {
|
if (previousNode != null) {
|
||||||
addEdge(previousNode, enterNode, preferredKind = EdgeKind.Dfg)
|
addEdge(previousNode, enterNode, preferredKind = EdgeKind.DfgForward)
|
||||||
}
|
}
|
||||||
|
|
||||||
createFunctionExitNode(function).also {
|
createFunctionExitNode(function).also {
|
||||||
@@ -200,8 +200,8 @@ class ControlFlowGraphBuilder {
|
|||||||
entersToPostponedAnonymousFunctions[symbol] = enterNode
|
entersToPostponedAnonymousFunctions[symbol] = enterNode
|
||||||
exitsFromPostponedAnonymousFunctions[symbol] = exitNode
|
exitsFromPostponedAnonymousFunctions[symbol] = exitNode
|
||||||
parentGraphForAnonymousFunctions[symbol] = currentGraph
|
parentGraphForAnonymousFunctions[symbol] = currentGraph
|
||||||
popAndAddEdge(enterNode, preferredKind = EdgeKind.Simple)
|
popAndAddEdge(enterNode, preferredKind = EdgeKind.Forward)
|
||||||
addEdge(enterNode, exitNode, preferredKind = EdgeKind.Dfg)
|
addEdge(enterNode, exitNode, preferredKind = EdgeKind.DfgForward)
|
||||||
lastNodes.push(exitNode)
|
lastNodes.push(exitNode)
|
||||||
return enterNode to exitNode
|
return enterNode to exitNode
|
||||||
}
|
}
|
||||||
@@ -295,9 +295,9 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
val invocationKind = anonymousFunction.invocationKind
|
val invocationKind = anonymousFunction.invocationKind
|
||||||
if (invocationKind != null) {
|
if (invocationKind != null) {
|
||||||
addEdge(exitNode, postponedExitNode, preferredKind = EdgeKind.Cfg)
|
addEdge(exitNode, postponedExitNode, preferredKind = EdgeKind.CfgForward)
|
||||||
} else {
|
} else {
|
||||||
val kind = if (postponedExitNode.isDead) EdgeKind.Dead else EdgeKind.Cfg
|
val kind = if (postponedExitNode.isDead) EdgeKind.DeadForward else EdgeKind.CfgForward
|
||||||
CFGNode.addJustKindEdge(postponedEnterNode, postponedExitNode, kind, propagateDeadness = true)
|
CFGNode.addJustKindEdge(postponedEnterNode, postponedExitNode, kind, propagateDeadness = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,11 +345,11 @@ class ControlFlowGraphBuilder {
|
|||||||
is FirAnonymousInitializer -> declaration.controlFlowGraphReference.controlFlowGraph
|
is FirAnonymousInitializer -> declaration.controlFlowGraphReference.controlFlowGraph
|
||||||
else -> null
|
else -> null
|
||||||
} ?: continue
|
} ?: continue
|
||||||
addEdge(node, graph.enterNode, preferredKind = EdgeKind.Cfg)
|
addEdge(node, graph.enterNode, preferredKind = EdgeKind.CfgForward)
|
||||||
node = graph.exitNode
|
node = graph.exitNode
|
||||||
classGraph.addSubGraph(graph)
|
classGraph.addSubGraph(graph)
|
||||||
}
|
}
|
||||||
addEdge(node, exitNode, preferredKind = EdgeKind.Cfg)
|
addEdge(node, exitNode, preferredKind = EdgeKind.CfgForward)
|
||||||
return popGraph()
|
return popGraph()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +442,7 @@ class ControlFlowGraphBuilder {
|
|||||||
exitTargetsForTry.push(exitNode)
|
exitTargetsForTry.push(exitNode)
|
||||||
|
|
||||||
enterToLocalClassesMembers[property.symbol]?.let {
|
enterToLocalClassesMembers[property.symbol]?.let {
|
||||||
addEdge(it, enterNode, preferredKind = EdgeKind.Dfg)
|
addEdge(it, enterNode, preferredKind = EdgeKind.DfgForward)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastNodes.push(enterNode)
|
lastNodes.push(enterNode)
|
||||||
@@ -873,10 +873,10 @@ class ControlFlowGraphBuilder {
|
|||||||
node: CFGNode<*>,
|
node: CFGNode<*>,
|
||||||
callCompleted: Boolean
|
callCompleted: Boolean
|
||||||
): Pair<EdgeKind, UnionFunctionCallArgumentsNode?> {
|
): Pair<EdgeKind, UnionFunctionCallArgumentsNode?> {
|
||||||
if (!shouldPassFlowFromInplaceLambda.top()) return EdgeKind.Simple to null
|
if (!shouldPassFlowFromInplaceLambda.top()) return EdgeKind.Forward to null
|
||||||
var kind = EdgeKind.Simple
|
var kind = EdgeKind.Forward
|
||||||
if (!callCompleted || exitsFromCompletedPostponedAnonymousFunctions.isEmpty()) {
|
if (!callCompleted || exitsFromCompletedPostponedAnonymousFunctions.isEmpty()) {
|
||||||
return EdgeKind.Simple to null
|
return EdgeKind.Forward to null
|
||||||
}
|
}
|
||||||
val unionNode by lazy { createUnionFunctionCallArgumentsNode(node.fir) }
|
val unionNode by lazy { createUnionFunctionCallArgumentsNode(node.fir) }
|
||||||
var hasDirectPreviousNode = false
|
var hasDirectPreviousNode = false
|
||||||
@@ -889,11 +889,11 @@ class ControlFlowGraphBuilder {
|
|||||||
if (node.level >= exitNode.level) continue
|
if (node.level >= exitNode.level) continue
|
||||||
hasPostponedLambdas = true
|
hasPostponedLambdas = true
|
||||||
if (exitNode == lastPostponedLambdaExitNode) {
|
if (exitNode == lastPostponedLambdaExitNode) {
|
||||||
popAndAddEdge(node, preferredKind = EdgeKind.Cfg)
|
popAndAddEdge(node, preferredKind = EdgeKind.CfgForward)
|
||||||
kind = EdgeKind.Dfg
|
kind = EdgeKind.DfgForward
|
||||||
hasDirectPreviousNode = true
|
hasDirectPreviousNode = true
|
||||||
}
|
}
|
||||||
addEdge(exitNode.lastPreviousNode, unionNode, preferredKind = EdgeKind.Dfg)
|
addEdge(exitNode.lastPreviousNode, unionNode, preferredKind = EdgeKind.DfgForward)
|
||||||
iterator.remove()
|
iterator.remove()
|
||||||
}
|
}
|
||||||
if (hasPostponedLambdas) {
|
if (hasPostponedLambdas) {
|
||||||
@@ -903,7 +903,7 @@ class ControlFlowGraphBuilder {
|
|||||||
addNewSimpleNode(unionNode)
|
addNewSimpleNode(unionNode)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return EdgeKind.Simple to null
|
return EdgeKind.Forward to null
|
||||||
}
|
}
|
||||||
return Pair(kind, unionNode)
|
return Pair(kind, unionNode)
|
||||||
}
|
}
|
||||||
@@ -937,7 +937,7 @@ class ControlFlowGraphBuilder {
|
|||||||
lastNodes.push(it)
|
lastNodes.push(it)
|
||||||
}
|
}
|
||||||
val lastNode = runIf(lastNode is InitBlockExitNode) { lastNodes.pop() } ?: enterToLocalClassesMembers[initBlock.symbol]
|
val lastNode = runIf(lastNode is InitBlockExitNode) { lastNodes.pop() } ?: enterToLocalClassesMembers[initBlock.symbol]
|
||||||
lastNode?.let { addEdge(it, enterNode, preferredKind = EdgeKind.Dfg) }
|
lastNode?.let { addEdge(it, enterNode, preferredKind = EdgeKind.DfgForward) }
|
||||||
|
|
||||||
createInitBlockExitNode(initBlock).also {
|
createInitBlockExitNode(initBlock).also {
|
||||||
initBlockExitNodes.push(it)
|
initBlockExitNodes.push(it)
|
||||||
@@ -1042,7 +1042,7 @@ class ControlFlowGraphBuilder {
|
|||||||
private fun addNewSimpleNode(
|
private fun addNewSimpleNode(
|
||||||
node: CFGNode<*>,
|
node: CFGNode<*>,
|
||||||
isDead: Boolean = false,
|
isDead: Boolean = false,
|
||||||
preferredKind: EdgeKind = EdgeKind.Simple
|
preferredKind: EdgeKind = EdgeKind.Forward
|
||||||
): CFGNode<*> {
|
): CFGNode<*> {
|
||||||
val lastNode = lastNodes.pop()
|
val lastNode = lastNodes.pop()
|
||||||
addEdge(lastNode, node, isDead = isDead, preferredKind = preferredKind)
|
addEdge(lastNode, node, isDead = isDead, preferredKind = preferredKind)
|
||||||
@@ -1050,7 +1050,7 @@ class ControlFlowGraphBuilder {
|
|||||||
return lastNode
|
return lastNode
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addNodeThatReturnsNothing(node: CFGNode<*>, preferredKind: EdgeKind = EdgeKind.Simple) {
|
private fun addNodeThatReturnsNothing(node: CFGNode<*>, preferredKind: EdgeKind = EdgeKind.Forward) {
|
||||||
val exitNode: CFGNode<*> = exitTargetsForTry.top()
|
val exitNode: CFGNode<*> = exitTargetsForTry.top()
|
||||||
addNodeWithJump(node, exitNode, preferredKind)
|
addNodeWithJump(node, exitNode, preferredKind)
|
||||||
}
|
}
|
||||||
@@ -1058,7 +1058,7 @@ class ControlFlowGraphBuilder {
|
|||||||
private fun addNodeWithJump(
|
private fun addNodeWithJump(
|
||||||
node: CFGNode<*>,
|
node: CFGNode<*>,
|
||||||
targetNode: CFGNode<*>?,
|
targetNode: CFGNode<*>?,
|
||||||
preferredKind: EdgeKind = EdgeKind.Simple,
|
preferredKind: EdgeKind = EdgeKind.Forward,
|
||||||
isBack: Boolean = false
|
isBack: Boolean = false
|
||||||
) {
|
) {
|
||||||
popAndAddEdge(node, preferredKind)
|
popAndAddEdge(node, preferredKind)
|
||||||
@@ -1074,7 +1074,7 @@ class ControlFlowGraphBuilder {
|
|||||||
lastNodes.push(stub)
|
lastNodes.push(stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun popAndAddEdge(to: CFGNode<*>, preferredKind: EdgeKind = EdgeKind.Simple) {
|
private fun popAndAddEdge(to: CFGNode<*>, preferredKind: EdgeKind = EdgeKind.Forward) {
|
||||||
addEdge(lastNodes.pop(), to, preferredKind = preferredKind)
|
addEdge(lastNodes.pop(), to, preferredKind = preferredKind)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,10 +1084,10 @@ class ControlFlowGraphBuilder {
|
|||||||
propagateDeadness: Boolean = true,
|
propagateDeadness: Boolean = true,
|
||||||
isDead: Boolean = false,
|
isDead: Boolean = false,
|
||||||
isBack: Boolean = false,
|
isBack: Boolean = false,
|
||||||
preferredKind: EdgeKind = EdgeKind.Simple
|
preferredKind: EdgeKind = EdgeKind.Forward
|
||||||
) {
|
) {
|
||||||
val kind = if (isDead || from.isDead || to.isDead) {
|
val kind = if (isDead || from.isDead || to.isDead) {
|
||||||
if (isBack) EdgeKind.DeadBack else EdgeKind.Dead
|
if (isBack) EdgeKind.DeadBackward else EdgeKind.DeadForward
|
||||||
} else preferredKind
|
} else preferredKind
|
||||||
CFGNode.addEdge(from, to, kind, propagateDeadness)
|
CFGNode.addEdge(from, to, kind, propagateDeadness)
|
||||||
}
|
}
|
||||||
@@ -1097,7 +1097,7 @@ class ControlFlowGraphBuilder {
|
|||||||
to: CFGNode<*>,
|
to: CFGNode<*>,
|
||||||
isDead: Boolean = false
|
isDead: Boolean = false
|
||||||
) {
|
) {
|
||||||
addEdge(from, to, propagateDeadness = false, isDead = isDead, isBack = true, preferredKind = EdgeKind.Back)
|
addEdge(from, to, propagateDeadness = false, isDead = isDead, isBack = true, preferredKind = EdgeKind.CfgBackward)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Utils -----------------------------------
|
// ----------------------------------- Utils -----------------------------------
|
||||||
|
|||||||
+6
-6
@@ -26,12 +26,12 @@ class FirControlFlowGraphRenderVisitor(
|
|||||||
|
|
||||||
private val EDGE_STYLE = EnumMap(
|
private val EDGE_STYLE = EnumMap(
|
||||||
mapOf(
|
mapOf(
|
||||||
EdgeKind.Simple to "",
|
EdgeKind.Forward to "",
|
||||||
EdgeKind.Dead to "[style=dotted]",
|
EdgeKind.DeadForward to "[style=dotted]",
|
||||||
EdgeKind.Cfg to "[color=green]",
|
EdgeKind.CfgForward to "[color=green]",
|
||||||
EdgeKind.Dfg to "[color=red]",
|
EdgeKind.DfgForward to "[color=red]",
|
||||||
EdgeKind.Back to "[color=green style=dashed]",
|
EdgeKind.CfgBackward to "[color=green style=dashed]",
|
||||||
EdgeKind.DeadBack to "[color=green style=dotted]"
|
EdgeKind.DeadBackward to "[color=green style=dotted]"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cfgKinds = listOf(EdgeKind.Dead, EdgeKind.Cfg, EdgeKind.DeadBack, EdgeKind.Back)
|
private val cfgKinds = listOf(EdgeKind.DeadForward, EdgeKind.CfgForward, EdgeKind.DeadBackward, EdgeKind.CfgBackward)
|
||||||
|
|
||||||
private fun checkEdge(from: CFGNode<*>, to: CFGNode<*>) {
|
private fun checkEdge(from: CFGNode<*>, to: CFGNode<*>) {
|
||||||
KtUsefulTestCase.assertContainsElements(from.followingNodes, to)
|
KtUsefulTestCase.assertContainsElements(from.followingNodes, to)
|
||||||
|
|||||||
Reference in New Issue
Block a user