From 9f2cdb01309a1076a861eb4062950d5dc5b74054 Mon Sep 17 00:00:00 2001 From: Vladimir Sukharev Date: Thu, 11 Aug 2022 08:27:06 +0000 Subject: [PATCH] Fix basic blocks order for WHEN expression Merge-request: KT-MR-6833 Merged-by: Vladimir Sukharev --- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 79 ++++++++++++------- .../backend.native/tests/build.gradle | 4 + .../kt53119_append_generated.kt | 36 ++++----- .../kt53119_append_manual.kt | 4 +- .../kt53119_plus_extension.kt | 22 ++---- .../kt53119_plus_member.kt | 12 +-- .../backend.native/tests/filecheck/when.kt | 24 ++++++ 7 files changed, 106 insertions(+), 75 deletions(-) create mode 100644 kotlin-native/backend.native/tests/filecheck/when.kt diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index b5249c33956..95f8999b47d 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1283,12 +1283,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map CASE1, COND2 -> CASE2, ELSE -> UNCONDITIONAL } + * the following sequence of basic blocks is generated: + * -- if COND1 + * -- CASE1 + * -- NEXT1(if COND2) + * -- CASE2 + * -- NEXT2 (UNCONDITIONAL) + * -- EXIT + */ private fun evaluateWhen(expression: IrWhen, resultSlot: LLVMValueRef?): LLVMValueRef { context.log{"evaluateWhen : ${ir2string(expression)}"} - val whenEmittingContext = WhenEmittingContext(expression) - generateDebugTrambolineIf("when", expression) - expression.branches.forEach { - val bbNext = if (it == expression.branches.last()) - null - else - functionGenerationContext.basicBlock("when_next", it.startLocation, it.endLocation) - generateWhenCase(whenEmittingContext, it, bbNext, resultSlot) + + // First, generate all empty basic blocks for conditions and variants + val bbOfFirstConditionCheck = functionGenerationContext.currentBlock + val branchInfos: List = expression.branches.map { + // Carefully create empty basic blocks and position them one after another + val bbCase = if (it.isUnconditional()) null else + functionGenerationContext.basicBlock("when_case", it.startLocation, it.endLocation).apply { functionGenerationContext.positionAtEnd(this) } + val bbNext = if (it.isUnconditional() || it == expression.branches.last()) null else + functionGenerationContext.basicBlock("when_next", it.startLocation, it.endLocation).apply { functionGenerationContext.positionAtEnd(this) } + BranchCaseNextInfo(it, bbCase, bbNext, resultSlot) } + // Now, exit basic block can be positioned after all blocks of WHEN expression + val whenEmittingContext = WhenEmittingContext(expression, lastBBOfWhenCases = functionGenerationContext.currentBlock) + functionGenerationContext.positionAtEnd(bbOfFirstConditionCheck) + + branchInfos.forEach { generateWhenCase(whenEmittingContext, it) } if (whenEmittingContext.bbExit.isInitialized()) functionGenerationContext.positionAtEnd(whenEmittingContext.bbExit.value) @@ -1330,25 +1350,26 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map 10 + 1 -> 11 + 2 -> 12 + else -> 13 + }) +} +// CHECK-LABEL: define void @"kfun:#main(){}"() +// CHECK: when_case +// CHECK: when_next +// CHECK: when_case1 +// CHECK: when_next2 +// CHECK: when_case3 +// CHECK: when_next4 +// CHECK: when_exit +// CHECK: call void @"kfun:kotlin.io#println(kotlin.Any?) +// CHECK: ret void