JVM: support enumEntries intrinsic for Kotlin enums

Implementation is very similar to the `enumValues` intrinsic.

Java enums and old (pre-1.9) Kotlin enums will be supported in a
subsequent commit.

 #KT-59710
This commit is contained in:
Alexander Udalov
2023-07-19 16:08:36 +02:00
committed by Space Team
parent c94c5a7d58
commit 874d1c514a
36 changed files with 652 additions and 4 deletions
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.codegen.MaterialValue
import org.jetbrains.kotlin.backend.jvm.codegen.materializedAt
import org.jetbrains.kotlin.backend.jvm.codegen.*
import org.jetbrains.kotlin.backend.jvm.ir.isReifiedTypeParameter
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
@@ -69,3 +66,23 @@ object EnumValues : IntrinsicMethod() {
private val ENUM_ARRAY_TYPE = AsmUtil.getArrayType(AsmTypes.ENUM_TYPE)
}
object EnumEntries : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo) = with(codegen) {
val type = expression.getTypeArgument(0)!!
if (type.isReifiedTypeParameter) {
// Note that the inliner expects exactly the following sequence of instructions.
// <REIFIED-OPERATIONS-MARKER>
// ACONST_NULL
// CHECKCAST Lkotlin/enums/EnumEntries;
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.ENUM_REIFIED)
mv.aconst(null)
mv.checkcast(AsmTypes.ENUM_ENTRIES)
MaterialValue(codegen, AsmTypes.ENUM_ENTRIES, expression.type)
} else {
// TODO: support enumEntries for Java enums.
mv.invokestatic(typeMapper.mapType(type).internalName, "getEntries", Type.getMethodDescriptor(AsmTypes.ENUM_ENTRIES), false)
MaterialValue(codegen, AsmTypes.ENUM_ENTRIES, expression.type)
}
}
}
@@ -35,6 +35,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
private val kotlinJvmFqn = FqName("kotlin.jvm")
private val kotlinJvmInternalUnsafeFqn = FqName("kotlin.jvm.internal.unsafe")
private val kotlinReflectFqn = StandardNames.KOTLIN_REFLECT_FQ_NAME
private val kotlinEnumsFqn = FqName("kotlin.enums")
private val anyFqn = StandardNames.FqNames.any.toSafe()
private val arrayFqn = StandardNames.FqNames.array.toSafe()
@@ -56,6 +57,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
Key(cloneableFqn, null, "clone", emptyList()) to Clone,
Key(kotlinFqn, null, "enumValues", listOf()) to EnumValues,
Key(kotlinFqn, null, "enumValueOf", listOf(stringFqn)) to EnumValueOf,
Key(kotlinEnumsFqn, null, "enumEntries", listOf()) to EnumEntries,
Key(kotlinFqn, stringFqn, "plus", listOf(anyFqn)) to StringPlus,
Key(kotlinReflectFqn, null, "typeOf", listOf()) to TypeOf,
irBuiltIns.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ),