backend: support break and continue from try with finally

This commit is contained in:
Svyatoslav Scherbina
2016-12-05 13:19:23 +07:00
committed by SvyatoslavScherbina
parent b55b67ebe6
commit 4a1b3f2824
2 changed files with 47 additions and 10 deletions
@@ -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()
}
}
-1
View File
@@ -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"
}