From 67f553d503851423a94aa5fa1280880e36473948 Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Fri, 1 Nov 2019 11:16:11 +0300 Subject: [PATCH] Fix #3476 (#3526) --- .../lower/NativeSuspendFunctionLowering.kt | 7 +-- backend.native/tests/build.gradle | 4 ++ .../codegen/coroutines/controlFlow_chain.kt | 43 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 backend.native/tests/codegen/coroutines/controlFlow_chain.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt index 60d3014d30c..8d259ca0e33 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt @@ -338,11 +338,12 @@ internal class NativeSuspendFunctionsLowering(ctx: Context): AbstractSuspendFunc suspendCall = newChildren[2] } expression.isSuspendCall -> { - val lastChild = newChildren.last() - if (lastChild != null) { + val lastChildIndex = newChildren.indexOfLast { it != null } + if (lastChildIndex != -1) { // Save state as late as possible. + val lastChild = newChildren[lastChildIndex]!! calledSaveState = true - newChildren[numberOfChildren - 1] = + newChildren[lastChildIndex] = irBlock(lastChild) { if (lastChild.isPure()) { +irCall(saveState) diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 4c6dcdc8a2b..b5029c3c435 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -1622,6 +1622,10 @@ task coroutines_correctOrder1(type: KonanLocalTest) { source = "codegen/coroutines/correctOrder1.kt" } +task coroutines_controlFlow_chain(type: KonanLocalTest) { + source = "codegen/coroutines/controlFlow_chain.kt" +} + task coroutines_controlFlow_if1(type: KonanLocalTest) { goldValue = "f1\ns1\nf3\n84\n" source = "codegen/coroutines/controlFlow_if1.kt" diff --git a/backend.native/tests/codegen/coroutines/controlFlow_chain.kt b/backend.native/tests/codegen/coroutines/controlFlow_chain.kt new file mode 100644 index 00000000000..4b14bdf5681 --- /dev/null +++ b/backend.native/tests/codegen/coroutines/controlFlow_chain.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_chain + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +// See https://github.com/JetBrains/kotlin-native/issues/3476 +@Test fun runTest() { + var result = 0 + builder { + foo().bar() + result = 1 + } + assertEquals(1, result) +} + +class Foo { + suspend fun bar() { + suspendHere() + } +} + +suspend fun foo() = Foo() \ No newline at end of file