diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/Stack.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/Stack.kt index c0b353f8c61..31c9d11cef7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/Stack.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/Stack.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.asReversedFrozen import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -16,6 +17,11 @@ abstract class Stack { abstract fun pop(): T abstract fun push(value: T) abstract fun reset() + + /** + * returns all elements of the stack in order of retrieval + */ + abstract fun all(): List } fun stackOf(vararg values: T): Stack = StackImpl(*values) @@ -38,6 +44,8 @@ private class StackImpl(vararg values: T) : Stack() { override fun reset() { stack.clear() } + + override fun all(): List = stack.asReversedFrozen() } class NodeStorage> : Stack(){ @@ -65,6 +73,8 @@ class NodeStorage> : Stack(){ stack.reset() map.clear() } + + override fun all(): List = stack.all() } class SymbolBasedNodeStorage> : Stack() where T : FirElement { @@ -92,4 +102,6 @@ class SymbolBasedNodeStorage> : Stack() where T : FirElemen stack.reset() map.clear() } + + override fun all(): List = stack.all() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 5c8d17dc09f..392f90fb427 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -1389,21 +1389,16 @@ class ControlFlowGraphBuilder { addBackEdge(node, targetNode, label = label) } } else { - //TODO this supports single try-finally block only - //need to get all try-finally up to target + //go through all final nodes between node and target val finallyNodes = finallyBefore(targetNode) - if (finallyNodes != null) { - val (finallyEnter, finallyExit) = finallyNodes - addEdge(node, finallyEnter, propagateDeadness = false, label = label) - if (!finallyExit.followingNodes.contains(targetNode)) { - addEdge(finallyExit, targetNode, propagateDeadness = false, label = label) - } - if (trackJump) { - //actually we can store all returns like this, but not sure if it make anything better - nonDirectJumps.put(targetNode, node) - } - } else { - addEdge(node, targetNode, propagateDeadness = false, label = label) + val finalFrom = finallyNodes.fold(node) { from, (finallyEnter, tryExit) -> + addEdgeIfNotExist(from, finallyEnter, propagateDeadness = false, label = label) + tryExit + } + addEdgeIfNotExist(finalFrom, targetNode, propagateDeadness = false, label = label) + if (trackJump && finallyNodes.isNotEmpty()) { + //actually we can store all returns like this, but not sure if it makes anything better + nonDirectJumps.put(targetNode, node) } } } @@ -1428,14 +1423,29 @@ class ControlFlowGraphBuilder { lastNodes.push(stub) } - private fun finallyBefore(target: CFGNode<*>): Pair? { - return finallyEnterNodes.topOrNull()?.takeIf { it.level > target.level }?.let { it to tryExitNodes.top() } + private fun finallyBefore(target: CFGNode<*>): List> { + return finallyEnterNodes.all().takeWhile { it.level > target.level }.map { + it to tryExitNodes[it.fir]!! + } } private fun popAndAddEdge(to: CFGNode<*>, preferredKind: EdgeKind = EdgeKind.Forward) { addEdge(lastNodes.pop(), to, preferredKind = preferredKind) } + private fun addEdgeIfNotExist( + from: CFGNode<*>, + to: CFGNode<*>, + propagateDeadness: Boolean = true, + isDead: Boolean = false, + preferredKind: EdgeKind = EdgeKind.Forward, + label: EdgeLabel = NormalPath + ) { + if (!from.followingNodes.contains(to)) { + addEdge(from, to, propagateDeadness, isDead, preferredKind = preferredKind, label = label) + } + } + private fun addEdge( from: CFGNode<*>, to: CFGNode<*>,