From d389897631c2baacea715e2fe5569c47fa8f7cd0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 29 Dec 2016 15:40:03 +0700 Subject: [PATCH] backend: generate refs cleanup code for exceptional unwind --- .../backend/konan/llvm/CodeGenerator.kt | 20 +++++++++++++++++ .../kotlin/backend/konan/llvm/ContextUtils.kt | 22 +++++++++++++++++++ .../kotlin/backend/konan/llvm/IrToBitcode.kt | 14 +++--------- .../kotlin/backend/konan/llvm/LlvmUtils.kt | 10 --------- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index bc29fa95e77..d1cd9ae50be 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -42,6 +42,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { prologueBb = LLVMAppendBasicBlock(function, "prologue") entryBb = LLVMAppendBasicBlock(function, "entry") epilogueBb = LLVMAppendBasicBlock(function, "epilogue") + cleanupLandingpad = LLVMAppendBasicBlock(function, "cleanup_landingpad")!! positionAtEnd(entryBb!!) slotsPhi = phi(kObjHeaderPtrPtr) slotCount = 0 @@ -88,6 +89,13 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { } } + appendingTo(cleanupLandingpad!!) { + val landingpad = gxxLandingpad(numClauses = 0) + LLVMSetCleanup(landingpad, 1) + releaseVars() + LLVMBuildResume(builder, landingpad) + } + returns.clear() vars.clear() returnSlot = null @@ -104,6 +112,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { private var prologueBb: LLVMBasicBlockRef? = null private var entryBb: LLVMBasicBlockRef? = null private var epilogueBb: LLVMBasicBlockRef? = null + private var cleanupLandingpad: LLVMBasicBlockRef? = null fun setName(value: LLVMValueRef, name: String) = LLVMSetValueName(value, name) @@ -302,6 +311,17 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { //-------------------------------------------------------------------------// + fun gxxLandingpad(numClauses: Int, name: String = ""): LLVMValueRef { + val personalityFunction = LLVMConstBitCast(context.llvm.gxxPersonalityFunction, int8TypePtr) + + // Type of `landingpad` instruction result (depends on personality function): + val landingpadType = structType(int8TypePtr, int32Type) + + return LLVMBuildLandingPad(builder, landingpadType, personalityFunction, numClauses, name)!! + } + + //-------------------------------------------------------------------------// + /** * Represents the mutable position of instructions being inserted. * diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 7d83c26670a..2609c23de9d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -220,6 +220,22 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { } } + private fun externalFunction(name: String, type: LLVMTypeRef): LLVMValueRef { + val found = LLVMGetNamedFunction(context.llvmModule, name) + if (found != null) { + assert (getFunctionType(found) == type) + return found + } else { + return LLVMAddFunction(context.llvmModule, name, type)!! + } + } + + private fun externalNounwindFunction(name: String, type: LLVMTypeRef): LLVMValueRef { + val function = externalFunction(name, type) + LLVMAddFunctionAttr(function, LLVMAttribute.LLVMNoUnwindAttribute) + return function + } + val staticData = StaticData(context) val runtimeFile = context.config.configuration.get(KonanConfigKeys.RUNTIME_FILE)!! @@ -250,7 +266,13 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val checkInstanceFunction = importRtFunction("CheckInstance") val throwExceptionFunction = importRtFunction("ThrowException") val appendToInitalizersTail = importRtFunction("AppendToInitializersTail") + + val gxxPersonalityFunction = externalNounwindFunction("__gxx_personality_v0", functionType(int32Type, true)) + val cxaBeginCatchFunction = externalNounwindFunction("__cxa_begin_catch", functionType(int8TypePtr, false, int8TypePtr)) + val cxaEndCatchFunction = externalNounwindFunction("__cxa_end_catch", functionType(voidType, false)) + val memsetFunction = importMemset() + val usedFunctions = mutableListOf() val staticInitializers = mutableListOf() val fileInitializers = mutableListOf() 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 d6b7ea3110c..89ec33724ba 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 @@ -913,15 +913,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid */ private fun genLandingpad() { with(codegen) { - // Type of `landingpad` instruction result (depends on personality function): - val landingpadType = structType(int8TypePtr, int32Type) - - val personalityFunction = externalFunction("__gxx_personality_v0", functionType(int32Type, true)) - val personalityFunctionRaw = LLVMConstBitCast(personalityFunction, int8TypePtr)!! - - val numClauses = 1 - val landingpadResult = - LLVMBuildLandingPad(codegen.builder, landingpadType, personalityFunctionRaw, numClauses, "lp") + val landingpadResult = codegen.gxxLandingpad(numClauses = 1, name = "lp") LLVMAddClause(landingpadResult, LLVMConstNull(kInt8Ptr)) @@ -931,7 +923,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid val exceptionRecord = LLVMBuildExtractValue(codegen.builder, landingpadResult, 0, "er") // __cxa_begin_catch returns pointer to C++ exception object. - val beginCatch = externalFunction("__cxa_begin_catch", functionType(int8TypePtr, false, int8TypePtr)) + val beginCatch = context.llvm.cxaBeginCatchFunction val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord), "") // Pointer to KotlinException instance: @@ -942,7 +934,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid val exceptionPtr = loadSlot(exceptionPtrPtr, true, "exception") // __cxa_end_catch performs some C++ cleanup, including calling `KotlinException` class destructor. - val endCatch = externalFunction("__cxa_end_catch", functionType(voidType, false)) + val endCatch = context.llvm.cxaEndCatchFunction call(endCatch, listOf(), "") jumpToHandler(exceptionPtr) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt index 3ba490dafe1..0f29071c24c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -193,16 +193,6 @@ internal fun getGlobalType(ptrToGlobal: LLVMValueRef): LLVMTypeRef { return LLVMGetElementType(ptrToGlobal.type)!! } -internal fun ContextUtils.externalFunction(name: String, type: LLVMTypeRef): LLVMValueRef { - val found = LLVMGetNamedFunction(context.llvmModule, name) - if (found != null) { - assert (getFunctionType(found) == type) - return found - } else { - return LLVMAddFunction(context.llvmModule, name, type)!! - } -} - internal fun ContextUtils.externalGlobal(name: String, type: LLVMTypeRef): LLVMValueRef { val found = LLVMGetNamedGlobal(context.llvmModule, name) if (found != null) {