From 694a7c329dc6272eec21bac04ca571ee9468b9a4 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 4 Apr 2019 14:40:53 +0200 Subject: [PATCH] Initial support of non-local return in IR --- .../codegen/inline/inlineCodegenUtils.kt | 2 +- .../backend/jvm/codegen/ExpressionCodegen.kt | 38 +++++++++++++++---- .../backend/jvm/codegen/IrInlineCodegen.kt | 3 +- .../jvm/codegen/IrSourceCompilerForInline.kt | 5 +-- .../withNonLocalReturn.kt | 1 - .../nonLocalReturns/deparenthesize/bracket.kt | 1 - .../nonLocalReturns/deparenthesize/labeled.kt | 1 - .../nonLocalReturns/explicitLocalReturn.kt | 1 - .../nonLocalReturns/justReturnInLambda.kt | 1 - .../boxInline/nonLocalReturns/kt5199.kt | 1 - .../nonLocalReturns/nestedNonLocals.kt | 1 - .../nonLocalReturnFromOuterLambda.kt | 1 - .../nonLocalReturns/propertyAccessors.kt | 1 - .../nonLocalReturns/returnFromFunctionExpr.kt | 1 - .../boxInline/nonLocalReturns/simple.kt | 1 - .../boxInline/nonLocalReturns/simpleVoid.kt | 1 - .../tryFinally/callSite/wrongVarInterval.kt | 1 - .../tryFinally/exceptionTable/noFinally.kt | 1 - .../nonLocalReturns/tryFinally/kt26384.kt | 1 - .../nonLocalReturnFromCatchBlock.kt | 1 - .../nonLocalReturnFromOuterLambda.kt | 1 - 21 files changed, 34 insertions(+), 31 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt index 07da7f8e1b5..e737e0fecb0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt @@ -268,7 +268,7 @@ internal fun getMarkedReturnLabelOrNull(returnInsn: AbstractInsnNode): String? { return null } -internal fun generateGlobalReturnFlag(iv: InstructionAdapter, labelName: String) { +fun generateGlobalReturnFlag(iv: InstructionAdapter, labelName: String) { iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index d9a5f2c7a3e..39741a4b075 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -16,10 +16,7 @@ import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.AsmUtil.* import org.jetbrains.kotlin.codegen.ExpressionCodegen.putReifiedOperationMarkerIfTypeIsReifiedParameter import org.jetbrains.kotlin.codegen.StackValue.* -import org.jetbrains.kotlin.codegen.inline.NameGenerator -import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner -import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages -import org.jetbrains.kotlin.codegen.inline.TypeParameterMappings +import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysTrueIfeq @@ -674,15 +671,40 @@ class ExpressionCodegen( } override fun visitReturn(expression: IrReturn, data: BlockInfo): StackValue { - val value = expression.value.apply { - gen(this, returnType, data) + val owner = expression.returnTargetSymbol.owner + val isNonLocalReturn = owner != irFunction + if (isNonLocalReturn && state.isInlineDisabled) { + //TODO: state.diagnostics.report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression)) + genThrow( + mv, "java/lang/UnsupportedOperationException", + "Non-local returns are not allowed with inlining disabled" + ) + return none() + } + + val actualReturn = + if (isNonLocalReturn) { + typeMapper.mapReturnType(owner.descriptor) + } else { + returnType + } + + expression.value.apply { + gen(this, actualReturn, data) } val afterReturnLabel = Label() - generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data) + generateFinallyBlocksIfNeeded(actualReturn, afterReturnLabel, data) expression.markLineNumber(startOffset = true) - mv.areturn(returnType) + if (isNonLocalReturn) { + val nonLocalReturnType = typeMapper.mapReturnType(owner.descriptor) + val labelName = (owner as IrFunction).name.asString() + generateGlobalReturnFlag(mv, labelName) + mv.areturn(nonLocalReturnType) + } else { + mv.areturn(actualReturn) + } mv.mark(afterReturnLabel) mv.nop()/*TODO check RESTORE_STACK_IN_TRY_CATCH processor*/ return expression.onStack diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index 82945008b26..3e5c269e4e9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -115,8 +115,7 @@ class IrExpressionLambdaImpl( ) : ExpressionLambda(typeMapper, isCrossInline), IrExpressionLambda { override fun isReturnFromMe(labelName: String): Boolean { - //TODO("not implemented") - return false + return false //always false } override val lambdaClassType: Type = Type.getObjectType("test123") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt index f0805d040f3..330bc284124 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt @@ -88,7 +88,7 @@ class IrSourceCompilerForInline( asmMethod: Method ): SMAPAndMethodNode { assert(callableDescriptor == callElement.descriptor.original) - val irFunction = ((callElement as IrCall).symbol.owner as IrFunction).let { irFunction -> + val irFunction = (callElement as IrCall).symbol.owner.let { irFunction -> if (!callDefault) irFunction else { /*TODO: get rid of hack*/ @@ -160,8 +160,7 @@ class IrSourceCompilerForInline( get() = callElement.descriptor as FunctionDescriptor override fun getContextLabels(): Set { - //TODO - return emptySet() + return setOf(codegen.irFunction.name.asString()) } override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) { diff --git a/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt b/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt index 8d335594840..4ab9a4450b1 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR inline fun run2(block: () -> Unit) = block() class A { diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt index f2d754a4409..8d3805a819a 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt index 2f91057df85..34b99e73279 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt index 2f91057df85..34b99e73279 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt index dee7a2a3d1e..200ee54cf38 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt index bcf79ad0024..d7e1c7edc17 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/nestedNonLocals.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/nestedNonLocals.kt index 8c106c41baa..97ff7ccdaeb 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/nestedNonLocals.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/nestedNonLocals.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/nonLocalReturnFromOuterLambda.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/nonLocalReturnFromOuterLambda.kt index 5868752d8df..af6f1e3d223 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/nonLocalReturnFromOuterLambda.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/nonLocalReturnFromOuterLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt index 50bdacb2465..275024ae34f 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt index 79625138945..d653a70cc5a 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt inline fun foo(f: () -> Unit) { diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt index 274b77ffb35..efe029b8d69 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt index d73fbe3069f..8cebf05330e 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/callSite/wrongVarInterval.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/callSite/wrongVarInterval.kt index 3aeabe22834..6d8641272e2 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/callSite/wrongVarInterval.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/callSite/wrongVarInterval.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/noFinally.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/noFinally.kt index 7bd001324f6..81b70d478dd 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/noFinally.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/noFinally.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt index 95261119da1..b0c09676d00 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromCatchBlock.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromCatchBlock.kt index c46314a6f41..240ec77b316 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromCatchBlock.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromCatchBlock.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // MODULE: lib // FILE: lib.kt diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromOuterLambda.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromOuterLambda.kt index 6036267b96f..90ad2de9c7c 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromOuterLambda.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromOuterLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // FILE: 1.kt package test