Fixed bug: finally blocks are not always inside IrFunction
For instance: package level field initializers.
This commit is contained in:
+1
-1
@@ -82,7 +82,7 @@ internal class KonanLower(val context: Context) {
|
|||||||
TailrecLowering(context).runOnFilePostfix(irFile)
|
TailrecLowering(context).runOnFilePostfix(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_FINALLY) {
|
phaser.phase(KonanPhase.LOWER_FINALLY) {
|
||||||
FinallyBlocksLowering(context).runOnFilePostfix(irFile)
|
FinallyBlocksLowering(context).lower(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_DEFAULT_PARAMETER_EXTENT) {
|
phaser.phase(KonanPhase.LOWER_DEFAULT_PARAMETER_EXTENT) {
|
||||||
DefaultArgumentStubGenerator(context).runOnFilePostfix(irFile)
|
DefaultArgumentStubGenerator(context).runOnFilePostfix(irFile)
|
||||||
|
|||||||
+193
-197
@@ -1,6 +1,5 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
@@ -12,22 +11,23 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass {
|
internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
private interface HighLevelJump {
|
private interface HighLevelJump {
|
||||||
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
||||||
@@ -79,204 +79,200 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lower(irFunction: IrFunction) {
|
override fun lower(irFile: IrFile) {
|
||||||
val functionDescriptor = irFunction.descriptor
|
irFile.transformChildrenVoid(this)
|
||||||
using(ReturnableScope(functionDescriptor)) {
|
}
|
||||||
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
|
|
||||||
|
|
||||||
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
override fun visitFunctionNew(declaration: IrFunction): IrStatement {
|
||||||
if (expression !is IrReturnableBlockImpl)
|
using(ReturnableScope(declaration.descriptor)) {
|
||||||
return super.visitContainerExpression(expression)
|
return super.visitFunctionNew(declaration)
|
||||||
|
|
||||||
using(ReturnableScope(expression.descriptor)) {
|
|
||||||
return super.visitContainerExpression(expression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitLoop(loop: IrLoop): IrExpression {
|
|
||||||
using(LoopScope(loop)) {
|
|
||||||
return super.visitLoop(loop)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitBreak(jump: IrBreak): IrExpression {
|
|
||||||
val startOffset = jump.startOffset
|
|
||||||
val endOffset = jump.endOffset
|
|
||||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
|
||||||
return performHighLevelJump(
|
|
||||||
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
|
||||||
jump = Break(jump.loop),
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
|
||||||
) ?: jump
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitContinue(jump: IrContinue): IrExpression {
|
|
||||||
val startOffset = jump.startOffset
|
|
||||||
val endOffset = jump.endOffset
|
|
||||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
|
||||||
return performHighLevelJump(
|
|
||||||
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
|
||||||
jump = Continue(jump.loop),
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
|
||||||
) ?: jump
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
|
|
||||||
return performHighLevelJump(
|
|
||||||
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
|
|
||||||
jump = Return(expression.returnTargetSymbol),
|
|
||||||
startOffset = expression.startOffset,
|
|
||||||
endOffset = expression.endOffset,
|
|
||||||
value = expression.value
|
|
||||||
) ?: expression
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun performHighLevelJump(targetScopePredicate: (Scope) -> Boolean,
|
|
||||||
jump: HighLevelJump,
|
|
||||||
startOffset: Int,
|
|
||||||
endOffset: Int,
|
|
||||||
value: IrExpression): IrExpression? {
|
|
||||||
val tryScopes = scopeStack.reversed()
|
|
||||||
.takeWhile { !targetScopePredicate(it) }
|
|
||||||
.filterIsInstance<TryScope>()
|
|
||||||
.toList()
|
|
||||||
if (tryScopes.isEmpty())
|
|
||||||
return null
|
|
||||||
return performHighLevelJump(tryScopes, 0, jump, startOffset, endOffset, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun performHighLevelJump(tryScopes: List<TryScope>,
|
|
||||||
index: Int,
|
|
||||||
jump: HighLevelJump,
|
|
||||||
startOffset: Int,
|
|
||||||
endOffset: Int,
|
|
||||||
value: IrExpression): IrExpression {
|
|
||||||
if (index == tryScopes.size)
|
|
||||||
return jump.toIr(context, startOffset, endOffset, value)
|
|
||||||
|
|
||||||
val currentTryScope = tryScopes[index]
|
|
||||||
currentTryScope.jumps.getOrPut(jump) {
|
|
||||||
val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type)
|
|
||||||
with(currentTryScope) {
|
|
||||||
irBuilder.run {
|
|
||||||
val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression)
|
|
||||||
expression = performHighLevelJump(
|
|
||||||
tryScopes = tryScopes,
|
|
||||||
index = index + 1,
|
|
||||||
jump = jump,
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
value = inlinedFinally)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
symbol
|
|
||||||
}.let {
|
|
||||||
return IrReturnImpl(
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
returnTargetSymbol = it,
|
|
||||||
value = value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTry(aTry: IrTry): IrExpression {
|
|
||||||
val finallyExpression = aTry.finallyExpression
|
|
||||||
if (finallyExpression == null)
|
|
||||||
return super.visitTry(aTry)
|
|
||||||
|
|
||||||
val startOffset = aTry.startOffset
|
|
||||||
val endOffset = aTry.endOffset
|
|
||||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
|
||||||
val transformer = this
|
|
||||||
irBuilder.run {
|
|
||||||
val transformedTry = IrTryImpl(
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
type = context.builtIns.nothingType
|
|
||||||
)
|
|
||||||
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
|
|
||||||
val parameter = IrTemporaryVariableDescriptorImpl(
|
|
||||||
containingDeclaration = irFunction.descriptor,
|
|
||||||
name = Name.identifier("t"),
|
|
||||||
outType = context.builtIns.throwable.defaultType
|
|
||||||
)
|
|
||||||
val catchParameter = IrVariableImpl(
|
|
||||||
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter)
|
|
||||||
|
|
||||||
val syntheticTry = IrTryImpl(
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
type = context.builtIns.nothingType,
|
|
||||||
tryResult = transformedTry,
|
|
||||||
catches = listOf(
|
|
||||||
irCatch(catchParameter).apply {
|
|
||||||
result = irBlock {
|
|
||||||
+finallyExpression.copy()
|
|
||||||
+irThrow(irGet(catchParameter.symbol))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
finallyExpression = null
|
|
||||||
)
|
|
||||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
|
||||||
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type)
|
|
||||||
val transformedResult = aTry.tryResult.transform(transformer, null)
|
|
||||||
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
|
||||||
for (aCatch in aTry.catches) {
|
|
||||||
val transformedCatch = aCatch.transform(transformer, null)
|
|
||||||
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
|
||||||
transformedTry.catches.add(transformedCatch)
|
|
||||||
}
|
|
||||||
return irInlineFinally(fallThroughSymbol, it.expression, it.finallyExpression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol,
|
|
||||||
value: IrExpression,
|
|
||||||
finallyExpression: IrExpression): IrExpression {
|
|
||||||
val returnType = symbol.descriptor.returnType!!
|
|
||||||
return when {
|
|
||||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
|
||||||
+irReturnableBlock(symbol) {
|
|
||||||
+value
|
|
||||||
}
|
|
||||||
+finallyExpression.copy()
|
|
||||||
}
|
|
||||||
else -> irBlock(value, null, returnType) {
|
|
||||||
val tmp = irTemporary(irReturnableBlock(symbol) {
|
|
||||||
+irReturn(symbol, value)
|
|
||||||
})
|
|
||||||
+finallyExpression.copy()
|
|
||||||
+irGet(tmp.symbol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType): FunctionDescriptor {
|
|
||||||
return SimpleFunctionDescriptorImpl.create(
|
|
||||||
functionDescriptor,
|
|
||||||
Annotations.EMPTY,
|
|
||||||
name.synthesizedName,
|
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
|
||||||
SourceElement.NO_SOURCE).apply {
|
|
||||||
initialize(null, null, emptyList(), emptyList(), returnType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol =
|
|
||||||
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType))
|
|
||||||
|
|
||||||
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
||||||
|
if (expression !is IrReturnableBlockImpl)
|
||||||
|
return super.visitContainerExpression(expression)
|
||||||
|
|
||||||
|
using(ReturnableScope(expression.descriptor)) {
|
||||||
|
return super.visitContainerExpression(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLoop(loop: IrLoop): IrExpression {
|
||||||
|
using(LoopScope(loop)) {
|
||||||
|
return super.visitLoop(loop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitBreak(jump: IrBreak): IrExpression {
|
||||||
|
val startOffset = jump.startOffset
|
||||||
|
val endOffset = jump.endOffset
|
||||||
|
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||||
|
return performHighLevelJump(
|
||||||
|
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
||||||
|
jump = Break(jump.loop),
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
||||||
|
) ?: jump
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitContinue(jump: IrContinue): IrExpression {
|
||||||
|
val startOffset = jump.startOffset
|
||||||
|
val endOffset = jump.endOffset
|
||||||
|
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||||
|
return performHighLevelJump(
|
||||||
|
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
||||||
|
jump = Continue(jump.loop),
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
||||||
|
) ?: jump
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
return performHighLevelJump(
|
||||||
|
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
|
||||||
|
jump = Return(expression.returnTargetSymbol),
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
value = expression.value
|
||||||
|
) ?: expression
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performHighLevelJump(targetScopePredicate: (Scope) -> Boolean,
|
||||||
|
jump: HighLevelJump,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
value: IrExpression): IrExpression? {
|
||||||
|
val tryScopes = scopeStack.reversed()
|
||||||
|
.takeWhile { !targetScopePredicate(it) }
|
||||||
|
.filterIsInstance<TryScope>()
|
||||||
|
.toList()
|
||||||
|
if (tryScopes.isEmpty())
|
||||||
|
return null
|
||||||
|
return performHighLevelJump(tryScopes, 0, jump, startOffset, endOffset, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performHighLevelJump(tryScopes: List<TryScope>,
|
||||||
|
index: Int,
|
||||||
|
jump: HighLevelJump,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
value: IrExpression): IrExpression {
|
||||||
|
if (index == tryScopes.size)
|
||||||
|
return jump.toIr(context, startOffset, endOffset, value)
|
||||||
|
|
||||||
|
val currentTryScope = tryScopes[index]
|
||||||
|
currentTryScope.jumps.getOrPut(jump) {
|
||||||
|
val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type)
|
||||||
|
with(currentTryScope) {
|
||||||
|
irBuilder.run {
|
||||||
|
val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression)
|
||||||
|
expression = performHighLevelJump(
|
||||||
|
tryScopes = tryScopes,
|
||||||
|
index = index + 1,
|
||||||
|
jump = jump,
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
value = inlinedFinally)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
symbol
|
||||||
|
}.let {
|
||||||
|
return IrReturnImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
returnTargetSymbol = it,
|
||||||
|
value = value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTry(aTry: IrTry): IrExpression {
|
||||||
|
val finallyExpression = aTry.finallyExpression
|
||||||
|
?: return super.visitTry(aTry)
|
||||||
|
|
||||||
|
val startOffset = aTry.startOffset
|
||||||
|
val endOffset = aTry.endOffset
|
||||||
|
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||||
|
val transformer = this
|
||||||
|
irBuilder.run {
|
||||||
|
val transformedTry = IrTryImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
type = context.builtIns.nothingType
|
||||||
|
)
|
||||||
|
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
|
||||||
|
val parameter = IrTemporaryVariableDescriptorImpl(
|
||||||
|
containingDeclaration = currentScope!!.scope.scopeOwner,
|
||||||
|
name = Name.identifier("t"),
|
||||||
|
outType = context.builtIns.throwable.defaultType
|
||||||
|
)
|
||||||
|
val catchParameter = IrVariableImpl(
|
||||||
|
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter)
|
||||||
|
|
||||||
|
val syntheticTry = IrTryImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
type = context.builtIns.nothingType,
|
||||||
|
tryResult = transformedTry,
|
||||||
|
catches = listOf(
|
||||||
|
irCatch(catchParameter).apply {
|
||||||
|
result = irBlock {
|
||||||
|
+finallyExpression.copy()
|
||||||
|
+irThrow(irGet(catchParameter.symbol))
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
finallyExpression = null
|
||||||
|
)
|
||||||
|
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||||
|
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type)
|
||||||
|
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||||
|
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||||
|
for (aCatch in aTry.catches) {
|
||||||
|
val transformedCatch = aCatch.transform(transformer, null)
|
||||||
|
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
||||||
|
transformedTry.catches.add(transformedCatch)
|
||||||
|
}
|
||||||
|
return irInlineFinally(fallThroughSymbol, it.expression, it.finallyExpression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol,
|
||||||
|
value: IrExpression,
|
||||||
|
finallyExpression: IrExpression): IrExpression {
|
||||||
|
val returnType = symbol.descriptor.returnType!!
|
||||||
|
return when {
|
||||||
|
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
||||||
|
+irReturnableBlock(symbol) {
|
||||||
|
+value
|
||||||
|
}
|
||||||
|
+finallyExpression.copy()
|
||||||
|
}
|
||||||
|
else -> irBlock(value, null, returnType) {
|
||||||
|
val tmp = irTemporary(irReturnableBlock(symbol) {
|
||||||
|
+irReturn(symbol, value)
|
||||||
|
})
|
||||||
|
+finallyExpression.copy()
|
||||||
|
+irGet(tmp.symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType) =
|
||||||
|
SimpleFunctionDescriptorImpl.create(currentScope!!.scope.scopeOwner, Annotations.EMPTY, name.synthesizedName,
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE).apply {
|
||||||
|
initialize(null, null, emptyList(), emptyList(), returnType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol =
|
||||||
|
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType))
|
||||||
|
|
||||||
|
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
||||||
|
|
||||||
fun IrBuilderWithScope.irReturn(target: IrFunctionSymbol, value: IrExpression) =
|
fun IrBuilderWithScope.irReturn(target: IrFunctionSymbol, value: IrExpression) =
|
||||||
IrReturnImpl(startOffset, endOffset, target, value)
|
IrReturnImpl(startOffset, endOffset, target, value)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user