diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 72a878121d3..07450419701 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -862,7 +862,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid } /** - * The [InnerScope] that includes code generated by [genFinalize] when leaving it + * The [InnerScope] that includes code generated by [genFinalizeImpl] when leaving it * with `return`, `break`, `continue` or throwing exception. */ private abstract inner class FinalizingScope() : CatchingScope() { @@ -878,24 +878,62 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid // Jump to finalize-and-return instead of simply returning. override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) { val block = returnBlocks.getOrPut(target) { - using(outerContext) { - continuationBlock(target.returnType!!) { returnValue -> - genFinalize() - outerContext.genReturn(target, returnValue) - } + continuationBlock(target.returnType!!) { returnValue -> + genFinalize() + outerContext.genReturn(target, returnValue) } } jump(block, value) } + /** + * Cache for [genBreak]. + */ + private val breakBlocks = mutableMapOf() + + // Jump to finalize-and-break instead of simply breaking. + override fun genBreak(destination: IrBreak) { + val block = breakBlocks.getOrPut(destination.loop) { + codegen.basicBlock("finalizeAndBreak") { + genFinalize() + outerContext.genBreak(destination) + } + } + + codegen.br(block) + } + + /** + * Cache for [genContinue]. + */ + private val continueBlocks = mutableMapOf() + + // Jump to finalize-and-continue instead of simply continuing. + override fun genContinue(destination: IrContinue) { + val block = breakBlocks.getOrPut(destination.loop) { + codegen.basicBlock("finalizeAndContinue") { + genFinalize() + outerContext.genContinue(destination) + } + } + + codegen.br(block) + } + // When an exception is caught, finalize the scope and rethrow the exception. override fun genHandler(exception: LLVMValueRef) { - genFinalize() + genFinalizeImpl() outerContext.genThrow(exception) } - protected abstract fun genFinalize() + private fun genFinalize() { + using(outerContext) { + this.genFinalizeImpl() + } + } + + protected abstract fun genFinalizeImpl() } /** @@ -915,7 +953,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid val scope = if (finalize == null) null else { object : FinalizingScope() { - override fun genFinalize() { + override fun genFinalizeImpl() { finalize() } } diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index f96052a180e..f37e65ca731 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -575,7 +575,6 @@ task finally8(type: RunKonanTest) { } task finally9(type: RunKonanTest) { - disabled = true goldValue = "Finally 1\nFinally 2\nAfter\n" source = "codegen/try/finally9.kt" }