Reimplemented special enum functions as intrinsics

Also fixes https://youtrack.jetbrains.com/issue/KT-33471
This commit is contained in:
Igor Chevdar
2019-08-23 18:58:33 +03:00
parent 04f3aae72b
commit b1453a4eba
7 changed files with 49 additions and 26 deletions
@@ -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")
@@ -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,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]!!
+11 -7
View File
@@ -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> {