JVM: support enumEntries intrinsic for Java & old Kotlin enums

#KT-59710 Fixed
This commit is contained in:
Alexander Udalov
2023-07-20 00:52:22 +02:00
committed by Space Team
parent 874d1c514a
commit 971b4e63e7
25 changed files with 389 additions and 54 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.Type.INT_TYPE
import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
class PsiInlineIntrinsicsSupport(
override val state: GenerationState,
@@ -72,6 +73,10 @@ class PsiInlineIntrinsicsSupport(
override fun toKotlinType(type: KotlinType): KotlinType = type
override fun generateExternalEntriesForEnumTypeIfNeeded(type: KotlinType): FieldInsnNode? {
error("Not supported in the old JVM backend")
}
override fun reportSuspendTypeUnsupported() {
state.diagnostics.report(TYPEOF_SUSPEND_TYPE.on(reportErrorsOn))
}
@@ -66,6 +66,8 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
fun toKotlinType(type: KT): KotlinType
fun generateExternalEntriesForEnumTypeIfNeeded(type: KT): FieldInsnNode?
fun reportSuspendTypeUnsupported()
fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name)
@@ -187,7 +189,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
OperationKind.SAFE_AS -> processAs(insn, instructions, type, asmType, safe = true)
OperationKind.IS -> processIs(insn, instructions, type, asmType)
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType)
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, type, asmType)
OperationKind.TYPE_OF -> processTypeOf(insn, instructions, type)
}
@@ -342,7 +344,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
return true
}
private fun processSpecialEnumFunction(insn: MethodInsnNode, instructions: InsnList, parameter: Type): Boolean {
private fun processSpecialEnumFunction(insn: MethodInsnNode, instructions: InsnList, type: KT, parameter: Type): Boolean {
val next1 = insn.next ?: return false
val next2 = next1.next ?: return false
if (next1.opcode == Opcodes.ACONST_NULL && next2.opcode == Opcodes.ALOAD) {
@@ -362,12 +364,17 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
} else if (next1.opcode == Opcodes.ACONST_NULL && next2.opcode == Opcodes.CHECKCAST) {
instructions.remove(next1)
instructions.remove(next2)
// TODO: support enumEntries for Java enums.
instructions.insert(
insn, MethodInsnNode(
Opcodes.INVOKESTATIC, parameter.internalName, "getEntries", Type.getMethodDescriptor(AsmTypes.ENUM_ENTRIES), false
val getField = intrinsicsSupport.generateExternalEntriesForEnumTypeIfNeeded(type)
if (getField != null) {
instructions.insert(insn, getField)
} else {
instructions.insert(
insn, MethodInsnNode(
Opcodes.INVOKESTATIC, parameter.internalName, "getEntries", Type.getMethodDescriptor(AsmTypes.ENUM_ENTRIES), false
)
)
)
}
return true
}