Native: minor exception handling refactoring
Move parts of exception handling implementation from IrToBitcode to CodeGenerator, to allow using filteringExceptionHandler in ObjCExport.
This commit is contained in:
committed by
Space
parent
2801704ad3
commit
388538be60
+21
-4
@@ -95,6 +95,19 @@ internal sealed class ExceptionHandler {
|
|||||||
abstract class Local : ExceptionHandler() {
|
abstract class Local : ExceptionHandler() {
|
||||||
abstract val unwind: LLVMBasicBlockRef
|
abstract val unwind: LLVMBasicBlockRef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun genThrow(
|
||||||
|
functionGenerationContext: FunctionGenerationContext,
|
||||||
|
kotlinException: LLVMValueRef
|
||||||
|
): Unit = with(functionGenerationContext) {
|
||||||
|
call(
|
||||||
|
context.llvm.throwExceptionFunction,
|
||||||
|
listOf(kotlinException),
|
||||||
|
Lifetime.IRRELEVANT,
|
||||||
|
this@ExceptionHandler
|
||||||
|
)
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum class ThreadState {
|
internal enum class ThreadState {
|
||||||
@@ -790,7 +803,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
return LLVMBuildExtractElement(builder, vector, index, name)!!
|
return LLVMBuildExtractElement(builder, vector, index, name)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun filteringExceptionHandler(codeContext: CodeContext, foreignExceptionMode: ForeignExceptionMode.Mode, switchThreadState: Boolean): ExceptionHandler {
|
fun filteringExceptionHandler(
|
||||||
|
outerHandler: ExceptionHandler,
|
||||||
|
foreignExceptionMode: ForeignExceptionMode.Mode,
|
||||||
|
switchThreadState: Boolean
|
||||||
|
): ExceptionHandler {
|
||||||
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position()?.start)
|
val lpBlock = basicBlockInFunction("filteringExceptionHandler", position()?.start)
|
||||||
|
|
||||||
val wrapExceptionMode = context.config.target.family.isAppleFamily &&
|
val wrapExceptionMode = context.config.target.family.isAppleFamily &&
|
||||||
@@ -830,8 +847,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
condBr(isObjCException, forwardNativeExceptionBlock, fatalForeignExceptionBlock)
|
condBr(isObjCException, forwardNativeExceptionBlock, fatalForeignExceptionBlock)
|
||||||
|
|
||||||
appendingTo(forwardNativeExceptionBlock) {
|
appendingTo(forwardNativeExceptionBlock) {
|
||||||
val exception = createForeignException(landingpad, codeContext.exceptionHandler)
|
val exception = createForeignException(landingpad, outerHandler)
|
||||||
codeContext.genThrow(exception)
|
outerHandler.genThrow(this, exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -840,7 +857,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
appendingTo(forwardKotlinExceptionBlock) {
|
appendingTo(forwardKotlinExceptionBlock) {
|
||||||
// Rethrow Kotlin exception to real handler.
|
// Rethrow Kotlin exception to real handler.
|
||||||
codeContext.genThrow(extractKotlinException(landingpad))
|
outerHandler.genThrow(this, extractKotlinException(landingpad))
|
||||||
}
|
}
|
||||||
|
|
||||||
appendingTo(fatalForeignExceptionBlock) {
|
appendingTo(fatalForeignExceptionBlock) {
|
||||||
|
|||||||
+22
-30
@@ -106,7 +106,7 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
|||||||
/**
|
/**
|
||||||
* Defines how to generate context-dependent operations.
|
* Defines how to generate context-dependent operations.
|
||||||
*/
|
*/
|
||||||
internal interface CodeContext {
|
private interface CodeContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates `return` [value] operation.
|
* Generates `return` [value] operation.
|
||||||
@@ -121,8 +121,6 @@ internal interface CodeContext {
|
|||||||
|
|
||||||
val exceptionHandler: ExceptionHandler
|
val exceptionHandler: ExceptionHandler
|
||||||
|
|
||||||
fun genThrow(exception: LLVMValueRef)
|
|
||||||
|
|
||||||
val stackLocalsManager: StackLocalsManager
|
val stackLocalsManager: StackLocalsManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,8 +238,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
override val exceptionHandler get() = unsupported()
|
override val exceptionHandler get() = unsupported()
|
||||||
|
|
||||||
override fun genThrow(exception: LLVMValueRef) = unsupported()
|
|
||||||
|
|
||||||
override val stackLocalsManager: StackLocalsManager get() = unsupported()
|
override val stackLocalsManager: StackLocalsManager get() = unsupported()
|
||||||
|
|
||||||
override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(variable)
|
override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(variable)
|
||||||
@@ -677,16 +673,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
override val exceptionHandler: ExceptionHandler
|
override val exceptionHandler: ExceptionHandler
|
||||||
get() = ExceptionHandler.Caller
|
get() = ExceptionHandler.Caller
|
||||||
|
|
||||||
override fun genThrow(exception: LLVMValueRef) {
|
|
||||||
val objHeaderPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, exception)
|
|
||||||
val args = listOf(objHeaderPtr)
|
|
||||||
|
|
||||||
functionGenerationContext.call(
|
|
||||||
context.llvm.throwExceptionFunction, args, Lifetime.IRRELEVANT, this.exceptionHandler
|
|
||||||
)
|
|
||||||
functionGenerationContext.unreachable()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val stackLocalsManager get() = functionGenerationContext.stackLocalsManager
|
override val stackLocalsManager get() = functionGenerationContext.stackLocalsManager
|
||||||
|
|
||||||
override fun functionScope(): CodeContext = this
|
override fun functionScope(): CodeContext = this
|
||||||
@@ -942,7 +928,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
// however such optimization can lead to phi functions with zero entries, which is not allowed by LLVM;
|
// however such optimization can lead to phi functions with zero entries, which is not allowed by LLVM;
|
||||||
// TODO: find the better solution.
|
// TODO: find the better solution.
|
||||||
|
|
||||||
jump(destination, result)
|
functionGenerationContext.jump(destination, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -964,11 +950,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
/**
|
/**
|
||||||
* Jumps to [target] passing [value].
|
* Jumps to [target] passing [value].
|
||||||
*/
|
*/
|
||||||
private fun jump(target: ContinuationBlock, value: LLVMValueRef?) {
|
private fun FunctionGenerationContext.jump(target: ContinuationBlock, value: LLVMValueRef?) {
|
||||||
val entry = target.block
|
val entry = target.block
|
||||||
functionGenerationContext.br(entry)
|
br(entry)
|
||||||
if (target.valuePhi != null) {
|
if (target.valuePhi != null) {
|
||||||
functionGenerationContext.assignPhis(target.valuePhi to value!!)
|
assignPhis(target.valuePhi to value!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1020,7 +1006,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
private fun evaluateThrow(expression: IrThrow): LLVMValueRef {
|
private fun evaluateThrow(expression: IrThrow): LLVMValueRef {
|
||||||
val exception = evaluateExpression(expression.value)
|
val exception = evaluateExpression(expression.value)
|
||||||
currentCodeContext.genThrow(exception)
|
currentCodeContext.exceptionHandler.genThrow(functionGenerationContext, exception)
|
||||||
return codegen.kNothingFakeValue
|
return codegen.kNothingFakeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1063,8 +1049,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return irFunction?.endLocation
|
return irFunction?.endLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jumpToHandler(exception: LLVMValueRef) {
|
private fun FunctionGenerationContext.jumpToHandler(exception: LLVMValueRef) {
|
||||||
jump(this.handler, exception)
|
jump(handler, exception)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1092,11 +1078,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
override val exceptionHandler: ExceptionHandler
|
override val exceptionHandler: ExceptionHandler
|
||||||
get() = object : ExceptionHandler.Local() {
|
get() = object : ExceptionHandler.Local() {
|
||||||
override val unwind get() = landingpad
|
override val unwind get() = landingpad
|
||||||
}
|
|
||||||
|
|
||||||
override fun genThrow(exception: LLVMValueRef) {
|
override fun genThrow(functionGenerationContext: FunctionGenerationContext, kotlinException: LLVMValueRef) {
|
||||||
jumpToHandler(exception)
|
// Super class implementation would do too, so this is just an optimization:
|
||||||
}
|
// use local jump instead of wrapping to C++ exception, throwing, catching and unwrapping it:
|
||||||
|
functionGenerationContext.jumpToHandler(kotlinException)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract fun genHandler(exception: LLVMValueRef)
|
protected abstract fun genHandler(exception: LLVMValueRef)
|
||||||
}
|
}
|
||||||
@@ -1137,7 +1125,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// rethrow the exception if no clause can handle it.
|
// rethrow the exception if no clause can handle it.
|
||||||
outerContext.genThrow(exception)
|
outerContext.exceptionHandler.genThrow(functionGenerationContext, exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2148,11 +2136,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
using (SuspensionPointScope(expression.suspensionPointIdParameter, bbResume, id)) {
|
using (SuspensionPointScope(expression.suspensionPointIdParameter, bbResume, id)) {
|
||||||
continuationBlock(expression.type, expression.result.startLocation).run {
|
continuationBlock(expression.type, expression.result.startLocation).run {
|
||||||
val normalResult = evaluateExpression(expression.result)
|
val normalResult = evaluateExpression(expression.result)
|
||||||
jump(this, normalResult)
|
functionGenerationContext.jump(this, normalResult)
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(bbResume)
|
functionGenerationContext.positionAtEnd(bbResume)
|
||||||
val resumeResult = evaluateExpression(expression.resumeResult)
|
val resumeResult = evaluateExpression(expression.resumeResult)
|
||||||
jump(this, resumeResult)
|
functionGenerationContext.jump(this, resumeResult)
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(this.block)
|
functionGenerationContext.positionAtEnd(this.block)
|
||||||
return this.value
|
return this.value
|
||||||
@@ -2354,7 +2342,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val needsNativeThreadState = function.needsNativeThreadState
|
val needsNativeThreadState = function.needsNativeThreadState
|
||||||
val exceptionHandler = function.annotations.findAnnotation(RuntimeNames.filterExceptions)?.let {
|
val exceptionHandler = function.annotations.findAnnotation(RuntimeNames.filterExceptions)?.let {
|
||||||
val foreignExceptionMode = ForeignExceptionMode.byValue(it.getAnnotationValueOrNull<String>("mode"))
|
val foreignExceptionMode = ForeignExceptionMode.byValue(it.getAnnotationValueOrNull<String>("mode"))
|
||||||
functionGenerationContext.filteringExceptionHandler(currentCodeContext, foreignExceptionMode, needsNativeThreadState)
|
functionGenerationContext.filteringExceptionHandler(
|
||||||
|
currentCodeContext.exceptionHandler,
|
||||||
|
foreignExceptionMode,
|
||||||
|
needsNativeThreadState
|
||||||
|
)
|
||||||
} ?: currentCodeContext.exceptionHandler
|
} ?: currentCodeContext.exceptionHandler
|
||||||
|
|
||||||
if (needsNativeThreadState) {
|
if (needsNativeThreadState) {
|
||||||
|
|||||||
Reference in New Issue
Block a user