diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index a1953e396d1..54233dc0869 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -6,28 +6,137 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.getOrPut import org.jetbrains.kotlin.backend.common.lower.EnumWhenLowering import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.MemoryModel +import org.jetbrains.kotlin.backend.konan.NativeMapping +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.builders.declarations.buildField +import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +internal data class LoweredEnumEntryDescription(val ordinal: Int, val getterId: Int) + +internal class EnumsSupport( + mapping: NativeMapping, + symbols: KonanSymbols, + private val irBuiltIns: IrBuiltIns, + private val irFactory: IrFactory, +) { + private val enumImplObjects = mapping.enumImplObjects + private val enumValueGetters = mapping.enumValueGetters + private val enumEntriesMaps = mapping.enumEntriesMaps + private val array = symbols.array + private val genericValueOfSymbol = symbols.valueOfForEnum + private val genericValuesSymbol = symbols.valuesForEnum + + fun enumEntriesMap(enumClass: IrClass): Map { + require(enumClass.isEnumClass) { "Expected enum class but was: ${enumClass.render()}" } + return enumEntriesMaps.getOrPut(enumClass) { + data class NameWithOrdinal(val name: Name, val ordinal: Int) + enumClass.declarations.asSequence() + .filterIsInstance() + .mapIndexed { index, it -> NameWithOrdinal(it.name, index) } + .sortedBy { it.name } + .withIndex() + .associate { it.value.name to LoweredEnumEntryDescription(it.value.ordinal, it.index) } + .toMap() + } + } + + fun getImplObject(enumClass: IrClass): IrClass { + require(enumClass.isEnumClass) { "Expected enum class but was: ${enumClass.render()}" } + return enumImplObjects.getOrPut(enumClass) { + irFactory.buildClass { + startOffset = enumClass.startOffset + endOffset = enumClass.endOffset + origin = DECLARATION_ORIGIN_ENUM + name = "OBJECT".synthesizedName + kind = ClassKind.OBJECT + }.apply { + superTypes = listOf(irBuiltIns.anyType) + parent = enumClass + + addChild(irFactory.buildField { + startOffset = enumClass.startOffset + endOffset = enumClass.endOffset + origin = DECLARATION_ORIGIN_ENUM + name = "VALUES".synthesizedName + type = array.typeWith(enumClass.defaultType) + visibility = DescriptorVisibilities.PRIVATE + isFinal = true + }) + } + } + } + + fun getValueGetter(enumClass: IrClass): IrFunction { + require(enumClass.isEnumClass) { "Expected enum class but was: ${enumClass.render()}" } + return enumValueGetters.getOrPut(enumClass) { + irFactory.buildFun { + startOffset = enumClass.startOffset + endOffset = enumClass.endOffset + origin = DECLARATION_ORIGIN_ENUM + name = "getEnumAt".synthesizedName + returnType = enumClass.defaultType + }.apply { + parent = enumClass + + addValueParameter { + name = Name.identifier("getterId") + origin = DECLARATION_ORIGIN_ENUM + type = irBuiltIns.intType + } + } + } + } + + fun getValuesField(implObject: IrClass) = implObject.fields.single() + + fun IrBuilderWithScope.irGetValuesField(enumClass: IrClass): IrExpression { + val implObject = getImplObject(enumClass) + val valuesField = getValuesField(implObject) + return irGetField(irGetObject(implObject.symbol), valuesField) + } + + fun IrBuilderWithScope.irEnumValues(enumClass: IrClass) = + irCall(genericValuesSymbol, listOf(enumClass.defaultType)).apply { + putValueArgument(0, irGetValuesField(enumClass)) + } + + fun IrBuilderWithScope.irEnumValueOf(enumClass: IrClass, value: IrExpression) = + irCall(genericValueOfSymbol, listOf(enumClass.defaultType)).apply { + putValueArgument(0, value) + putValueArgument(1, irGetValuesField(enumClass)) + } +} + +internal object DECLARATION_ORIGIN_ENUM : IrDeclarationOriginImpl("ENUM") + internal class NativeEnumWhenLowering constructor(context: Context) : EnumWhenLowering(context) { override fun mapConstEnumEntry(entry: IrEnumEntry): Int { val enumEntriesMap = (context as Context).enumsSupport.enumEntriesMap(entry.parentAsClass) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumSpecialDeclarationsFactory.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumSpecialDeclarationsFactory.kt deleted file mode 100644 index 86093b64063..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumSpecialDeclarationsFactory.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.backend.konan.lower - -import org.jetbrains.kotlin.backend.common.getOrPut -import org.jetbrains.kotlin.backend.konan.NativeMapping -import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.ir.IrBuiltIns -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter -import org.jetbrains.kotlin.ir.builders.declarations.buildClass -import org.jetbrains.kotlin.ir.builders.declarations.buildField -import org.jetbrains.kotlin.ir.builders.declarations.buildFun -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.types.typeWith -import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.Name - -internal class EnumsSupport( - mapping: NativeMapping, - symbols: KonanSymbols, - private val irBuiltIns: IrBuiltIns, - private val irFactory: IrFactory, -) { - private val enumImplObjects = mapping.enumImplObjects - private val enumValueGetters = mapping.enumValueGetters - private val enumEntriesMaps = mapping.enumEntriesMaps - private val array = symbols.array - private val genericValueOfSymbol = symbols.valueOfForEnum - private val genericValuesSymbol = symbols.valuesForEnum - - fun enumEntriesMap(enumClass: IrClass): Map { - require(enumClass.isEnumClass) { "Expected enum class but was: ${enumClass.render()}" } - return enumEntriesMaps.getOrPut(enumClass) { - data class NameWithOrdinal(val name: Name, val ordinal: Int) - enumClass.declarations.asSequence() - .filterIsInstance() - .mapIndexed { index, it -> NameWithOrdinal(it.name, index) } - .sortedBy { it.name } - .withIndex() - .associate { it.value.name to LoweredEnumEntryDescription(it.value.ordinal, it.index) } - .toMap() - } - } - - fun getImplObject(enumClass: IrClass): IrClass { - require(enumClass.isEnumClass) { "Expected enum class but was: ${enumClass.render()}" } - return enumImplObjects.getOrPut(enumClass) { - irFactory.buildClass { - startOffset = enumClass.startOffset - endOffset = enumClass.endOffset - origin = DECLARATION_ORIGIN_ENUM - name = "OBJECT".synthesizedName - kind = ClassKind.OBJECT - }.apply { - superTypes = listOf(irBuiltIns.anyType) - parent = enumClass - - addChild(irFactory.buildField { - startOffset = enumClass.startOffset - endOffset = enumClass.endOffset - origin = DECLARATION_ORIGIN_ENUM - name = "VALUES".synthesizedName - type = array.typeWith(enumClass.defaultType) - visibility = DescriptorVisibilities.PRIVATE - isFinal = true - }) - } - } - } - - fun getValueGetter(enumClass: IrClass): IrFunction { - require(enumClass.isEnumClass) { "Expected enum class but was: ${enumClass.render()}" } - return enumValueGetters.getOrPut(enumClass) { - irFactory.buildFun { - startOffset = enumClass.startOffset - endOffset = enumClass.endOffset - origin = DECLARATION_ORIGIN_ENUM - name = "getEnumAt".synthesizedName - returnType = enumClass.defaultType - }.apply { - parent = enumClass - - addValueParameter { - name = Name.identifier("getterId") - origin = DECLARATION_ORIGIN_ENUM - type = irBuiltIns.intType - } - } - } - } - - fun getValuesField(implObject: IrClass) = implObject.fields.single() - - fun IrBuilderWithScope.irGetValuesField(enumClass: IrClass): IrExpression { - val implObject = getImplObject(enumClass) - val valuesField = getValuesField(implObject) - return irGetField(irGetObject(implObject.symbol), valuesField) - } - - fun IrBuilderWithScope.irEnumValues(enumClass: IrClass) = - irCall(genericValuesSymbol, listOf(enumClass.defaultType)).apply { - putValueArgument(0, irGetValuesField(enumClass)) - } - - fun IrBuilderWithScope.irEnumValueOf(enumClass: IrClass, value: IrExpression) = - irCall(genericValueOfSymbol, listOf(enumClass.defaultType)).apply { - putValueArgument(0, value) - putValueArgument(1, irGetValuesField(enumClass)) - } -} - -internal object DECLARATION_ORIGIN_ENUM : IrDeclarationOriginImpl("ENUM") - -internal data class LoweredEnumEntryDescription(val ordinal: Int, val getterId: Int)