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")
|
prologueBb = LLVMAppendBasicBlock(function, "prologue")
|
||||||
entryBb = LLVMAppendBasicBlock(function, "entry")
|
entryBb = LLVMAppendBasicBlock(function, "entry")
|
||||||
epilogueBb = LLVMAppendBasicBlock(function, "epilogue")
|
epilogueBb = LLVMAppendBasicBlock(function, "epilogue")
|
||||||
|
cleanupLandingpad = LLVMAppendBasicBlock(function, "cleanup_landingpad")!!
|
||||||
positionAtEnd(entryBb!!)
|
positionAtEnd(entryBb!!)
|
||||||
slotsPhi = phi(kObjHeaderPtrPtr)
|
slotsPhi = phi(kObjHeaderPtrPtr)
|
||||||
slotCount = 0
|
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()
|
returns.clear()
|
||||||
vars.clear()
|
vars.clear()
|
||||||
returnSlot = null
|
returnSlot = null
|
||||||
@@ -104,6 +112,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
private var prologueBb: LLVMBasicBlockRef? = null
|
private var prologueBb: LLVMBasicBlockRef? = null
|
||||||
private var entryBb: LLVMBasicBlockRef? = null
|
private var entryBb: LLVMBasicBlockRef? = null
|
||||||
private var epilogueBb: LLVMBasicBlockRef? = null
|
private var epilogueBb: LLVMBasicBlockRef? = null
|
||||||
|
private var cleanupLandingpad: LLVMBasicBlockRef? = null
|
||||||
|
|
||||||
fun setName(value: LLVMValueRef, name: String) = LLVMSetValueName(value, name)
|
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.
|
* 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 staticData = StaticData(context)
|
||||||
|
|
||||||
val runtimeFile = context.config.configuration.get(KonanConfigKeys.RUNTIME_FILE)!!
|
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 checkInstanceFunction = importRtFunction("CheckInstance")
|
||||||
val throwExceptionFunction = importRtFunction("ThrowException")
|
val throwExceptionFunction = importRtFunction("ThrowException")
|
||||||
val appendToInitalizersTail = importRtFunction("AppendToInitializersTail")
|
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 memsetFunction = importMemset()
|
||||||
|
|
||||||
val usedFunctions = mutableListOf<LLVMValueRef>()
|
val usedFunctions = mutableListOf<LLVMValueRef>()
|
||||||
val staticInitializers = mutableListOf<LLVMValueRef>()
|
val staticInitializers = mutableListOf<LLVMValueRef>()
|
||||||
val fileInitializers = mutableListOf<IrElement>()
|
val fileInitializers = mutableListOf<IrElement>()
|
||||||
|
|||||||
+3
-11
@@ -913,15 +913,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
*/
|
*/
|
||||||
private fun genLandingpad() {
|
private fun genLandingpad() {
|
||||||
with(codegen) {
|
with(codegen) {
|
||||||
// Type of `landingpad` instruction result (depends on personality function):
|
val landingpadResult = codegen.gxxLandingpad(numClauses = 1, name = "lp")
|
||||||
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")
|
|
||||||
|
|
||||||
LLVMAddClause(landingpadResult, LLVMConstNull(kInt8Ptr))
|
LLVMAddClause(landingpadResult, LLVMConstNull(kInt8Ptr))
|
||||||
|
|
||||||
@@ -931,7 +923,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val exceptionRecord = LLVMBuildExtractValue(codegen.builder, landingpadResult, 0, "er")
|
val exceptionRecord = LLVMBuildExtractValue(codegen.builder, landingpadResult, 0, "er")
|
||||||
|
|
||||||
// __cxa_begin_catch returns pointer to C++ exception object.
|
// __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), "")
|
val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord), "")
|
||||||
|
|
||||||
// Pointer to KotlinException instance:
|
// Pointer to KotlinException instance:
|
||||||
@@ -942,7 +934,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val exceptionPtr = loadSlot(exceptionPtrPtr, true, "exception")
|
val exceptionPtr = loadSlot(exceptionPtrPtr, true, "exception")
|
||||||
|
|
||||||
// __cxa_end_catch performs some C++ cleanup, including calling `KotlinException` class destructor.
|
// __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(), "")
|
call(endCatch, listOf(), "")
|
||||||
|
|
||||||
jumpToHandler(exceptionPtr)
|
jumpToHandler(exceptionPtr)
|
||||||
|
|||||||
-10
@@ -193,16 +193,6 @@ internal fun getGlobalType(ptrToGlobal: LLVMValueRef): LLVMTypeRef {
|
|||||||
return LLVMGetElementType(ptrToGlobal.type)!!
|
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 {
|
internal fun ContextUtils.externalGlobal(name: String, type: LLVMTypeRef): LLVMValueRef {
|
||||||
val found = LLVMGetNamedGlobal(context.llvmModule, name)
|
val found = LLVMGetNamedGlobal(context.llvmModule, name)
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user