backend: support break and continue from try with finally
This commit is contained in:
committed by
SvyatoslavScherbina
parent
b55b67ebe6
commit
4a1b3f2824
+47
-9
@@ -862,7 +862,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
}
|
||||
|
||||
/**
|
||||
* The [InnerScope] that includes code generated by [genFinalize] when leaving it
|
||||
* The [InnerScope] that includes code generated by [genFinalizeImpl] when leaving it
|
||||
* with `return`, `break`, `continue` or throwing exception.
|
||||
*/
|
||||
private abstract inner class FinalizingScope() : CatchingScope() {
|
||||
@@ -878,24 +878,62 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
// Jump to finalize-and-return instead of simply returning.
|
||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
||||
val block = returnBlocks.getOrPut(target) {
|
||||
using(outerContext) {
|
||||
continuationBlock(target.returnType!!) { returnValue ->
|
||||
genFinalize()
|
||||
outerContext.genReturn(target, returnValue)
|
||||
}
|
||||
continuationBlock(target.returnType!!) { returnValue ->
|
||||
genFinalize()
|
||||
outerContext.genReturn(target, returnValue)
|
||||
}
|
||||
}
|
||||
|
||||
jump(block, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache for [genBreak].
|
||||
*/
|
||||
private val breakBlocks = mutableMapOf<IrLoop, LLVMBasicBlockRef>()
|
||||
|
||||
// Jump to finalize-and-break instead of simply breaking.
|
||||
override fun genBreak(destination: IrBreak) {
|
||||
val block = breakBlocks.getOrPut(destination.loop) {
|
||||
codegen.basicBlock("finalizeAndBreak") {
|
||||
genFinalize()
|
||||
outerContext.genBreak(destination)
|
||||
}
|
||||
}
|
||||
|
||||
codegen.br(block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache for [genContinue].
|
||||
*/
|
||||
private val continueBlocks = mutableMapOf<IrLoop, LLVMBasicBlockRef>()
|
||||
|
||||
// Jump to finalize-and-continue instead of simply continuing.
|
||||
override fun genContinue(destination: IrContinue) {
|
||||
val block = breakBlocks.getOrPut(destination.loop) {
|
||||
codegen.basicBlock("finalizeAndContinue") {
|
||||
genFinalize()
|
||||
outerContext.genContinue(destination)
|
||||
}
|
||||
}
|
||||
|
||||
codegen.br(block)
|
||||
}
|
||||
|
||||
// When an exception is caught, finalize the scope and rethrow the exception.
|
||||
override fun genHandler(exception: LLVMValueRef) {
|
||||
genFinalize()
|
||||
genFinalizeImpl()
|
||||
outerContext.genThrow(exception)
|
||||
}
|
||||
|
||||
protected abstract fun genFinalize()
|
||||
private fun genFinalize() {
|
||||
using(outerContext) {
|
||||
this.genFinalizeImpl()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun genFinalizeImpl()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -915,7 +953,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
val scope = if (finalize == null) null else {
|
||||
object : FinalizingScope() {
|
||||
override fun genFinalize() {
|
||||
override fun genFinalizeImpl() {
|
||||
finalize()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +575,6 @@ task finally8(type: RunKonanTest) {
|
||||
}
|
||||
|
||||
task finally9(type: RunKonanTest) {
|
||||
disabled = true
|
||||
goldValue = "Finally 1\nFinally 2\nAfter\n"
|
||||
source = "codegen/try/finally9.kt"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user