From b1453a4ebaee8ff258bdf4fc3f68501eb91a1963 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Fri, 23 Aug 2019 18:58:33 +0300 Subject: [PATCH] Reimplemented special enum functions as intrinsics Also fixes https://youtrack.jetbrains.com/issue/KT-33471 --- .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 9 +------- .../backend/konan/llvm/IntrinsicGenerator.kt | 5 ++++ .../backend/konan/lower/EnumClassLowering.kt | 23 +++++++++++-------- runtime/src/main/kotlin/kotlin/Enum.kt | 18 +++++++++------ .../kotlin/kotlin/native/internal/Enums.kt | 14 +++++++++++ .../kotlin/native/internal/IntrinsicType.kt | 4 ++++ .../kotlin/native/internal/RuntimeUtils.kt | 2 +- 7 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 runtime/src/main/kotlin/kotlin/native/internal/Enums.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 1d664c73cce..06c092f00e6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -226,6 +226,7 @@ internal class KonanSymbols( override val ThrowTypeCastException = internalFunction("ThrowTypeCastException") val throwInvalidReceiverTypeException = internalFunction("ThrowInvalidReceiverTypeException") + val throwIllegalStateException = internalFunction("ThrowIllegalStateException") override val ThrowUninitializedPropertyAccessException = internalFunction("ThrowUninitializedPropertyAccessException") @@ -303,14 +304,6 @@ internal class KonanSymbols( val valueOfForEnum = internalFunction("valueOfForEnum") - val enumValues = symbolTable.referenceSimpleFunction( - builtInsPackage("kotlin").getContributedFunctions( - Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single()) - - val enumValueOf = symbolTable.referenceSimpleFunction( - builtInsPackage("kotlin").getContributedFunctions( - Name.identifier("enumValueOf"), NoLookupLocation.FROM_BACKEND).single()) - val createUninitializedInstance = internalFunction("createUninitializedInstance") val initInstance = internalFunction("initInstance") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index 873a82ec6fb..b6b1e2a0437 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -63,6 +63,9 @@ internal enum class IntrinsicType { IDENTITY, IMMUTABLE_BLOB, INIT_INSTANCE, + // Enums + ENUM_VALUES, + ENUM_VALUE_OF, // Coroutines GET_CONTINUATION, RETURN_IF_SUSPENDED, @@ -246,6 +249,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv IntrinsicType.INTEROP_STATIC_C_FUNCTION, IntrinsicType.INTEROP_FUNPTR_INVOKE, IntrinsicType.INTEROP_CONVERT, + IntrinsicType.ENUM_VALUES, + IntrinsicType.ENUM_VALUE_OF, IntrinsicType.WORKER_EXECUTE -> reportNonLoweredIntrinsic(intrinsicType) IntrinsicType.INIT_INSTANCE, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index e4679f59cf0..34507334a0e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -13,6 +13,8 @@ import org.jetbrains.kotlin.backend.common.lower.EnumWhenLowering import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* @@ -95,30 +97,31 @@ internal class EnumUsageLowering(val context: Context) override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) - if (expression.symbol != enumValuesSymbol && expression.symbol != enumValueOfSymbol) + val intrinsicType = tryGetIntrinsicType(expression) + if (intrinsicType != IntrinsicType.ENUM_VALUES && intrinsicType != IntrinsicType.ENUM_VALUE_OF) return expression + val startOffset = expression.startOffset + val endOffset = expression.endOffset val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol - ?: return expression // Type parameter. - if (irClassSymbol == context.ir.symbols.enum) return expression // Type parameter erased to 'Enum'. + if (irClassSymbol == null || irClassSymbol == context.ir.symbols.enum) { + // Either a type parameter or a type parameter erased to 'Enum'. + return irCall(startOffset, endOffset, context.ir.symbols.throwIllegalStateException.owner, emptyList()) + } val irClass = irClassSymbol.owner assert (irClass.kind == ClassKind.ENUM_CLASS) - return if (expression.symbol == enumValuesSymbol) { - enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass) + return if (intrinsicType == IntrinsicType.ENUM_VALUES) { + enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass) } else { val value = expression.getValueArgument(0)!! - enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, irClass, value) + enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value) } } - private val enumValueOfSymbol = context.ir.symbols.enumValueOf - - private val enumValuesSymbol = context.ir.symbols.enumValues - private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression { val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) val ordinal = loweredEnum.entriesMap[name]!! diff --git a/runtime/src/main/kotlin/kotlin/Enum.kt b/runtime/src/main/kotlin/kotlin/Enum.kt index cbb976699c6..406e525e89b 100644 --- a/runtime/src/main/kotlin/kotlin/Enum.kt +++ b/runtime/src/main/kotlin/kotlin/Enum.kt @@ -5,6 +5,9 @@ package kotlin +import kotlin.native.internal.enumValueOfIntrinsic +import kotlin.native.internal.enumValuesIntrinsic + /** * The common base class of all enum classes. * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/enum-classes.html) for more @@ -30,11 +33,12 @@ public abstract class Enum>(public val name: String, public val ordin } } -@Suppress("UNUSED_PARAMETER") -public fun > enumValueOf(name: String): T { - throw Exception("Call to this function should've been lowered") -} +/** + * Returns an enum entry with specified name. + */ +public inline fun > enumValueOf(name: String): T = enumValueOfIntrinsic(name) -public fun > enumValues(): Array { - throw Exception("Call to this function should've been lowered") -} +/** + * Returns an array containing enum T entries. + */ +public inline fun > enumValues(): Array = enumValuesIntrinsic() diff --git a/runtime/src/main/kotlin/kotlin/native/internal/Enums.kt b/runtime/src/main/kotlin/kotlin/native/internal/Enums.kt new file mode 100644 index 00000000000..050b312a2e3 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/native/internal/Enums.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +@TypedIntrinsic(IntrinsicType.ENUM_VALUES) +@PublishedApi +internal external fun > enumValuesIntrinsic(): Array + +@TypedIntrinsic(IntrinsicType.ENUM_VALUE_OF) +@PublishedApi +internal external fun > enumValueOfIntrinsic(name: String): T diff --git a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt index 6a283a8a7f6..5f4ef01757c 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt @@ -54,6 +54,10 @@ class IntrinsicType { const val IMMUTABLE_BLOB = "IMMUTABLE_BLOB" const val INIT_INSTANCE = "INIT_INSTANCE" + // Enums + const val ENUM_VALUES = "ENUM_VALUES" + const val ENUM_VALUE_OF = "ENUM_VALUE_OF" + // Coroutines const val GET_CONTINUATION = "GET_CONTINUATION" const val RETURN_IF_SUSPENDED = "RETURN_IF_SUSPENDED" diff --git a/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt b/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt index 89a2f038fb6..fd5df9706be 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt @@ -117,7 +117,7 @@ public fun > valueOfForEnum(name: String, values: Array) : T { else -> return values[middle] } } - throw Exception("Invalid enum name: $name") + throw Exception("Invalid enum value name: $name") } public fun > valuesForEnum(values: Array): Array {