backend: generate refs cleanup code for exceptional unwind
This commit is contained in:
committed by
SvyatoslavScherbina
parent
57ae3a1cc7
commit
d389897631
+20
@@ -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.
|
||||
*
|
||||
|
||||
+22
@@ -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<LLVMValueRef>()
|
||||
val staticInitializers = mutableListOf<LLVMValueRef>()
|
||||
val fileInitializers = mutableListOf<IrElement>()
|
||||
|
||||
+3
-11
@@ -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)
|
||||
|
||||
-10
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user