FIR CFA: automatically compute node levels
This commit is contained in:
+21
-86
@@ -30,6 +30,11 @@ class ControlFlowGraphBuilder {
|
|||||||
val currentGraph: ControlFlowGraph
|
val currentGraph: ControlFlowGraph
|
||||||
get() = graphs.top()
|
get() = graphs.top()
|
||||||
|
|
||||||
|
val levelCounter: Int
|
||||||
|
// `try` expressions aren't subgraphs, but they increase the level in order to tell which nodes
|
||||||
|
// are inside the try and which aren't
|
||||||
|
get() = graphs.size + tryExitNodes.size - 1 /* top-level graph */
|
||||||
|
|
||||||
private val lastNodes: Stack<CFGNode<*>> = stackOf()
|
private val lastNodes: Stack<CFGNode<*>> = stackOf()
|
||||||
val lastNode: CFGNode<*>
|
val lastNode: CFGNode<*>
|
||||||
get() = lastNodes.top()
|
get() = lastNodes.top()
|
||||||
@@ -37,8 +42,6 @@ class ControlFlowGraphBuilder {
|
|||||||
val lastNodeOrNull: CFGNode<*>?
|
val lastNodeOrNull: CFGNode<*>?
|
||||||
get() = lastNodes.topOrNull()
|
get() = lastNodes.topOrNull()
|
||||||
|
|
||||||
var levelCounter: Int = 0
|
|
||||||
|
|
||||||
// ----------------------------------- Node caches -----------------------------------
|
// ----------------------------------- Node caches -----------------------------------
|
||||||
|
|
||||||
private val exitTargetsForReturn: SymbolBasedNodeStorage<FirFunction, FunctionExitNode> = SymbolBasedNodeStorage()
|
private val exitTargetsForReturn: SymbolBasedNodeStorage<FirFunction, FunctionExitNode> = SymbolBasedNodeStorage()
|
||||||
@@ -114,7 +117,6 @@ class ControlFlowGraphBuilder {
|
|||||||
nodes: (E) -> Pair<EnterNode, ExitNode>
|
nodes: (E) -> Pair<EnterNode, ExitNode>
|
||||||
): Pair<EnterNode, ExitNode> where EnterNode : CFGNode<T>, EnterNode : GraphEnterNodeMarker, ExitNode : CFGNode<T>, ExitNode : GraphExitNodeMarker {
|
): Pair<EnterNode, ExitNode> where EnterNode : CFGNode<T>, EnterNode : GraphEnterNodeMarker, ExitNode : CFGNode<T>, ExitNode : GraphExitNodeMarker {
|
||||||
graphs.push(ControlFlowGraph(fir as? FirDeclaration, name, kind))
|
graphs.push(ControlFlowGraph(fir as? FirDeclaration, name, kind))
|
||||||
levelCounter++
|
|
||||||
return nodes(fir).also { (enterNode, exitNode) ->
|
return nodes(fir).also { (enterNode, exitNode) ->
|
||||||
currentGraph.enterNode = enterNode
|
currentGraph.enterNode = enterNode
|
||||||
currentGraph.exitNode = exitNode
|
currentGraph.exitNode = exitNode
|
||||||
@@ -123,7 +125,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun popGraph(): ControlFlowGraph {
|
private fun popGraph(): ControlFlowGraph {
|
||||||
levelCounter--
|
|
||||||
return graphs.pop().also { it.complete() }
|
return graphs.pop().also { it.complete() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +386,6 @@ class ControlFlowGraphBuilder {
|
|||||||
fun enterClass(klass: FirClass, buildGraph: Boolean): Pair<CFGNode<*>?, ClassEnterNode>? {
|
fun enterClass(klass: FirClass, buildGraph: Boolean): Pair<CFGNode<*>?, ClassEnterNode>? {
|
||||||
if (!buildGraph || klass !is FirControlFlowGraphOwner) {
|
if (!buildGraph || klass !is FirControlFlowGraphOwner) {
|
||||||
graphs.push(ControlFlowGraph(null, "<discarded class graph>", ControlFlowGraph.Kind.ClassInitializer))
|
graphs.push(ControlFlowGraph(null, "<discarded class graph>", ControlFlowGraph.Kind.ClassInitializer))
|
||||||
levelCounter++
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,7 +432,6 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
fun exitClass(): Pair<ClassExitNode?, ControlFlowGraph>? {
|
fun exitClass(): Pair<ClassExitNode?, ControlFlowGraph>? {
|
||||||
if (currentGraph.declaration == null) {
|
if (currentGraph.declaration == null) {
|
||||||
levelCounter--
|
|
||||||
graphs.pop().also { assert(it.kind == ControlFlowGraph.Kind.ClassInitializer) }
|
graphs.pop().also { assert(it.kind == ControlFlowGraph.Kind.ClassInitializer) }
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -704,7 +703,6 @@ class ControlFlowGraphBuilder {
|
|||||||
addNewSimpleNode(node)
|
addNewSimpleNode(node)
|
||||||
whenExitNodes.push(createWhenExitNode(whenExpression))
|
whenExitNodes.push(createWhenExitNode(whenExpression))
|
||||||
notCompletedFunctionCalls.push(mutableListOf())
|
notCompletedFunctionCalls.push(mutableListOf())
|
||||||
levelCounter++
|
|
||||||
splitDataFlowForPostponedLambdas()
|
splitDataFlowForPostponedLambdas()
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@@ -714,28 +712,20 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun enterWhenBranchCondition(whenBranch: FirWhenBranch): WhenBranchConditionEnterNode {
|
fun enterWhenBranchCondition(whenBranch: FirWhenBranch): WhenBranchConditionEnterNode {
|
||||||
return createWhenBranchConditionEnterNode(whenBranch).also { addNewSimpleNode(it) }.also { levelCounter++ }
|
return createWhenBranchConditionEnterNode(whenBranch).also { addNewSimpleNode(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitWhenBranchCondition(whenBranch: FirWhenBranch): Pair<WhenBranchConditionExitNode, WhenBranchResultEnterNode> {
|
fun exitWhenBranchCondition(whenBranch: FirWhenBranch): Pair<WhenBranchConditionExitNode, WhenBranchResultEnterNode> {
|
||||||
levelCounter--
|
val conditionExitNode = createWhenBranchConditionExitNode(whenBranch).also { addNewSimpleNode(it) }
|
||||||
val conditionExitNode = createWhenBranchConditionExitNode(whenBranch).also {
|
lastNodes.push(conditionExitNode) // keep one for next condition entry
|
||||||
addNewSimpleNode(it)
|
val branchEnterNode = createWhenBranchResultEnterNode(whenBranch).also { addNewSimpleNode(it) }
|
||||||
}.also { levelCounter++ }
|
|
||||||
val branchEnterNode = createWhenBranchResultEnterNode(whenBranch).also {
|
|
||||||
lastNodes.push(it)
|
|
||||||
addEdge(conditionExitNode, it)
|
|
||||||
}
|
|
||||||
return conditionExitNode to branchEnterNode
|
return conditionExitNode to branchEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitWhenBranchResult(whenBranch: FirWhenBranch): WhenBranchResultExitNode {
|
fun exitWhenBranchResult(whenBranch: FirWhenBranch): WhenBranchResultExitNode {
|
||||||
levelCounter--
|
|
||||||
val node = createWhenBranchResultExitNode(whenBranch)
|
val node = createWhenBranchResultExitNode(whenBranch)
|
||||||
popAndAddEdge(node)
|
popAndAddEdge(node)
|
||||||
val whenExitNode = whenExitNodes.top()
|
addEdge(node, whenExitNodes.top(), propagateDeadness = false)
|
||||||
addEdge(node, whenExitNode, propagateDeadness = false)
|
|
||||||
levelCounter++
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,7 +733,6 @@ class ControlFlowGraphBuilder {
|
|||||||
whenExpression: FirWhenExpression,
|
whenExpression: FirWhenExpression,
|
||||||
callCompleted: Boolean
|
callCompleted: Boolean
|
||||||
): Pair<WhenExitNode, WhenSyntheticElseBranchNode?> {
|
): Pair<WhenExitNode, WhenSyntheticElseBranchNode?> {
|
||||||
levelCounter -= whenExpression.branches.size
|
|
||||||
val whenExitNode = whenExitNodes.pop()
|
val whenExitNode = whenExitNodes.pop()
|
||||||
// exit from last condition node still on stack
|
// exit from last condition node still on stack
|
||||||
// we should remove it
|
// we should remove it
|
||||||
@@ -758,40 +747,29 @@ class ControlFlowGraphBuilder {
|
|||||||
mergeDataFlowFromPostponedLambdas(whenExitNode, callCompleted)
|
mergeDataFlowFromPostponedLambdas(whenExitNode, callCompleted)
|
||||||
whenExitNode.updateDeadStatus()
|
whenExitNode.updateDeadStatus()
|
||||||
lastNodes.push(whenExitNode)
|
lastNodes.push(whenExitNode)
|
||||||
levelCounter--
|
|
||||||
return whenExitNode to syntheticElseBranchNode
|
return whenExitNode to syntheticElseBranchNode
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- While Loop -----------------------------------
|
// ----------------------------------- While Loop -----------------------------------
|
||||||
|
|
||||||
fun enterWhileLoop(loop: FirLoop): Pair<LoopEnterNode, LoopConditionEnterNode> {
|
fun enterWhileLoop(loop: FirLoop): Pair<LoopEnterNode, LoopConditionEnterNode> {
|
||||||
val loopEnterNode = createLoopEnterNode(loop).also {
|
val loopEnterNode = createLoopEnterNode(loop).also { addNewSimpleNode(it) }
|
||||||
addNewSimpleNode(it)
|
|
||||||
}
|
|
||||||
loopExitNodes.push(createLoopExitNode(loop))
|
loopExitNodes.push(createLoopExitNode(loop))
|
||||||
levelCounter++
|
val conditionEnterNode = createLoopConditionEnterNode(loop.condition, loop).also { addNewSimpleNode(it) }
|
||||||
val conditionEnterNode = createLoopConditionEnterNode(loop.condition, loop).also {
|
loopConditionEnterNodes.push(conditionEnterNode)
|
||||||
addNewSimpleNode(it)
|
|
||||||
loopConditionEnterNodes.push(it)
|
|
||||||
}
|
|
||||||
levelCounter++
|
|
||||||
return loopEnterNode to conditionEnterNode
|
return loopEnterNode to conditionEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitWhileLoopCondition(loop: FirLoop): Pair<LoopConditionExitNode, LoopBlockEnterNode> {
|
fun exitWhileLoopCondition(loop: FirLoop): Pair<LoopConditionExitNode, LoopBlockEnterNode> {
|
||||||
levelCounter--
|
val conditionExitNode = createLoopConditionExitNode(loop.condition).also { addNewSimpleNode(it) }
|
||||||
val conditionExitNode = createLoopConditionExitNode(loop.condition)
|
|
||||||
addNewSimpleNode(conditionExitNode)
|
|
||||||
val conditionConstBooleanValue = loop.condition.booleanConstValue
|
val conditionConstBooleanValue = loop.condition.booleanConstValue
|
||||||
addEdge(conditionExitNode, loopExitNodes.top(), propagateDeadness = false, isDead = conditionConstBooleanValue == true)
|
addEdge(conditionExitNode, loopExitNodes.top(), propagateDeadness = false, isDead = conditionConstBooleanValue == true)
|
||||||
val loopBlockEnterNode = createLoopBlockEnterNode(loop)
|
val loopBlockEnterNode = createLoopBlockEnterNode(loop)
|
||||||
addNewSimpleNode(loopBlockEnterNode, conditionConstBooleanValue == false)
|
addNewSimpleNode(loopBlockEnterNode, conditionConstBooleanValue == false)
|
||||||
levelCounter++
|
|
||||||
return conditionExitNode to loopBlockEnterNode
|
return conditionExitNode to loopBlockEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitWhileLoop(loop: FirLoop): Triple<LoopConditionEnterNode, LoopBlockExitNode, LoopExitNode> {
|
fun exitWhileLoop(loop: FirLoop): Triple<LoopConditionEnterNode, LoopBlockExitNode, LoopExitNode> {
|
||||||
levelCounter--
|
|
||||||
val loopBlockExitNode = createLoopBlockExitNode(loop)
|
val loopBlockExitNode = createLoopBlockExitNode(loop)
|
||||||
popAndAddEdge(loopBlockExitNode)
|
popAndAddEdge(loopBlockExitNode)
|
||||||
val conditionEnterNode = loopConditionEnterNodes.pop()
|
val conditionEnterNode = loopConditionEnterNodes.pop()
|
||||||
@@ -799,41 +777,32 @@ class ControlFlowGraphBuilder {
|
|||||||
val loopExitNode = loopExitNodes.pop()
|
val loopExitNode = loopExitNodes.pop()
|
||||||
loopExitNode.updateDeadStatus()
|
loopExitNode.updateDeadStatus()
|
||||||
lastNodes.push(loopExitNode)
|
lastNodes.push(loopExitNode)
|
||||||
levelCounter--
|
|
||||||
return Triple(conditionEnterNode, loopBlockExitNode, loopExitNode)
|
return Triple(conditionEnterNode, loopBlockExitNode, loopExitNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Do while Loop -----------------------------------
|
// ----------------------------------- Do while Loop -----------------------------------
|
||||||
|
|
||||||
fun enterDoWhileLoop(loop: FirLoop): Pair<LoopEnterNode, LoopBlockEnterNode> {
|
fun enterDoWhileLoop(loop: FirLoop): Pair<LoopEnterNode, LoopBlockEnterNode> {
|
||||||
val loopEnterNode = createLoopEnterNode(loop)
|
val loopEnterNode = createLoopEnterNode(loop).also { addNewSimpleNode(it) }
|
||||||
addNewSimpleNode(loopEnterNode)
|
|
||||||
loopExitNodes.push(createLoopExitNode(loop))
|
loopExitNodes.push(createLoopExitNode(loop))
|
||||||
levelCounter++
|
val blockEnterNode = createLoopBlockEnterNode(loop).also { addNewSimpleNode(it) }
|
||||||
val blockEnterNode = createLoopBlockEnterNode(loop)
|
lastNodes.push(blockEnterNode) // to add back edge at the end
|
||||||
addNewSimpleNode(blockEnterNode)
|
|
||||||
// put block enter node twice so we can refer it after exit from loop condition
|
|
||||||
lastNodes.push(blockEnterNode)
|
|
||||||
loopConditionEnterNodes.push(createLoopConditionEnterNode(loop.condition, loop))
|
loopConditionEnterNodes.push(createLoopConditionEnterNode(loop.condition, loop))
|
||||||
levelCounter++
|
|
||||||
return loopEnterNode to blockEnterNode
|
return loopEnterNode to blockEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enterDoWhileLoopCondition(loop: FirLoop): Pair<LoopBlockExitNode, LoopConditionEnterNode> {
|
fun enterDoWhileLoopCondition(loop: FirLoop): Pair<LoopBlockExitNode, LoopConditionEnterNode> {
|
||||||
levelCounter--
|
|
||||||
val blockExitNode = createLoopBlockExitNode(loop).also { addNewSimpleNode(it) }
|
val blockExitNode = createLoopBlockExitNode(loop).also { addNewSimpleNode(it) }
|
||||||
// This may sound shocking, but `do...while` conditions can `continue` to themselves,
|
// This may sound shocking, but `do...while` conditions can `continue` to themselves,
|
||||||
// so we can't pop the node off the stack here.
|
// so we can't pop the node off the stack here.
|
||||||
val conditionEnterNode = loopConditionEnterNodes.top().also { addNewSimpleNode(it) }
|
val conditionEnterNode = loopConditionEnterNodes.top().also { addNewSimpleNode(it) }
|
||||||
// Might have had live `continue`s with an unreachable block exit, so recompute deadness.
|
// Might have had live `continue`s with an unreachable block exit, so recompute deadness.
|
||||||
conditionEnterNode.updateDeadStatus()
|
conditionEnterNode.updateDeadStatus()
|
||||||
levelCounter++
|
|
||||||
return blockExitNode to conditionEnterNode
|
return blockExitNode to conditionEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitDoWhileLoop(loop: FirLoop): Pair<LoopConditionExitNode, LoopExitNode> {
|
fun exitDoWhileLoop(loop: FirLoop): Pair<LoopConditionExitNode, LoopExitNode> {
|
||||||
loopConditionEnterNodes.pop()
|
loopConditionEnterNodes.pop()
|
||||||
levelCounter--
|
|
||||||
val conditionExitNode = createLoopConditionExitNode(loop.condition)
|
val conditionExitNode = createLoopConditionExitNode(loop.condition)
|
||||||
val conditionBooleanValue = loop.condition.booleanConstValue
|
val conditionBooleanValue = loop.condition.booleanConstValue
|
||||||
popAndAddEdge(conditionExitNode)
|
popAndAddEdge(conditionExitNode)
|
||||||
@@ -844,7 +813,6 @@ class ControlFlowGraphBuilder {
|
|||||||
addEdge(conditionExitNode, loopExit, propagateDeadness = false, isDead = conditionBooleanValue == true)
|
addEdge(conditionExitNode, loopExit, propagateDeadness = false, isDead = conditionBooleanValue == true)
|
||||||
loopExit.updateDeadStatus()
|
loopExit.updateDeadStatus()
|
||||||
lastNodes.push(loopExit)
|
lastNodes.push(loopExit)
|
||||||
levelCounter--
|
|
||||||
return conditionExitNode to loopExit
|
return conditionExitNode to loopExit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,14 +825,12 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
addNewSimpleNode(enterNode)
|
addNewSimpleNode(enterNode)
|
||||||
binaryLogicExpressionExitNodes.push(exitNode)
|
binaryLogicExpressionExitNodes.push(exitNode)
|
||||||
levelCounter++
|
|
||||||
return enterNode
|
return enterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitLeftBinaryLogicExpressionArgument(
|
fun exitLeftBinaryLogicExpressionArgument(
|
||||||
binaryLogicExpression: FirBinaryLogicExpression
|
binaryLogicExpression: FirBinaryLogicExpression
|
||||||
): Pair<CFGNode<FirBinaryLogicExpression>, CFGNode<FirBinaryLogicExpression>> {
|
): Pair<CFGNode<FirBinaryLogicExpression>, CFGNode<FirBinaryLogicExpression>> {
|
||||||
levelCounter--
|
|
||||||
val leftBooleanConstValue = binaryLogicExpression.leftOperand.booleanConstValue
|
val leftBooleanConstValue = binaryLogicExpression.leftOperand.booleanConstValue
|
||||||
val (leftExitNode, rightEnterNode) = when (binaryLogicExpression.kind) {
|
val (leftExitNode, rightEnterNode) = when (binaryLogicExpression.kind) {
|
||||||
LogicOperationKind.AND ->
|
LogicOperationKind.AND ->
|
||||||
@@ -878,12 +844,10 @@ class ControlFlowGraphBuilder {
|
|||||||
addEdge(leftExitNode, binaryLogicExpressionExitNodes.top(), propagateDeadness = false, isDead = leftBooleanConstValue == isAnd)
|
addEdge(leftExitNode, binaryLogicExpressionExitNodes.top(), propagateDeadness = false, isDead = leftBooleanConstValue == isAnd)
|
||||||
addEdge(leftExitNode, rightEnterNode, isDead = leftBooleanConstValue == !isAnd)
|
addEdge(leftExitNode, rightEnterNode, isDead = leftBooleanConstValue == !isAnd)
|
||||||
lastNodes.push(rightEnterNode)
|
lastNodes.push(rightEnterNode)
|
||||||
levelCounter++
|
|
||||||
return leftExitNode to rightEnterNode
|
return leftExitNode to rightEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitBinaryLogicExpression(): AbstractBinaryExitNode<FirBinaryLogicExpression> {
|
fun exitBinaryLogicExpression(): AbstractBinaryExitNode<FirBinaryLogicExpression> {
|
||||||
levelCounter--
|
|
||||||
val exitNode = binaryLogicExpressionExitNodes.pop()
|
val exitNode = binaryLogicExpressionExitNodes.pop()
|
||||||
val rightNode = lastNodes.pop()
|
val rightNode = lastNodes.pop()
|
||||||
addEdge(rightNode, exitNode, propagateDeadness = false)
|
addEdge(rightNode, exitNode, propagateDeadness = false)
|
||||||
@@ -897,14 +861,10 @@ class ControlFlowGraphBuilder {
|
|||||||
// ----------------------------------- Try-catch-finally -----------------------------------
|
// ----------------------------------- Try-catch-finally -----------------------------------
|
||||||
|
|
||||||
fun enterTryExpression(tryExpression: FirTryExpression): Pair<TryExpressionEnterNode, TryMainBlockEnterNode> {
|
fun enterTryExpression(tryExpression: FirTryExpression): Pair<TryExpressionEnterNode, TryMainBlockEnterNode> {
|
||||||
val enterTryExpressionNode = createTryExpressionEnterNode(tryExpression)
|
val enterTryExpressionNode = createTryExpressionEnterNode(tryExpression).also { addNewSimpleNode(it) }
|
||||||
val exitTryExpressionNode = createTryExpressionExitNode(tryExpression)
|
tryExitNodes.push(createTryExpressionExitNode(tryExpression))
|
||||||
addNewSimpleNode(enterTryExpressionNode)
|
|
||||||
tryExitNodes.push(exitTryExpressionNode)
|
|
||||||
levelCounter++
|
|
||||||
|
|
||||||
val enterTryMainBlockNode = createTryMainBlockEnterNode(tryExpression)
|
val enterTryMainBlockNode = createTryMainBlockEnterNode(tryExpression).also { addNewSimpleNode(it) }
|
||||||
addNewSimpleNode(enterTryMainBlockNode)
|
|
||||||
|
|
||||||
catchNodes.push(tryExpression.catches.map { createCatchClauseEnterNode(it) })
|
catchNodes.push(tryExpression.catches.map { createCatchClauseEnterNode(it) })
|
||||||
if (tryExpression.finallyBlock != null) {
|
if (tryExpression.finallyBlock != null) {
|
||||||
@@ -923,12 +883,10 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
notCompletedFunctionCalls.push(mutableListOf())
|
notCompletedFunctionCalls.push(mutableListOf())
|
||||||
splitDataFlowForPostponedLambdas()
|
splitDataFlowForPostponedLambdas()
|
||||||
levelCounter++
|
|
||||||
return enterTryExpressionNode to enterTryMainBlockNode
|
return enterTryExpressionNode to enterTryMainBlockNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitTryMainBlock(): TryMainBlockExitNode {
|
fun exitTryMainBlock(): TryMainBlockExitNode {
|
||||||
levelCounter--
|
|
||||||
val exitTryExpressionNode = tryExitNodes.top()
|
val exitTryExpressionNode = tryExitNodes.top()
|
||||||
val node = createTryMainBlockExitNode(exitTryExpressionNode.fir)
|
val node = createTryMainBlockExitNode(exitTryExpressionNode.fir)
|
||||||
popAndAddEdge(node)
|
popAndAddEdge(node)
|
||||||
@@ -956,12 +914,10 @@ class ControlFlowGraphBuilder {
|
|||||||
addEdge(catchEnterNode, finallyEnterNodes.top(), propagateDeadness = false, label = UncaughtExceptionPath)
|
addEdge(catchEnterNode, finallyEnterNodes.top(), propagateDeadness = false, label = UncaughtExceptionPath)
|
||||||
}
|
}
|
||||||
lastNodes.push(catchEnterNode)
|
lastNodes.push(catchEnterNode)
|
||||||
levelCounter++
|
|
||||||
return catchEnterNode
|
return catchEnterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitCatchClause(catch: FirCatch): CatchClauseExitNode {
|
fun exitCatchClause(catch: FirCatch): CatchClauseExitNode {
|
||||||
levelCounter--
|
|
||||||
val exitTryExpressionNode = tryExitNodes.top()
|
val exitTryExpressionNode = tryExitNodes.top()
|
||||||
val catchExitNode = createCatchClauseExitNode(catch)
|
val catchExitNode = createCatchClauseExitNode(catch)
|
||||||
popAndAddEdge(catchExitNode)
|
popAndAddEdge(catchExitNode)
|
||||||
@@ -1030,7 +986,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitTryExpression(callCompleted: Boolean): TryExpressionExitNode {
|
fun exitTryExpression(callCompleted: Boolean): TryExpressionExitNode {
|
||||||
levelCounter--
|
|
||||||
notCompletedFunctionCalls.pop().forEach(::completeFunctionCall)
|
notCompletedFunctionCalls.pop().forEach(::completeFunctionCall)
|
||||||
val node = tryExitNodes.pop()
|
val node = tryExitNodes.pop()
|
||||||
mergeDataFlowFromPostponedLambdas(node, callCompleted)
|
mergeDataFlowFromPostponedLambdas(node, callCompleted)
|
||||||
@@ -1070,7 +1025,7 @@ class ControlFlowGraphBuilder {
|
|||||||
// it would be much easier if we could build calls after full completion only, at least for Nothing calls
|
// it would be much easier if we could build calls after full completion only, at least for Nothing calls
|
||||||
private fun completeFunctionCall(node: FunctionCallNode) {
|
private fun completeFunctionCall(node: FunctionCallNode) {
|
||||||
if (!node.fir.resultType.isNothing) return
|
if (!node.fir.resultType.isNothing) return
|
||||||
val stub = withLevelOfNode(node) { createStubNode() }
|
val stub = StubNode(currentGraph, node.level, currentGraph.nodeCount++)
|
||||||
val edges = node.followingNodes.map { it to node.edgeTo(it) }
|
val edges = node.followingNodes.map { it to node.edgeTo(it) }
|
||||||
CFGNode.removeAllOutgoingEdges(node)
|
CFGNode.removeAllOutgoingEdges(node)
|
||||||
CFGNode.addEdge(node, stub, EdgeKind.DeadForward, propagateDeadness = false)
|
CFGNode.addEdge(node, stub, EdgeKind.DeadForward, propagateDeadness = false)
|
||||||
@@ -1111,7 +1066,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun enterCall() {
|
fun enterCall() {
|
||||||
levelCounter++
|
|
||||||
splitDataFlowForPostponedLambdas()
|
splitDataFlowForPostponedLambdas()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,7 +1084,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitFunctionCall(functionCall: FirFunctionCall, callCompleted: Boolean): FunctionCallNode {
|
fun exitFunctionCall(functionCall: FirFunctionCall, callCompleted: Boolean): FunctionCallNode {
|
||||||
levelCounter--
|
|
||||||
val returnsNothing = functionCall.resultType.isNothing
|
val returnsNothing = functionCall.resultType.isNothing
|
||||||
val node = createFunctionCallNode(functionCall)
|
val node = createFunctionCallNode(functionCall)
|
||||||
unifyDataFlowFromPostponedLambdas(node, callCompleted)
|
unifyDataFlowFromPostponedLambdas(node, callCompleted)
|
||||||
@@ -1146,7 +1099,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitDelegatedConstructorCall(call: FirDelegatedConstructorCall, callCompleted: Boolean): DelegatedConstructorCallNode {
|
fun exitDelegatedConstructorCall(call: FirDelegatedConstructorCall, callCompleted: Boolean): DelegatedConstructorCallNode {
|
||||||
levelCounter--
|
|
||||||
val node = createDelegatedConstructorCallNode(call)
|
val node = createDelegatedConstructorCallNode(call)
|
||||||
unifyDataFlowFromPostponedLambdas(node, callCompleted)
|
unifyDataFlowFromPostponedLambdas(node, callCompleted)
|
||||||
addNewSimpleNode(node)
|
addNewSimpleNode(node)
|
||||||
@@ -1154,7 +1106,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitStringConcatenationCall(call: FirStringConcatenationCall): StringConcatenationCallNode {
|
fun exitStringConcatenationCall(call: FirStringConcatenationCall): StringConcatenationCallNode {
|
||||||
levelCounter--
|
|
||||||
val node = createStringConcatenationCallNode(call)
|
val node = createStringConcatenationCallNode(call)
|
||||||
unifyDataFlowFromPostponedLambdas(node, callCompleted = true)
|
unifyDataFlowFromPostponedLambdas(node, callCompleted = true)
|
||||||
addNewSimpleNode(node)
|
addNewSimpleNode(node)
|
||||||
@@ -1178,7 +1129,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, callCompleted: Boolean): CheckNotNullCallNode {
|
fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, callCompleted: Boolean): CheckNotNullCallNode {
|
||||||
levelCounter--
|
|
||||||
val node = createCheckNotNullCallNode(checkNotNullCall)
|
val node = createCheckNotNullCallNode(checkNotNullCall)
|
||||||
unifyDataFlowFromPostponedLambdas(node, callCompleted)
|
unifyDataFlowFromPostponedLambdas(node, callCompleted)
|
||||||
if (checkNotNullCall.resultType.isNothing) {
|
if (checkNotNullCall.resultType.isNothing) {
|
||||||
@@ -1196,7 +1146,6 @@ class ControlFlowGraphBuilder {
|
|||||||
// and are never evaluated. We'll push all nodes created in the process into a stub graph, then throw it away.
|
// and are never evaluated. We'll push all nodes created in the process into a stub graph, then throw it away.
|
||||||
// TODO: don't waste time creating the nodes in the first place
|
// TODO: don't waste time creating the nodes in the first place
|
||||||
graphs.push(ControlFlowGraph(null, "<compile-time expression graph>", ControlFlowGraph.Kind.FakeCall))
|
graphs.push(ControlFlowGraph(null, "<compile-time expression graph>", ControlFlowGraph.Kind.FakeCall))
|
||||||
levelCounter++
|
|
||||||
return createFakeExpressionEnterNode().also {
|
return createFakeExpressionEnterNode().also {
|
||||||
lastNodes.push(it)
|
lastNodes.push(it)
|
||||||
exitTargetsForTry.push(it) // technically might create CFG loops, but the graph will never be visited anyway...
|
exitTargetsForTry.push(it) // technically might create CFG loops, but the graph will never be visited anyway...
|
||||||
@@ -1204,7 +1153,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitFakeExpression() {
|
fun exitFakeExpression() {
|
||||||
levelCounter--
|
|
||||||
lastNodes.pop()
|
lastNodes.pop()
|
||||||
exitTargetsForTry.pop()
|
exitTargetsForTry.pop()
|
||||||
graphs.pop().also { assert(it.kind == ControlFlowGraph.Kind.FakeCall) }
|
graphs.pop().also { assert(it.kind == ControlFlowGraph.Kind.FakeCall) }
|
||||||
@@ -1395,19 +1343,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Utils -----------------------------------
|
|
||||||
|
|
||||||
private fun <R> withLevelOfNode(node: CFGNode<*>, f: () -> R): R {
|
|
||||||
val last = levelCounter
|
|
||||||
levelCounter = node.level
|
|
||||||
try {
|
|
||||||
return f()
|
|
||||||
} finally {
|
|
||||||
levelCounter = last
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirDeclaration?.isLocalClassOrAnonymousObject() = ((this as? FirRegularClass)?.isLocal == true) || this is FirAnonymousObject
|
fun FirDeclaration?.isLocalClassOrAnonymousObject() = ((this as? FirRegularClass)?.isLocal == true) || this is FirAnonymousObject
|
||||||
|
|||||||
+98
-98
@@ -368,8 +368,8 @@ digraph kt44814_kt {
|
|||||||
subgraph cluster_41 {
|
subgraph cluster_41 {
|
||||||
color=blue
|
color=blue
|
||||||
112 [label="Enter function <init> [3]" style="filled" fillcolor=red];
|
112 [label="Enter function <init> [3]" style="filled" fillcolor=red];
|
||||||
113 [label="Access variable R|<local>/node| [4]"];
|
113 [label="Access variable R|<local>/node| [3]"];
|
||||||
114 [label="Access variable R|<local>/token| [4]"];
|
114 [label="Access variable R|<local>/token| [3]"];
|
||||||
115 [label="Delegated constructor call: super<R|FirModifier<LighterASTNode>|>(...) [3]" style="filled" fillcolor=yellow];
|
115 [label="Delegated constructor call: super<R|FirModifier<LighterASTNode>|>(...) [3]" style="filled" fillcolor=yellow];
|
||||||
116 [label="Exit function <init> [3]" style="filled" fillcolor=red];
|
116 [label="Exit function <init> [3]" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
@@ -387,8 +387,8 @@ digraph kt44814_kt {
|
|||||||
subgraph cluster_44 {
|
subgraph cluster_44 {
|
||||||
color=blue
|
color=blue
|
||||||
122 [label="Enter function <init> [3]" style="filled" fillcolor=red];
|
122 [label="Enter function <init> [3]" style="filled" fillcolor=red];
|
||||||
123 [label="Access variable R|<local>/node| [4]"];
|
123 [label="Access variable R|<local>/node| [3]"];
|
||||||
124 [label="Access variable R|<local>/token| [4]"];
|
124 [label="Access variable R|<local>/token| [3]"];
|
||||||
125 [label="Delegated constructor call: super<R|FirModifier<ASTNode>|>(...) [3]" style="filled" fillcolor=yellow];
|
125 [label="Delegated constructor call: super<R|FirModifier<ASTNode>|>(...) [3]" style="filled" fillcolor=yellow];
|
||||||
126 [label="Exit function <init> [3]" style="filled" fillcolor=red];
|
126 [label="Exit function <init> [3]" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
@@ -462,13 +462,13 @@ digraph kt44814_kt {
|
|||||||
subgraph cluster_51 {
|
subgraph cluster_51 {
|
||||||
color=blue
|
color=blue
|
||||||
142 [label="Enter block [3]"];
|
142 [label="Enter block [3]"];
|
||||||
143 [label="Function call: R|/LighterASTNode.LighterASTNode|() [6]" style="filled" fillcolor=yellow];
|
143 [label="Function call: R|/LighterASTNode.LighterASTNode|() [3]" style="filled" fillcolor=yellow];
|
||||||
144 [label="Function call: R|kotlin/collections/listOf|<R|LighterASTNode|>(...) [5]" style="filled" fillcolor=yellow];
|
144 [label="Function call: R|kotlin/collections/listOf|<R|LighterASTNode|>(...) [3]" style="filled" fillcolor=yellow];
|
||||||
145 [label="Function call: R|/LighterASTNode.LighterASTNode|(...) [4]" style="filled" fillcolor=yellow];
|
145 [label="Function call: R|/LighterASTNode.LighterASTNode|(...) [3]" style="filled" fillcolor=yellow];
|
||||||
146 [label="Function call: R|/FlyweightCapableTreeStructure.FlyweightCapableTreeStructure|() [4]" style="filled" fillcolor=yellow];
|
146 [label="Function call: R|/FlyweightCapableTreeStructure.FlyweightCapableTreeStructure|() [3]" style="filled" fillcolor=yellow];
|
||||||
147 [label="Function call: R|/FirLightSourceElement.FirLightSourceElement|(...) [3]" style="filled" fillcolor=yellow];
|
147 [label="Function call: R|/FirLightSourceElement.FirLightSourceElement|(...) [3]" style="filled" fillcolor=yellow];
|
||||||
148 [label="Variable declaration: lval sourceElement: R|FirSourceElement?| [3]"];
|
148 [label="Variable declaration: lval sourceElement: R|FirSourceElement?| [3]"];
|
||||||
149 [label="Access variable R|<local>/sourceElement| [4]"];
|
149 [label="Access variable R|<local>/sourceElement| [3]"];
|
||||||
150 [label="Function call: (this@R|/FirModifierList.Companion|, R|<local>/sourceElement|).R|/FirModifierList.Companion.getModifierList|() [3]" style="filled" fillcolor=yellow];
|
150 [label="Function call: (this@R|/FirModifierList.Companion|, R|<local>/sourceElement|).R|/FirModifierList.Companion.getModifierList|() [3]" style="filled" fillcolor=yellow];
|
||||||
151 [label="Variable declaration: lval result: R|FirModifierList?| [3]"];
|
151 [label="Variable declaration: lval result: R|FirModifierList?| [3]"];
|
||||||
subgraph cluster_52 {
|
subgraph cluster_52 {
|
||||||
@@ -476,32 +476,32 @@ digraph kt44814_kt {
|
|||||||
152 [label="Enter when [3]"];
|
152 [label="Enter when [3]"];
|
||||||
subgraph cluster_53 {
|
subgraph cluster_53 {
|
||||||
color=blue
|
color=blue
|
||||||
153 [label="Enter when branch condition [4]"];
|
153 [label="Enter when branch condition [3]"];
|
||||||
154 [label="Access variable R|<local>/result| [5]"];
|
154 [label="Access variable R|<local>/result| [3]"];
|
||||||
155 [label="Type operator: (R|<local>/result| is R|FirModifierList.FirLightModifierList|) [5]"];
|
155 [label="Type operator: (R|<local>/result| is R|FirModifierList.FirLightModifierList|) [3]"];
|
||||||
156 [label="Exit when branch condition [4]"];
|
156 [label="Exit when branch condition [3]"];
|
||||||
}
|
}
|
||||||
subgraph cluster_54 {
|
subgraph cluster_54 {
|
||||||
color=blue
|
color=blue
|
||||||
157 [label="Enter when branch condition else [5]"];
|
157 [label="Enter when branch condition else [3]"];
|
||||||
158 [label="Exit when branch condition [5]"];
|
158 [label="Exit when branch condition [3]"];
|
||||||
}
|
}
|
||||||
159 [label="Enter when branch result [6]"];
|
159 [label="Enter when branch result [3]"];
|
||||||
subgraph cluster_55 {
|
subgraph cluster_55 {
|
||||||
color=blue
|
color=blue
|
||||||
160 [label="Enter block [6]"];
|
160 [label="Enter block [3]"];
|
||||||
161 [label="Const: String(Fail) [6]"];
|
161 [label="Const: String(Fail) [3]"];
|
||||||
162 [label="Exit block [6]"];
|
162 [label="Exit block [3]"];
|
||||||
}
|
}
|
||||||
163 [label="Exit when branch result [5]"];
|
163 [label="Exit when branch result [3]"];
|
||||||
164 [label="Enter when branch result [5]"];
|
164 [label="Enter when branch result [3]"];
|
||||||
subgraph cluster_56 {
|
subgraph cluster_56 {
|
||||||
color=blue
|
color=blue
|
||||||
165 [label="Enter block [5]"];
|
165 [label="Enter block [3]"];
|
||||||
166 [label="Const: String(OK) [5]"];
|
166 [label="Const: String(OK) [3]"];
|
||||||
167 [label="Exit block [5]"];
|
167 [label="Exit block [3]"];
|
||||||
}
|
}
|
||||||
168 [label="Exit when branch result [4]"];
|
168 [label="Exit when branch result [3]"];
|
||||||
169 [label="Exit when [3]"];
|
169 [label="Exit when [3]"];
|
||||||
}
|
}
|
||||||
170 [label="Jump: ^boxImpl when () {
|
170 [label="Jump: ^boxImpl when () {
|
||||||
@@ -527,108 +527,108 @@ digraph kt44814_kt {
|
|||||||
subgraph cluster_59 {
|
subgraph cluster_59 {
|
||||||
color=blue
|
color=blue
|
||||||
176 [label="Enter when [3]"];
|
176 [label="Enter when [3]"];
|
||||||
177 [label="Access variable this@R|/FirModifierList.Companion.getModifierList| [4]"];
|
177 [label="Access variable this@R|/FirModifierList.Companion.getModifierList| [3]"];
|
||||||
subgraph cluster_60 {
|
subgraph cluster_60 {
|
||||||
color=blue
|
color=blue
|
||||||
178 [label="Enter when branch condition [4]"];
|
178 [label="Enter when branch condition [3]"];
|
||||||
179 [label="Exit $subj [5]"];
|
179 [label="Exit $subj [3]"];
|
||||||
180 [label="Const: Null(null) [5]"];
|
180 [label="Const: Null(null) [3]"];
|
||||||
181 [label="Equality operator == [5]"];
|
181 [label="Equality operator == [3]"];
|
||||||
182 [label="Exit when branch condition [4]"];
|
182 [label="Exit when branch condition [3]"];
|
||||||
}
|
}
|
||||||
subgraph cluster_61 {
|
subgraph cluster_61 {
|
||||||
color=blue
|
color=blue
|
||||||
183 [label="Enter when branch condition [5]"];
|
183 [label="Enter when branch condition [3]"];
|
||||||
184 [label="Exit $subj [6]"];
|
184 [label="Exit $subj [3]"];
|
||||||
185 [label="Type operator: ($subj$ is R|FirPsiSourceElement|) [6]"];
|
185 [label="Type operator: ($subj$ is R|FirPsiSourceElement|) [3]"];
|
||||||
186 [label="Exit when branch condition [5]"];
|
186 [label="Exit when branch condition [3]"];
|
||||||
}
|
}
|
||||||
subgraph cluster_62 {
|
subgraph cluster_62 {
|
||||||
color=blue
|
color=blue
|
||||||
187 [label="Enter when branch condition [6]"];
|
187 [label="Enter when branch condition [3]"];
|
||||||
188 [label="Exit $subj [7]"];
|
188 [label="Exit $subj [3]"];
|
||||||
189 [label="Type operator: ($subj$ is R|FirLightSourceElement|) [7]"];
|
189 [label="Type operator: ($subj$ is R|FirLightSourceElement|) [3]"];
|
||||||
190 [label="Exit when branch condition [6]"];
|
190 [label="Exit when branch condition [3]"];
|
||||||
}
|
}
|
||||||
191 [label="Enter when branch result [7]"];
|
191 [label="Enter when branch result [3]"];
|
||||||
subgraph cluster_63 {
|
subgraph cluster_63 {
|
||||||
color=blue
|
color=blue
|
||||||
192 [label="Enter block [7]"];
|
192 [label="Enter block [3]"];
|
||||||
193 [label="Access variable R|/FirLightSourceElement.lighterASTNode| [9]"];
|
193 [label="Access variable R|/FirLightSourceElement.lighterASTNode| [3]"];
|
||||||
194 [label="Access variable R|/FirLightSourceElement.treeStructure| [9]"];
|
194 [label="Access variable R|/FirLightSourceElement.treeStructure| [3]"];
|
||||||
195 [label="Function call: this@R|/FirModifierList.Companion.getModifierList|.R|/FirLightSourceElement.lighterASTNode|.R|/LighterASTNode.getChildren|(...) [8]" style="filled" fillcolor=yellow];
|
195 [label="Function call: this@R|/FirModifierList.Companion.getModifierList|.R|/FirLightSourceElement.lighterASTNode|.R|/LighterASTNode.getChildren|(...) [3]" style="filled" fillcolor=yellow];
|
||||||
196 [label="Postponed enter to lambda [8]"];
|
196 [label="Postponed enter to lambda [3]"];
|
||||||
subgraph cluster_64 {
|
subgraph cluster_64 {
|
||||||
color=blue
|
color=blue
|
||||||
197 [label="Enter function anonymousFunction [9]" style="filled" fillcolor=red];
|
197 [label="Enter function anonymousFunction [4]" style="filled" fillcolor=red];
|
||||||
subgraph cluster_65 {
|
subgraph cluster_65 {
|
||||||
color=blue
|
color=blue
|
||||||
198 [label="Enter block [9]"];
|
198 [label="Enter block [4]"];
|
||||||
199 [label="Access variable R|<local>/it| [9]"];
|
199 [label="Access variable R|<local>/it| [4]"];
|
||||||
200 [label="Enter safe call [9]"];
|
200 [label="Enter safe call [4]"];
|
||||||
201 [label="Access variable R|/LighterASTNode.tokenType| [9]"];
|
201 [label="Access variable R|/LighterASTNode.tokenType| [4]"];
|
||||||
202 [label="Exit safe call [9]"];
|
202 [label="Exit safe call [4]"];
|
||||||
203 [label="Access qualifier /TokenType [9]"];
|
203 [label="Access qualifier /TokenType [4]"];
|
||||||
204 [label="Access variable R|/TokenType.Companion.MODIFIER_LIST| [9]"];
|
204 [label="Access variable R|/TokenType.Companion.MODIFIER_LIST| [4]"];
|
||||||
205 [label="Equality operator == [9]"];
|
205 [label="Equality operator == [4]"];
|
||||||
206 [label="Exit block [9]"];
|
206 [label="Exit block [4]"];
|
||||||
}
|
}
|
||||||
207 [label="Exit function anonymousFunction [9]" style="filled" fillcolor=red];
|
207 [label="Exit function anonymousFunction [4]" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
208 [label="Postponed exit from lambda [8]"];
|
208 [label="Postponed exit from lambda [3]"];
|
||||||
209 [label="Function call: this@R|/FirModifierList.Companion.getModifierList|.R|/FirLightSourceElement.lighterASTNode|.R|/LighterASTNode.getChildren|(...).R|kotlin/collections/find|<R|LighterASTNode?|>(...) [7]" style="filled" fillcolor=yellow];
|
209 [label="Function call: this@R|/FirModifierList.Companion.getModifierList|.R|/FirLightSourceElement.lighterASTNode|.R|/LighterASTNode.getChildren|(...).R|kotlin/collections/find|<R|LighterASTNode?|>(...) [3]" style="filled" fillcolor=yellow];
|
||||||
210 [label="Exit lhs of ?: [7]"];
|
210 [label="Exit lhs of ?: [3]"];
|
||||||
211 [label="Enter rhs of ?: [7]"];
|
211 [label="Enter rhs of ?: [3]"];
|
||||||
212 [label="Const: Null(null) [7]"];
|
212 [label="Const: Null(null) [3]"];
|
||||||
213 [label="Jump: ^getModifierList Null(null) [7]"];
|
213 [label="Jump: ^getModifierList Null(null) [3]"];
|
||||||
214 [label="Stub [7]" style="filled" fillcolor=gray];
|
214 [label="Stub [3]" style="filled" fillcolor=gray];
|
||||||
215 [label="Lhs of ?: is not null [7]"];
|
215 [label="Lhs of ?: is not null [3]"];
|
||||||
216 [label="Exit ?: [7]"];
|
216 [label="Exit ?: [3]"];
|
||||||
217 [label="Variable declaration: lval modifierListNode: R|LighterASTNode| [7]"];
|
217 [label="Variable declaration: lval modifierListNode: R|LighterASTNode| [3]"];
|
||||||
218 [label="Access variable R|<local>/modifierListNode| [8]"];
|
218 [label="Access variable R|<local>/modifierListNode| [3]"];
|
||||||
219 [label="Access variable R|/FirLightSourceElement.treeStructure| [8]"];
|
219 [label="Access variable R|/FirLightSourceElement.treeStructure| [3]"];
|
||||||
220 [label="Function call: R|/FirModifierList.FirLightModifierList.FirLightModifierList|(...) [7]" style="filled" fillcolor=yellow];
|
220 [label="Function call: R|/FirModifierList.FirLightModifierList.FirLightModifierList|(...) [3]" style="filled" fillcolor=yellow];
|
||||||
221 [label="Exit block [7]"];
|
221 [label="Exit block [3]"];
|
||||||
}
|
}
|
||||||
222 [label="Exit when branch result [6]"];
|
222 [label="Exit when branch result [3]"];
|
||||||
223 [label="Enter when branch result [6]"];
|
223 [label="Enter when branch result [3]"];
|
||||||
subgraph cluster_66 {
|
subgraph cluster_66 {
|
||||||
color=blue
|
color=blue
|
||||||
224 [label="Enter block [6]"];
|
224 [label="Enter block [3]"];
|
||||||
225 [label="Access variable R|/FirPsiSourceElement.psi| [6]"];
|
225 [label="Access variable R|/FirPsiSourceElement.psi| [3]"];
|
||||||
226 [label="Type operator: (this@R|/FirModifierList.Companion.getModifierList|.R|/FirPsiSourceElement.psi| as? R|KtModifierListOwner|) [6]"];
|
226 [label="Type operator: (this@R|/FirModifierList.Companion.getModifierList|.R|/FirPsiSourceElement.psi| as? R|KtModifierListOwner|) [3]"];
|
||||||
227 [label="Enter safe call [6]"];
|
227 [label="Enter safe call [3]"];
|
||||||
228 [label="Access variable R|/KtModifierListOwner.modifierList| [6]"];
|
228 [label="Access variable R|/KtModifierListOwner.modifierList| [3]"];
|
||||||
229 [label="Enter safe call [6]"];
|
229 [label="Enter safe call [3]"];
|
||||||
230 [label="Postponed enter to lambda [7]"];
|
230 [label="Postponed enter to lambda [3]"];
|
||||||
subgraph cluster_67 {
|
subgraph cluster_67 {
|
||||||
color=blue
|
color=blue
|
||||||
231 [label="Enter function anonymousFunction [8]" style="filled" fillcolor=red];
|
231 [label="Enter function anonymousFunction [4]" style="filled" fillcolor=red];
|
||||||
subgraph cluster_68 {
|
subgraph cluster_68 {
|
||||||
color=blue
|
color=blue
|
||||||
232 [label="Enter block [8]"];
|
232 [label="Enter block [4]"];
|
||||||
233 [label="Access variable R|<local>/it| [9]"];
|
233 [label="Access variable R|<local>/it| [4]"];
|
||||||
234 [label="Function call: R|/FirModifierList.FirPsiModifierList.FirPsiModifierList|(...) [8]" style="filled" fillcolor=yellow];
|
234 [label="Function call: R|/FirModifierList.FirPsiModifierList.FirPsiModifierList|(...) [4]" style="filled" fillcolor=yellow];
|
||||||
235 [label="Exit block [8]"];
|
235 [label="Exit block [4]"];
|
||||||
}
|
}
|
||||||
236 [label="Exit function anonymousFunction [8]" style="filled" fillcolor=red];
|
236 [label="Exit function anonymousFunction [4]" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
237 [label="Postponed exit from lambda [7]"];
|
237 [label="Postponed exit from lambda [3]"];
|
||||||
238 [label="Function call: $subj$.R|kotlin/let|<R|KtModifierList|, R|FirModifierList.FirPsiModifierList|>(...) [6]" style="filled" fillcolor=yellow];
|
238 [label="Function call: $subj$.R|kotlin/let|<R|KtModifierList|, R|FirModifierList.FirPsiModifierList|>(...) [3]" style="filled" fillcolor=yellow];
|
||||||
239 [label="Exit safe call [6]"];
|
239 [label="Exit safe call [3]"];
|
||||||
240 [label="Exit safe call [6]"];
|
240 [label="Exit safe call [3]"];
|
||||||
241 [label="Exit block [6]"];
|
241 [label="Exit block [3]"];
|
||||||
}
|
}
|
||||||
242 [label="Exit when branch result [5]"];
|
242 [label="Exit when branch result [3]"];
|
||||||
243 [label="Merge postponed lambda exits [6]"];
|
243 [label="Merge postponed lambda exits [3]"];
|
||||||
244 [label="Enter when branch result [5]"];
|
244 [label="Enter when branch result [3]"];
|
||||||
subgraph cluster_69 {
|
subgraph cluster_69 {
|
||||||
color=blue
|
color=blue
|
||||||
245 [label="Enter block [5]"];
|
245 [label="Enter block [3]"];
|
||||||
246 [label="Const: Null(null) [5]"];
|
246 [label="Const: Null(null) [3]"];
|
||||||
247 [label="Exit block [5]"];
|
247 [label="Exit block [3]"];
|
||||||
}
|
}
|
||||||
248 [label="Exit when branch result [4]"];
|
248 [label="Exit when branch result [3]"];
|
||||||
249 [label="Exit when [3]"];
|
249 [label="Exit when [3]"];
|
||||||
}
|
}
|
||||||
250 [label="Jump: ^getModifierList when (this@R|/FirModifierList.Companion.getModifierList|) {
|
250 [label="Jump: ^getModifierList when (this@R|/FirModifierList.Companion.getModifierList|) {
|
||||||
@@ -861,7 +861,7 @@ digraph kt44814_kt {
|
|||||||
subgraph cluster_78 {
|
subgraph cluster_78 {
|
||||||
color=blue
|
color=blue
|
||||||
274 [label="Enter block [1]"];
|
274 [label="Enter block [1]"];
|
||||||
275 [label="Access qualifier /FirModifierList [2]"];
|
275 [label="Access qualifier /FirModifierList [1]"];
|
||||||
276 [label="Function call: Q|FirModifierList|.R|/FirModifierList.Companion.boxImpl|() [1]" style="filled" fillcolor=yellow];
|
276 [label="Function call: Q|FirModifierList|.R|/FirModifierList.Companion.boxImpl|() [1]" style="filled" fillcolor=yellow];
|
||||||
277 [label="Jump: ^box Q|FirModifierList|.R|/FirModifierList.Companion.boxImpl|() [1]"];
|
277 [label="Jump: ^box Q|FirModifierList|.R|/FirModifierList.Companion.boxImpl|() [1]"];
|
||||||
278 [label="Stub [1]" style="filled" fillcolor=gray];
|
278 [label="Stub [1]" style="filled" fillcolor=gray];
|
||||||
|
|||||||
Reference in New Issue
Block a user