Initial support of non-local return in IR

This commit is contained in:
Mikhael Bogdanov
2019-04-04 14:40:53 +02:00
parent 3f9154a4a1
commit 694a7c329d
21 changed files with 34 additions and 31 deletions
@@ -268,7 +268,7 @@ internal fun getMarkedReturnLabelOrNull(returnInsn: AbstractInsnNode): String? {
return null return null
} }
internal fun generateGlobalReturnFlag(iv: InstructionAdapter, labelName: String) { fun generateGlobalReturnFlag(iv: InstructionAdapter, labelName: String) {
iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false) iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false)
} }
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.* import org.jetbrains.kotlin.codegen.AsmUtil.*
import org.jetbrains.kotlin.codegen.ExpressionCodegen.putReifiedOperationMarkerIfTypeIsReifiedParameter import org.jetbrains.kotlin.codegen.ExpressionCodegen.putReifiedOperationMarkerIfTypeIsReifiedParameter
import org.jetbrains.kotlin.codegen.StackValue.* import org.jetbrains.kotlin.codegen.StackValue.*
import org.jetbrains.kotlin.codegen.inline.NameGenerator import org.jetbrains.kotlin.codegen.inline.*
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.intrinsics.JavaClassProperty import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysTrueIfeq import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysTrueIfeq
@@ -674,15 +671,40 @@ class ExpressionCodegen(
} }
override fun visitReturn(expression: IrReturn, data: BlockInfo): StackValue { override fun visitReturn(expression: IrReturn, data: BlockInfo): StackValue {
val value = expression.value.apply { val owner = expression.returnTargetSymbol.owner
gen(this, returnType, data) 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() val afterReturnLabel = Label()
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data) generateFinallyBlocksIfNeeded(actualReturn, afterReturnLabel, data)
expression.markLineNumber(startOffset = true) 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.mark(afterReturnLabel)
mv.nop()/*TODO check RESTORE_STACK_IN_TRY_CATCH processor*/ mv.nop()/*TODO check RESTORE_STACK_IN_TRY_CATCH processor*/
return expression.onStack return expression.onStack
@@ -115,8 +115,7 @@ class IrExpressionLambdaImpl(
) : ExpressionLambda(typeMapper, isCrossInline), IrExpressionLambda { ) : ExpressionLambda(typeMapper, isCrossInline), IrExpressionLambda {
override fun isReturnFromMe(labelName: String): Boolean { override fun isReturnFromMe(labelName: String): Boolean {
//TODO("not implemented") return false //always false
return false
} }
override val lambdaClassType: Type = Type.getObjectType("test123") override val lambdaClassType: Type = Type.getObjectType("test123")
@@ -88,7 +88,7 @@ class IrSourceCompilerForInline(
asmMethod: Method asmMethod: Method
): SMAPAndMethodNode { ): SMAPAndMethodNode {
assert(callableDescriptor == callElement.descriptor.original) 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 if (!callDefault) irFunction
else { else {
/*TODO: get rid of hack*/ /*TODO: get rid of hack*/
@@ -160,8 +160,7 @@ class IrSourceCompilerForInline(
get() = callElement.descriptor as FunctionDescriptor get() = callElement.descriptor as FunctionDescriptor
override fun getContextLabels(): Set<String> { override fun getContextLabels(): Set<String> {
//TODO return setOf(codegen.irFunction.name.asString())
return emptySet()
} }
override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) { override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
inline fun run2(block: () -> Unit) = block() inline fun run2(block: () -> Unit) = block()
class A { class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
inline fun foo(f: () -> Unit) { inline fun foo(f: () -> Unit) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// NO_CHECK_LAMBDA_INLINING // NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt // FILE: 1.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// MODULE: lib // MODULE: lib
// FILE: lib.kt // FILE: lib.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test