From 32ce25400190f1068ceb5bd5edb12b50bc63217e Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Fri, 27 Jan 2023 17:20:13 +0200 Subject: [PATCH] [K/N] Added a filecheck test on suspend lambdas tail calls --- .../backend.native/tests/build.gradle | 8 +- ...alls.kt => suspend_tailcalls_functions.kt} | 0 .../filecheck/suspend_tailcalls_lambdas.kt | 383 ++++++++++++++++++ 3 files changed, 389 insertions(+), 2 deletions(-) rename kotlin-native/backend.native/tests/filecheck/{suspend_tailcalls.kt => suspend_tailcalls_functions.kt} (100%) create mode 100644 kotlin-native/backend.native/tests/filecheck/suspend_tailcalls_lambdas.kt diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index e88e21e41de..036948c4249 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -6666,8 +6666,12 @@ fileCheckTest("filecheck_suspend_returnNothing") { annotatedSource = project.file('filecheck/suspend_returnNothing.kt') } -fileCheckTest("filecheck_suspend_tailcalls") { - annotatedSource = project.file('filecheck/suspend_tailcalls.kt') +fileCheckTest("filecheck_suspend_tailcalls_functions") { + annotatedSource = project.file('filecheck/suspend_tailcalls_functions.kt') +} + +fileCheckTest("filecheck_suspend_tailcalls_lambdas") { + annotatedSource = project.file('filecheck/suspend_tailcalls_lambdas.kt') } fileCheckTest("filecheck_bce") { diff --git a/kotlin-native/backend.native/tests/filecheck/suspend_tailcalls.kt b/kotlin-native/backend.native/tests/filecheck/suspend_tailcalls_functions.kt similarity index 100% rename from kotlin-native/backend.native/tests/filecheck/suspend_tailcalls.kt rename to kotlin-native/backend.native/tests/filecheck/suspend_tailcalls_functions.kt diff --git a/kotlin-native/backend.native/tests/filecheck/suspend_tailcalls_lambdas.kt b/kotlin-native/backend.native/tests/filecheck/suspend_tailcalls_lambdas.kt new file mode 100644 index 00000000000..512d89614f7 --- /dev/null +++ b/kotlin-native/backend.native/tests/filecheck/suspend_tailcalls_lambdas.kt @@ -0,0 +1,383 @@ +/* + * Copyright 2010-2022 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. + */ + +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 sUnit(): Unit = suspendCoroutineUninterceptedOrReturn { x -> + println("sUnit") + x.resume(Unit) + COROUTINE_SUSPENDED +} + +suspend fun sUnit2(): Unit = suspendCoroutineUninterceptedOrReturn { x -> + println("sUnit2") + x.resume(Unit) + COROUTINE_SUSPENDED +} + +suspend fun sInt(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("sInt") + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun sInt2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("sInt2") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builderUnit(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun builderInt(c: suspend () -> Int) { + c.startCoroutine(EmptyContinuation) +} + + +fun s1() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s1$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s1$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + println("s1") + } + // CHECK-LABEL: epilogue: +} + +fun s2() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s2$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s2$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + println("s2") + sUnit() + } + // CHECK-LABEL: epilogue: +} + +fun s3() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s3$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s3$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + println("s3") + sUnit() + return@builderUnit + } + // CHECK-LABEL: epilogue: +} + +fun s4() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s4$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s4$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + println("s4") + return@builderInt sInt() + } + // CHECK-LABEL: epilogue: +} + +fun s5() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s5$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s5$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + println("s5") + run { sUnit() } + } + // CHECK-LABEL: epilogue: +} + +fun s6() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s6$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s6$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s6") + sUnit() + } + } + // CHECK-LABEL: epilogue: +} + +fun s7() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s7$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s7$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s7") + sInt() + } + } + // CHECK-LABEL: epilogue: +} + +fun s8() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s8$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s8$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s8") + return@builderInt sInt() + } + } + // CHECK-LABEL: epilogue: +} + +fun s9() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s9$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s9$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s9-1") + run { + println("s9-2") + sUnit() + } + } + } + // CHECK-LABEL: epilogue: +} + +fun s10() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s10$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s10$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s10-1") + return@builderInt run { + println("s10-2") + sInt() + } + } + } + // CHECK-LABEL: epilogue: +} + +fun s11() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s11$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s11$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + println("s11") + sUnit() + return@builderUnit + } + // CHECK-LABEL: epilogue: +} + +fun s12() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s12$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s12$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s12") + sUnit() + return@builderUnit + } + } + // CHECK-LABEL: epilogue: +} + +fun s13() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s13$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s13$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s13") + sUnit() + } + return@builderUnit + } + // CHECK-LABEL: epilogue: +} + +fun s14() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s14$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s14$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s14") + sUnit() + return@run + } + } + // CHECK-LABEL: epilogue: +} + +@Suppress("UNREACHABLE_CODE") +fun s15() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s15$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s15$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run { + println("s15-1") + return@builderInt run { + println("s15-2") + return@builderInt sInt() + } + } + } + // CHECK-LABEL: epilogue: +} + +fun s16() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s16$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s16$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + run outer@{ + println("s16-1") + return@builderInt run inner@{ + println("s16-2") + return@inner sInt() + } + } + } + // CHECK-LABEL: epilogue: +} + +@Suppress("UNREACHABLE_CODE") +fun s17() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s17$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s17$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + return@builderInt run outer@{ + println("s17-1") + return@builderInt run inner@{ + println("s17-2") + return@outer sInt() + } + } + } + // CHECK-LABEL: epilogue: +} + +fun s18(f: Boolean) { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s18$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s18$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + if (f) { + println("s18-1") + sUnit() + } else { + println("s18-2") + sUnit2() + } + } + // CHECK-LABEL: epilogue: +} + +fun s19(f: Boolean) { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s19$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s19$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + if (f) { + println("s19-1") + return@builderInt sInt() + } else { + println("s19-2") + return@builderInt sInt2() + } + } + // CHECK-LABEL: epilogue: +} + +fun s20(f: Boolean) { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s20$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s20$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + return@builderInt if (f) { + println("s20-1") + sInt() + } else { + println("s20-2") + sInt2() + } + } + // CHECK-LABEL: epilogue: +} + +fun s21() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s21$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s21$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + try { + println("s21") + } catch (t: Throwable) { + sUnit() + } + } + // CHECK-LABEL: epilogue: +} + +fun s22() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s22$lambda${{[0-9]*}} + builderInt { + // CHECK-NOT: call void @"kfun:$s22$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + try { + println("s22") + } catch (t: Throwable) { + return@builderInt sInt() + } + return@builderInt sInt2() + } + // CHECK-LABEL: epilogue: +} + +fun s23(f: Boolean) { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s23$lambda${{[0-9]*}} + builderUnit { + // CHECK-NOT: call void @"kfun:$s23$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + val x = run { + if (f) { + println("s23") + sUnit() + return@builderUnit + } + 42 + } + println(x) + } + // CHECK-LABEL: epilogue: +} + +fun s24() { + // CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s24$lambda${{[0-9]*}} + builderUnit { + // CHECK: call void @"kfun:$s24$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}. + sInt() + } + // CHECK-LABEL: epilogue: +} + +fun main() { + s1() + s2() + s3() + s4() + s5() + s6() + s7() + s8() + s9() + s10() + s11() + s12() + s13() + s14() + s15() + s16() + s17() + s18(true) + s19(true) + s20(true) + s21() + s22() + s23(true) + s24() +} \ No newline at end of file