Removed finally blocks handling from code generator
This commit is contained in:
+11
-135
@@ -906,148 +906,24 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The [InnerScope] that includes code generated by [genFinalizeImpl] when leaving it
|
|
||||||
* with `return`, `break`, `continue` or throwing exception.
|
|
||||||
*/
|
|
||||||
private abstract inner class FinalizingScope() : CatchingScope() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache for [genReturn].
|
|
||||||
*
|
|
||||||
* `returnBlocks[func]` contains the [ContinuationBlock] to be used for `return` from `func`;
|
|
||||||
* the block expects return value as its value.
|
|
||||||
*/
|
|
||||||
private val returnBlocks = mutableMapOf<CallableDescriptor, ContinuationBlock>()
|
|
||||||
|
|
||||||
// Jump to finalize-and-return instead of simply returning.
|
|
||||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
|
||||||
val block = returnBlocks.getOrPut(target) {
|
|
||||||
continuationBlock(target.returnType!!) {
|
|
||||||
genFinalize()
|
|
||||||
val returnValue = it.valuePhi // `null` if return type is `Unit`.
|
|
||||||
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].
|
|
||||||
*
|
|
||||||
* Note: can't merge with [breakBlocks] because the code for `break` and `continue` is different.
|
|
||||||
*/
|
|
||||||
private val continueBlocks = mutableMapOf<IrLoop, LLVMBasicBlockRef>()
|
|
||||||
|
|
||||||
// Jump to finalize-and-continue instead of simply continuing.
|
|
||||||
override fun genContinue(destination: IrContinue) {
|
|
||||||
val block = continueBlocks.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) {
|
|
||||||
genFinalizeImpl()
|
|
||||||
outerContext.genThrow(exception)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun genFinalize() {
|
|
||||||
using(outerContext) {
|
|
||||||
this.genFinalizeImpl()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun genFinalizeImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the code which gets "finalized" exactly once when completed either normally or abnormally.
|
|
||||||
*
|
|
||||||
* @param code generates the code to be post-dominated by cleanup.
|
|
||||||
* It must jump to given [ContinuationBlock] with its result when completed normally.
|
|
||||||
*
|
|
||||||
* @param finalize generates the cleanup code that must be executed when code generated by [code] is completed.
|
|
||||||
*
|
|
||||||
* @param type Kotlin type of the result of generated code.
|
|
||||||
*
|
|
||||||
* @return the result of the generated code.
|
|
||||||
*/
|
|
||||||
private fun genFinalizedBy(finalize: (() -> Unit)?,
|
|
||||||
type: KotlinType, code: (ContinuationBlock) -> Unit): LLVMValueRef {
|
|
||||||
|
|
||||||
val scope = if (finalize == null) null else {
|
|
||||||
object : FinalizingScope() {
|
|
||||||
override fun genFinalizeImpl() {
|
|
||||||
finalize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val continuation = continuationBlock(type)
|
|
||||||
|
|
||||||
using(scope) {
|
|
||||||
code(continuation)
|
|
||||||
}
|
|
||||||
codegen.positionAtEnd(continuation.block)
|
|
||||||
finalize?.invoke()
|
|
||||||
|
|
||||||
// TODO: finalize is duplicated many times (just as in C++, Java or Kotlin JVM);
|
|
||||||
// it is very important to optimize this.
|
|
||||||
|
|
||||||
return continuation.value
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates code that is "finalized" by given expression.
|
|
||||||
*/
|
|
||||||
private fun genFinalizedBy(finalize: IrExpression?, type: KotlinType,
|
|
||||||
code: (ContinuationBlock) -> Unit): LLVMValueRef {
|
|
||||||
|
|
||||||
val finalizeFun: (() -> Unit)? = if (finalize == null) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
{ evaluateExpression(finalize) }
|
|
||||||
}
|
|
||||||
|
|
||||||
return genFinalizedBy(finalizeFun, type, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun evaluateTry(expression: IrTry): LLVMValueRef {
|
private fun evaluateTry(expression: IrTry): LLVMValueRef {
|
||||||
// TODO: does basic block order influence machine code order?
|
// TODO: does basic block order influence machine code order?
|
||||||
// If so, consider reordering blocks to reduce exception tables size.
|
// If so, consider reordering blocks to reduce exception tables size.
|
||||||
|
|
||||||
return genFinalizedBy(expression.finallyExpression, expression.type) { continuation ->
|
assert (expression.finallyExpression == null, { "All finally blocks should've been lowered" })
|
||||||
|
|
||||||
val catchScope = if (expression.catches.isEmpty()) null else CatchScope(expression.catches, continuation)
|
val continuation = continuationBlock(expression.type)
|
||||||
|
|
||||||
using(catchScope) {
|
val catchScope = if (expression.catches.isEmpty())
|
||||||
evaluateExpressionAndJump(expression.tryResult, continuation)
|
null
|
||||||
}
|
else
|
||||||
|
CatchScope(expression.catches, continuation)
|
||||||
|
using(catchScope) {
|
||||||
|
evaluateExpressionAndJump(expression.tryResult, continuation)
|
||||||
}
|
}
|
||||||
|
codegen.positionAtEnd(continuation.block)
|
||||||
|
|
||||||
|
return continuation.value
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|||||||
Reference in New Issue
Block a user