Reimplemented special enum functions as intrinsics
Also fixes https://youtrack.jetbrains.com/issue/KT-33471
This commit is contained in:
+1
-8
@@ -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")
|
||||
|
||||
+5
@@ -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,
|
||||
|
||||
+13
-10
@@ -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]!!
|
||||
|
||||
@@ -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<E: Enum<E>>(public val name: String, public val ordin
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public fun <T: Enum<T>> enumValueOf(name: String): T {
|
||||
throw Exception("Call to this function should've been lowered")
|
||||
}
|
||||
/**
|
||||
* Returns an enum entry with specified name.
|
||||
*/
|
||||
public inline fun <reified T: Enum<T>> enumValueOf(name: String): T = enumValueOfIntrinsic<T>(name)
|
||||
|
||||
public fun <T: Enum<T>> enumValues(): Array<T> {
|
||||
throw Exception("Call to this function should've been lowered")
|
||||
}
|
||||
/**
|
||||
* Returns an array containing enum T entries.
|
||||
*/
|
||||
public inline fun <reified T: Enum<T>> enumValues(): Array<T> = enumValuesIntrinsic<T>()
|
||||
|
||||
@@ -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 <T : Enum<T>> enumValuesIntrinsic(): Array<T>
|
||||
|
||||
@TypedIntrinsic(IntrinsicType.ENUM_VALUE_OF)
|
||||
@PublishedApi
|
||||
internal external fun <T : Enum<T>> enumValueOfIntrinsic(name: String): T
|
||||
@@ -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"
|
||||
|
||||
@@ -117,7 +117,7 @@ public fun <T: Enum<T>> valueOfForEnum(name: String, values: Array<T>) : T {
|
||||
else -> return values[middle]
|
||||
}
|
||||
}
|
||||
throw Exception("Invalid enum name: $name")
|
||||
throw Exception("Invalid enum value name: $name")
|
||||
}
|
||||
|
||||
public fun <T: Enum<T>> valuesForEnum(values: Array<T>): Array<T> {
|
||||
|
||||
Reference in New Issue
Block a user