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")
|
override val ThrowTypeCastException = internalFunction("ThrowTypeCastException")
|
||||||
|
|
||||||
val throwInvalidReceiverTypeException = internalFunction("ThrowInvalidReceiverTypeException")
|
val throwInvalidReceiverTypeException = internalFunction("ThrowInvalidReceiverTypeException")
|
||||||
|
val throwIllegalStateException = internalFunction("ThrowIllegalStateException")
|
||||||
|
|
||||||
override val ThrowUninitializedPropertyAccessException = internalFunction("ThrowUninitializedPropertyAccessException")
|
override val ThrowUninitializedPropertyAccessException = internalFunction("ThrowUninitializedPropertyAccessException")
|
||||||
|
|
||||||
@@ -303,14 +304,6 @@ internal class KonanSymbols(
|
|||||||
|
|
||||||
val valueOfForEnum = internalFunction("valueOfForEnum")
|
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 createUninitializedInstance = internalFunction("createUninitializedInstance")
|
||||||
|
|
||||||
val initInstance = internalFunction("initInstance")
|
val initInstance = internalFunction("initInstance")
|
||||||
|
|||||||
+5
@@ -63,6 +63,9 @@ internal enum class IntrinsicType {
|
|||||||
IDENTITY,
|
IDENTITY,
|
||||||
IMMUTABLE_BLOB,
|
IMMUTABLE_BLOB,
|
||||||
INIT_INSTANCE,
|
INIT_INSTANCE,
|
||||||
|
// Enums
|
||||||
|
ENUM_VALUES,
|
||||||
|
ENUM_VALUE_OF,
|
||||||
// Coroutines
|
// Coroutines
|
||||||
GET_CONTINUATION,
|
GET_CONTINUATION,
|
||||||
RETURN_IF_SUSPENDED,
|
RETURN_IF_SUSPENDED,
|
||||||
@@ -246,6 +249,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
|||||||
IntrinsicType.INTEROP_STATIC_C_FUNCTION,
|
IntrinsicType.INTEROP_STATIC_C_FUNCTION,
|
||||||
IntrinsicType.INTEROP_FUNPTR_INVOKE,
|
IntrinsicType.INTEROP_FUNPTR_INVOKE,
|
||||||
IntrinsicType.INTEROP_CONVERT,
|
IntrinsicType.INTEROP_CONVERT,
|
||||||
|
IntrinsicType.ENUM_VALUES,
|
||||||
|
IntrinsicType.ENUM_VALUE_OF,
|
||||||
IntrinsicType.WORKER_EXECUTE ->
|
IntrinsicType.WORKER_EXECUTE ->
|
||||||
reportNonLoweredIntrinsic(intrinsicType)
|
reportNonLoweredIntrinsic(intrinsicType)
|
||||||
IntrinsicType.INIT_INSTANCE,
|
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.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -95,30 +97,31 @@ internal class EnumUsageLowering(val context: Context)
|
|||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
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
|
return expression
|
||||||
|
|
||||||
|
val startOffset = expression.startOffset
|
||||||
|
val endOffset = expression.endOffset
|
||||||
val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol
|
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
|
val irClass = irClassSymbol.owner
|
||||||
|
|
||||||
assert (irClass.kind == ClassKind.ENUM_CLASS)
|
assert (irClass.kind == ClassKind.ENUM_CLASS)
|
||||||
|
|
||||||
return if (expression.symbol == enumValuesSymbol) {
|
return if (intrinsicType == IntrinsicType.ENUM_VALUES) {
|
||||||
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass)
|
enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass)
|
||||||
} else {
|
} else {
|
||||||
val value = expression.getValueArgument(0)!!
|
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 {
|
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression {
|
||||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||||
val ordinal = loweredEnum.entriesMap[name]!!
|
val ordinal = loweredEnum.entriesMap[name]!!
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
package kotlin
|
package kotlin
|
||||||
|
|
||||||
|
import kotlin.native.internal.enumValueOfIntrinsic
|
||||||
|
import kotlin.native.internal.enumValuesIntrinsic
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The common base class of all enum classes.
|
* The common base class of all enum classes.
|
||||||
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/enum-classes.html) for more
|
* 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 {
|
* Returns an enum entry with specified name.
|
||||||
throw Exception("Call to this function should've been lowered")
|
*/
|
||||||
}
|
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 IMMUTABLE_BLOB = "IMMUTABLE_BLOB"
|
||||||
const val INIT_INSTANCE = "INIT_INSTANCE"
|
const val INIT_INSTANCE = "INIT_INSTANCE"
|
||||||
|
|
||||||
|
// Enums
|
||||||
|
const val ENUM_VALUES = "ENUM_VALUES"
|
||||||
|
const val ENUM_VALUE_OF = "ENUM_VALUE_OF"
|
||||||
|
|
||||||
// Coroutines
|
// Coroutines
|
||||||
const val GET_CONTINUATION = "GET_CONTINUATION"
|
const val GET_CONTINUATION = "GET_CONTINUATION"
|
||||||
const val RETURN_IF_SUSPENDED = "RETURN_IF_SUSPENDED"
|
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]
|
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> {
|
public fun <T: Enum<T>> valuesForEnum(values: Array<T>): Array<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user