backend: generate refs cleanup code for exceptional unwind

This commit is contained in:
Svyatoslav Scherbina
2016-12-29 15:40:03 +07:00
committed by SvyatoslavScherbina
parent 57ae3a1cc7
commit d389897631
4 changed files with 45 additions and 21 deletions
@@ -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.
*
@@ -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>()
@@ -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)
@@ -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) {