Split up EnumClassLowering on two parts
EnumConstructorsLowering will be moved to common part Also moved EnumClassLowering down along the pipeline
This commit is contained in:
+5
-2
@@ -83,8 +83,8 @@ internal class KonanLower(val context: Context, val parentPhaser: PhaseManager)
|
||||
phaser.phase(KonanPhase.LOWER_FOR_LOOPS) {
|
||||
ForLoopsLowering(context).lower(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||
EnumClassLowering(context).run(irFile)
|
||||
phaser.phase(KonanPhase.LOWER_ENUM_CONSTRUCTORS) {
|
||||
EnumConstructorsLowering(context).run(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
||||
InitializersLowering(context).runOnFilePostfix(irFile)
|
||||
@@ -117,6 +117,9 @@ internal class KonanLower(val context: Context, val parentPhaser: PhaseManager)
|
||||
phaser.phase(KonanPhase.LOWER_INNER_CLASSES) {
|
||||
InnerClassLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||
EnumClassLowering(context).run(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INTEROP_PART2) {
|
||||
InteropLoweringPart2(context).lower(irFile)
|
||||
}
|
||||
|
||||
+4
-3
@@ -29,9 +29,10 @@ enum class KonanPhase(val description: String,
|
||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
||||
/* ... ... */ LOWER_FOR_LOOPS("For loops lowering"),
|
||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||
/* ... ... */ LOWER_ENUM_CONSTRUCTORS("Enum constructors lowering"),
|
||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering", LOWER_ENUM_CONSTRUCTORS),
|
||||
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUM_CONSTRUCTORS),
|
||||
/* ... ... */ LOWER_LATEINIT("Lateinit properties lowering", LOWER_INLINE),
|
||||
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_DELEGATION),
|
||||
@@ -39,7 +40,7 @@ enum class KonanPhase(val description: String,
|
||||
/* ... ... */ LOWER_INTEROP_PART2("Interop lowering, part 2", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
|
||||
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUMS),
|
||||
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUM_CONSTRUCTORS),
|
||||
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES, LOWER_DEFAULT_PARAMETER_EXTENT),
|
||||
/* ... ... */ LOWER_COMPILE_TIME_EVAL("Compile time evaluation lowering", LOWER_VARARG, enabled = false),
|
||||
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT, GEN_SYNTHETIC_FIELDS),
|
||||
|
||||
-1
@@ -100,7 +100,6 @@ internal val IrClass.isInterface: Boolean
|
||||
get() = (this.kind == ClassKind.INTERFACE)
|
||||
|
||||
fun IrClass.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT
|
||||
|| this.kind == ClassKind.ENUM_CLASS
|
||||
|
||||
internal fun IrFunction.hasValueTypeAt(index: Int): Boolean {
|
||||
when (index) {
|
||||
|
||||
-1
@@ -134,7 +134,6 @@ internal val MemberScope.contributedMethods: List<FunctionDescriptor>
|
||||
}
|
||||
|
||||
fun ClassDescriptor.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT
|
||||
|| this.kind == ClassKind.ENUM_CLASS
|
||||
|
||||
internal val FunctionDescriptor.target: FunctionDescriptor
|
||||
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ val IrFunction.isOverridableOrOverrides
|
||||
get() = this is IrSimpleFunction && (this.isOverridable || this.overriddenSymbols.isNotEmpty())
|
||||
|
||||
val IrClass.isFinalClass: Boolean
|
||||
get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
|
||||
get() = modality == Modality.FINAL
|
||||
|
||||
fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
|
||||
if (this == other) return true
|
||||
|
||||
+51
-459
@@ -7,21 +7,13 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
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.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
@@ -29,17 +21,10 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
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.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
||||
@@ -163,111 +148,25 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
EnumClassTransformer(irClass).run()
|
||||
}
|
||||
|
||||
private interface EnumConstructorCallTransformer {
|
||||
fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression
|
||||
fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression
|
||||
}
|
||||
|
||||
private inner class EnumClassTransformer(val irClass: IrClass) {
|
||||
private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass)
|
||||
private val loweredEnumConstructors = mutableMapOf<IrConstructor, IrConstructor>()
|
||||
private val defaultEnumEntryConstructors = mutableMapOf<IrConstructor, IrConstructor>()
|
||||
private val loweredEnumConstructorParameters = mutableMapOf<IrValueParameter, IrValueParameter>()
|
||||
private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context)
|
||||
|
||||
fun run() {
|
||||
insertInstanceInitializerCall()
|
||||
lowerEnumConstructors(irClass)
|
||||
lowerEnumEntriesClasses()
|
||||
val defaultClass = createDefaultClassForEnumEntries()
|
||||
lowerEnumClassBody(defaultClass)
|
||||
pullUpEnumEntriesClasses()
|
||||
createImplObject()
|
||||
}
|
||||
|
||||
private fun insertInstanceInitializerCall() {
|
||||
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
// Skip nested
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
val blockBody = declaration.body as? IrBlockBody
|
||||
?: throw AssertionError("Unexpected constructor body: ${declaration.body}")
|
||||
if (blockBody.statements.all { it !is IrInstanceInitializerCall }) {
|
||||
blockBody.statements.transformFlat {
|
||||
if (it is IrEnumConstructorCall)
|
||||
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
|
||||
irClass.symbol, context.irBuiltIns.unitType))
|
||||
else null
|
||||
}
|
||||
}
|
||||
return declaration
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun lowerEnumEntriesClasses() {
|
||||
private fun pullUpEnumEntriesClasses() {
|
||||
irClass.declarations.transformFlat { declaration ->
|
||||
if (declaration is IrEnumEntry) {
|
||||
listOfNotNull(declaration, lowerEnumEntryClass(declaration.correspondingClass))
|
||||
val correspondingClass = declaration.correspondingClass
|
||||
declaration.correspondingClass = null
|
||||
listOfNotNull(declaration, correspondingClass)
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerEnumEntryClass(enumEntryClass: IrClass?): IrClass? {
|
||||
if (enumEntryClass == null) return null
|
||||
|
||||
lowerEnumConstructors(enumEntryClass)
|
||||
|
||||
return enumEntryClass
|
||||
}
|
||||
|
||||
private fun createDefaultClassForEnumEntries(): IrClass? {
|
||||
if (!irClass.declarations.any { it is IrEnumEntry && it.correspondingClass == null }) return null
|
||||
val defaultClass = WrappedClassDescriptor().let {
|
||||
IrClassImpl(
|
||||
irClass.startOffset, irClass.endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrClassSymbolImpl(it),
|
||||
"DEFAULT".synthesizedName,
|
||||
ClassKind.CLASS,
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isExternal = false,
|
||||
isInline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = irClass
|
||||
irClass.declarations += this
|
||||
createParameterDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
for (superConstructor in irClass.constructors) {
|
||||
val constructor = defaultClass.addSimpleDelegatingConstructor(superConstructor, context.irBuiltIns)
|
||||
defaultEnumEntryConstructors[superConstructor] = constructor
|
||||
|
||||
for (parameter in constructor.valueParameters) {
|
||||
val defaultValue = superConstructor.valueParameters[parameter.index].defaultValue ?: continue
|
||||
val body = defaultValue.deepCopyWithVariables()
|
||||
body.transformChildrenVoid(ParameterMapper(superConstructor, constructor, false))
|
||||
body.patchDeclarationParents(constructor)
|
||||
parameter.defaultValue = body
|
||||
}
|
||||
}
|
||||
|
||||
defaultClass.superTypes += irClass.defaultType
|
||||
defaultClass.addFakeOverrides()
|
||||
|
||||
return defaultClass
|
||||
}
|
||||
|
||||
private fun createImplObject() {
|
||||
val implObject = loweredEnum.implObject
|
||||
|
||||
@@ -300,7 +199,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
implObject.declarations += createSyntheticValuesPropertyDeclaration(enumEntries)
|
||||
implObject.declarations += createValuesPropertyInitializer(enumEntries)
|
||||
|
||||
|
||||
irClass.declarations += implObject
|
||||
}
|
||||
@@ -311,6 +210,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
val implObject = loweredEnum.implObject
|
||||
val constructor = implObject.constructors.single()
|
||||
|
||||
val irValuesInitializer = context.createArrayOfExpression(
|
||||
startOffset, endOffset,
|
||||
irClass.defaultType,
|
||||
@@ -335,31 +237,22 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
}
|
||||
)
|
||||
val irField = loweredEnum.valuesField.apply {
|
||||
initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
|
||||
val irField = loweredEnum.valuesField
|
||||
context.createIrBuilder(constructor.symbol).run {
|
||||
(constructor.body as IrBlockBody).statements +=
|
||||
irSetField(irGet(implObject.thisReceiver!!), irField, irValuesInitializer)
|
||||
}
|
||||
|
||||
val getter = loweredEnum.valuesGetter
|
||||
context.createIrBuilder(getter.symbol).run {
|
||||
getter.body = irBlockBody(irClass) { +irReturn(irGetField(irGetObject(implObject.symbol), irField)) }
|
||||
}
|
||||
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
val value = IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
loweredEnum.valuesField.symbol,
|
||||
loweredEnum.valuesField.type,
|
||||
receiver
|
||||
)
|
||||
val returnStatement = IrReturnImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
loweredEnum.valuesGetter.symbol,
|
||||
value
|
||||
)
|
||||
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
|
||||
createValuesPropertyInitializer(enumEntries)
|
||||
|
||||
return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
||||
false, loweredEnum.valuesField.descriptor, irField, getter, null).apply {
|
||||
parent = loweredEnum.implObject
|
||||
parent = implObject
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,54 +262,50 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
private val arrayType = context.ir.symbols.array.typeWith(irClass.defaultType)
|
||||
|
||||
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
||||
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>) {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
fun IrBlockBodyBuilder.initInstanceCall(instance: IrCall, constructor: IrCall): IrCall =
|
||||
fun IrBlockBuilder.initInstanceCall(instance: IrCall, constructor: IrCall): IrCall =
|
||||
irCall(initInstanceSymbol).apply {
|
||||
putValueArgument(0, instance)
|
||||
putValueArgument(1, constructor)
|
||||
}
|
||||
|
||||
val implObject = loweredEnum.implObject
|
||||
return IrAnonymousInitializerImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrAnonymousInitializerSymbolImpl(WrappedClassDescriptor())
|
||||
).apply {
|
||||
parent = implObject
|
||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) {
|
||||
val receiver = implObject.thisReceiver!!
|
||||
val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField))
|
||||
enumEntries
|
||||
.sortedBy { it.name }
|
||||
.withIndex()
|
||||
.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
dispatchReceiver = irGet(instances)
|
||||
putValueArgument(0, irInt(it.index))
|
||||
}
|
||||
val initializer = it.value.initializerExpression!!
|
||||
initializer.patchDeclarationParents(implObject)
|
||||
when {
|
||||
initializer is IrCall -> +initInstanceCall(instance, initializer)
|
||||
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
||||
val statements = initializer.statements
|
||||
val constructorCall = statements.last() as IrCall
|
||||
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
||||
+initializer
|
||||
}
|
||||
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
val constructor = implObject.constructors.single()
|
||||
val irBuilder = context.createIrBuilder(constructor.symbol, startOffset, endOffset)
|
||||
val valuesInitializer = irBuilder.irBlock(startOffset, endOffset) {
|
||||
val receiver = implObject.thisReceiver!!
|
||||
val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField))
|
||||
enumEntries
|
||||
.sortedBy { it.name }
|
||||
.withIndex()
|
||||
.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
dispatchReceiver = irGet(instances)
|
||||
putValueArgument(0, irInt(it.index))
|
||||
}
|
||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(receiver)
|
||||
}
|
||||
val initializer = it.value.initializerExpression!!
|
||||
initializer.patchDeclarationParents(constructor)
|
||||
when {
|
||||
initializer is IrCall -> +initInstanceCall(instance, initializer)
|
||||
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
||||
val statements = initializer.statements
|
||||
val constructorCall = statements.last() as IrCall
|
||||
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
||||
+initializer
|
||||
}
|
||||
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
}
|
||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(receiver)
|
||||
}
|
||||
}
|
||||
(constructor.body as IrBlockBody).statements += valuesInitializer
|
||||
}
|
||||
|
||||
private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
|
||||
@@ -453,302 +342,5 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructors(irClass: IrClass) {
|
||||
irClass.declarations.forEachIndexed { index, declaration ->
|
||||
if (declaration is IrConstructor)
|
||||
irClass.declarations[index] = transformEnumConstructor(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
||||
val loweredEnumConstructor = lowerEnumConstructor(enumConstructor)
|
||||
|
||||
for (parameter in enumConstructor.valueParameters) {
|
||||
val defaultValue = parameter.defaultValue ?: continue
|
||||
defaultValue.transformChildrenVoid(ParameterMapper(enumConstructor, loweredEnumConstructor, true))
|
||||
loweredEnumConstructor.valueParameters[parameter.loweredIndex].defaultValue = defaultValue
|
||||
defaultValue.patchDeclarationParents(loweredEnumConstructor)
|
||||
}
|
||||
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructor(constructor: IrConstructor): IrConstructorImpl {
|
||||
val startOffset = constructor.startOffset
|
||||
val endOffset = constructor.endOffset
|
||||
val loweredConstructor = WrappedClassConstructorDescriptor(
|
||||
constructor.descriptor.annotations,
|
||||
constructor.descriptor.source
|
||||
).let {
|
||||
IrConstructorImpl(
|
||||
startOffset, endOffset,
|
||||
constructor.origin,
|
||||
IrConstructorSymbolImpl(it),
|
||||
constructor.name,
|
||||
Visibilities.PROTECTED,
|
||||
constructor.returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isPrimary = constructor.isPrimary
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = constructor.parent
|
||||
body = constructor.body!! // Will be transformed later.
|
||||
}
|
||||
}
|
||||
|
||||
fun createSynthesizedValueParameter(index: Int, name: String, type: IrType) =
|
||||
WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.identifier(name),
|
||||
index,
|
||||
type,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = loweredConstructor
|
||||
}
|
||||
}
|
||||
|
||||
loweredConstructor.valueParameters += createSynthesizedValueParameter(0, "name", context.irBuiltIns.stringType)
|
||||
loweredConstructor.valueParameters += createSynthesizedValueParameter(1, "ordinal", context.irBuiltIns.intType)
|
||||
constructor.valueParameters.mapTo(loweredConstructor.valueParameters) {
|
||||
it.copyTo(loweredConstructor, index = it.loweredIndex).apply {
|
||||
loweredEnumConstructorParameters[it] = this
|
||||
}
|
||||
}
|
||||
|
||||
loweredEnumConstructors[constructor] = loweredConstructor
|
||||
|
||||
return loweredConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumClassBody(defaultClass: IrClass?) {
|
||||
irClass.transformChildrenVoid(EnumClassBodyTransformer(defaultClass))
|
||||
// Enum entries's classes have already been pulled out to the upper level - clear them up.
|
||||
irClass.declarations.filterIsInstance<IrEnumEntry>().forEach { it.correspondingClass = null }
|
||||
}
|
||||
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) :
|
||||
EnumConstructorCallTransformer {
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
enumConstructorCall.symbol)
|
||||
|
||||
assert(result.symbol.owner.valueParameters.size == 2) {
|
||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
||||
}
|
||||
|
||||
val nameParameter = enumClassConstructor.valueParameters.getOrElse(0) {
|
||||
throw AssertionError("No 'name' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
val ordinalParameter = enumClassConstructor.valueParameters.getOrElse(1) {
|
||||
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, nameParameter.type, nameParameter.symbol, origin)
|
||||
)
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, ordinalParameter.type, ordinalParameter.symbol, origin)
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression {
|
||||
val startOffset = delegatingConstructorCall.startOffset
|
||||
val endOffset = delegatingConstructorCall.endOffset
|
||||
|
||||
val delegatingConstructor = delegatingConstructorCall.symbol.owner
|
||||
val loweredDelegatingConstructor = loweredEnumConstructors.getOrElse(delegatingConstructor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $delegatingConstructor")
|
||||
}
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredDelegatingConstructor.symbol)
|
||||
|
||||
val firstParameter = enumClassConstructor.valueParameters[0]
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, firstParameter.type, firstParameter.symbol))
|
||||
val secondParameter = enumClassConstructor.valueParameters[1]
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol))
|
||||
|
||||
delegatingConstructor.valueParameters.forEach {
|
||||
result.putValueArgument(it.loweredIndex, delegatingConstructorCall.getValueArgument(it.index))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private abstract inner class InEnumEntry(private val enumEntry: IrEnumEntry) : EnumConstructorCallTransformer {
|
||||
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val name = enumEntry.name.asString()
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry.descriptor)
|
||||
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
|
||||
val enumConstructor = enumConstructorCall.symbol.owner
|
||||
val loweredConstructor = loweredEnumConstructors.getOrElse(enumConstructor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $enumConstructor")
|
||||
}
|
||||
|
||||
val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol)
|
||||
|
||||
result.putValueArgument(0,
|
||||
IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name))
|
||||
result.putValueArgument(1,
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
|
||||
|
||||
enumConstructor.valueParameters.forEach {
|
||||
result.putValueArgument(it.loweredIndex, enumConstructorCall.getValueArgument(it.index))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression {
|
||||
throw AssertionError("Unexpected delegating constructor call within enum entry: $enumEntry")
|
||||
}
|
||||
|
||||
abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrMemberAccessExpression
|
||||
}
|
||||
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
loweredConstructor: IrConstructorSymbol
|
||||
) = IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredConstructor
|
||||
)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
|
||||
val irConstructorSymbol = defaultEnumEntryConstructors[loweredConstructor.owner]?.symbol
|
||||
?: loweredConstructor
|
||||
return IrCallImpl(startOffset, endOffset, irConstructorSymbol.owner.returnType, irConstructorSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class EnumClassBodyTransformer(val defaultClass: IrClass?) : IrElementTransformerVoid() {
|
||||
private var enumConstructorCallTransformer: EnumConstructorCallTransformer? = null
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
if (declaration.kind == ClassKind.ENUM_CLASS || declaration == defaultClass)
|
||||
return declaration
|
||||
return super.visitClass(declaration)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry): IrStatement {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
|
||||
enumConstructorCallTransformer = InEnumEntryInitializer(declaration)
|
||||
|
||||
declaration.initializerExpression = declaration.initializerExpression?.transform(this, data = null)
|
||||
|
||||
enumConstructorCallTransformer = null
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
val containingClass = declaration.parentAsClass
|
||||
|
||||
// TODO local (non-enum) class in enum class constructor?
|
||||
val previous = enumConstructorCallTransformer
|
||||
|
||||
if (containingClass.kind == ClassKind.ENUM_ENTRY) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
val entry = irClass.declarations.filterIsInstance<IrEnumEntry>().single { it.correspondingClass == containingClass }
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(entry)
|
||||
} else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
||||
}
|
||||
|
||||
val result = super.visitConstructor(declaration)
|
||||
|
||||
enumConstructorCallTransformer = previous
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (expression.symbol.owner.parentAsClass.kind == ClassKind.ENUM_CLASS) {
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val parameter = expression.symbol.owner
|
||||
val loweredParameter = loweredEnumConstructorParameters[parameter]
|
||||
return if (loweredParameter == null) {
|
||||
expression
|
||||
} else {
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter.type,
|
||||
loweredParameter.symbol, expression.origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val IrValueParameter.loweredIndex: Int get() = index + 2
|
||||
|
||||
private class ParameterMapper(superConstructor: IrConstructor,
|
||||
val constructor: IrConstructor,
|
||||
val useLoweredIndex: Boolean) : IrElementTransformerVoid() {
|
||||
private val valueParameters = superConstructor.valueParameters.toSet()
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
|
||||
val superParameter = expression.symbol.owner as? IrValueParameter ?: return expression
|
||||
if (valueParameters.contains(superParameter)) {
|
||||
val index = if (useLoweredIndex) superParameter.loweredIndex else superParameter.index
|
||||
val parameter = constructor.valueParameters[index]
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
}
|
||||
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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 org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
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.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class EnumConstructorsLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
fun run(irFile: IrFile) {
|
||||
runOnFilePostfix(irFile)
|
||||
}
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
if (irClass.kind != ClassKind.ENUM_CLASS) return
|
||||
EnumClassTransformer(irClass).run()
|
||||
}
|
||||
|
||||
private interface EnumConstructorCallTransformer {
|
||||
fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression
|
||||
fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression
|
||||
}
|
||||
|
||||
private inner class EnumClassTransformer(val irClass: IrClass) {
|
||||
private val loweredEnumConstructors = mutableMapOf<IrConstructor, IrConstructor>()
|
||||
private val loweredEnumConstructorParameters = mutableMapOf<IrValueParameter, IrValueParameter>()
|
||||
|
||||
fun run() {
|
||||
insertInstanceInitializerCall()
|
||||
lowerEnumConstructors(irClass)
|
||||
lowerEnumEntriesClasses()
|
||||
lowerEnumClassBody()
|
||||
}
|
||||
|
||||
private fun insertInstanceInitializerCall() {
|
||||
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
// Skip nested
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
val blockBody = declaration.body as? IrBlockBody
|
||||
?: throw AssertionError("Unexpected constructor body: ${declaration.body}")
|
||||
if (blockBody.statements.all { it !is IrInstanceInitializerCall }) {
|
||||
blockBody.statements.transformFlat {
|
||||
if (it is IrEnumConstructorCall)
|
||||
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
|
||||
irClass.symbol, context.irBuiltIns.unitType))
|
||||
else null
|
||||
}
|
||||
}
|
||||
return declaration
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun lowerEnumEntriesClasses() {
|
||||
for (enumEntry in irClass.declarations.filterIsInstance<IrEnumEntry>())
|
||||
enumEntry.correspondingClass?.let { lowerEnumConstructors(it) }
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructors(irClass: IrClass) {
|
||||
irClass.declarations.forEachIndexed { index, declaration ->
|
||||
if (declaration is IrConstructor)
|
||||
irClass.declarations[index] = transformEnumConstructor(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
||||
val loweredEnumConstructor = lowerEnumConstructor(enumConstructor)
|
||||
|
||||
for (parameter in enumConstructor.valueParameters) {
|
||||
val defaultValue = parameter.defaultValue ?: continue
|
||||
defaultValue.transformChildrenVoid(ParameterMapper(enumConstructor, loweredEnumConstructor, true))
|
||||
loweredEnumConstructor.valueParameters[parameter.loweredIndex].defaultValue = defaultValue
|
||||
defaultValue.patchDeclarationParents(loweredEnumConstructor)
|
||||
}
|
||||
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructor(constructor: IrConstructor): IrConstructorImpl {
|
||||
val startOffset = constructor.startOffset
|
||||
val endOffset = constructor.endOffset
|
||||
val loweredConstructor = WrappedClassConstructorDescriptor(
|
||||
constructor.descriptor.annotations,
|
||||
constructor.descriptor.source
|
||||
).let {
|
||||
IrConstructorImpl(
|
||||
startOffset, endOffset,
|
||||
constructor.origin,
|
||||
IrConstructorSymbolImpl(it),
|
||||
constructor.name,
|
||||
Visibilities.PROTECTED,
|
||||
constructor.returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isPrimary = constructor.isPrimary
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = constructor.parent
|
||||
body = constructor.body!! // Will be transformed later.
|
||||
}
|
||||
}
|
||||
|
||||
fun createSynthesizedValueParameter(index: Int, name: String, type: IrType) =
|
||||
WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.identifier(name),
|
||||
index,
|
||||
type,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = loweredConstructor
|
||||
}
|
||||
}
|
||||
|
||||
loweredConstructor.valueParameters += createSynthesizedValueParameter(0, "name", context.irBuiltIns.stringType)
|
||||
loweredConstructor.valueParameters += createSynthesizedValueParameter(1, "ordinal", context.irBuiltIns.intType)
|
||||
constructor.valueParameters.mapTo(loweredConstructor.valueParameters) {
|
||||
it.copyTo(loweredConstructor, index = it.loweredIndex).apply {
|
||||
loweredEnumConstructorParameters[it] = this
|
||||
}
|
||||
}
|
||||
|
||||
loweredEnumConstructors[constructor] = loweredConstructor
|
||||
|
||||
return loweredConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumClassBody() {
|
||||
val transformer = EnumClassBodyTransformer()
|
||||
irClass.transformChildrenVoid(transformer)
|
||||
irClass.declarations.filterIsInstance<IrEnumEntry>().forEach {
|
||||
it.correspondingClass?.transformChildrenVoid(transformer)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) :
|
||||
EnumConstructorCallTransformer {
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
enumConstructorCall.symbol)
|
||||
|
||||
assert(result.symbol.owner.valueParameters.size == 2) {
|
||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
||||
}
|
||||
|
||||
val nameParameter = enumClassConstructor.valueParameters.getOrElse(0) {
|
||||
throw AssertionError("No 'name' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
val ordinalParameter = enumClassConstructor.valueParameters.getOrElse(1) {
|
||||
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, nameParameter.type, nameParameter.symbol, origin)
|
||||
)
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, ordinalParameter.type, ordinalParameter.symbol, origin)
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression {
|
||||
val startOffset = delegatingConstructorCall.startOffset
|
||||
val endOffset = delegatingConstructorCall.endOffset
|
||||
|
||||
val delegatingConstructor = delegatingConstructorCall.symbol.owner
|
||||
val loweredDelegatingConstructor = loweredEnumConstructors.getOrElse(delegatingConstructor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $delegatingConstructor")
|
||||
}
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredDelegatingConstructor.symbol)
|
||||
|
||||
val firstParameter = enumClassConstructor.valueParameters[0]
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, firstParameter.type, firstParameter.symbol))
|
||||
val secondParameter = enumClassConstructor.valueParameters[1]
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol))
|
||||
|
||||
delegatingConstructor.valueParameters.forEach {
|
||||
result.putValueArgument(it.loweredIndex, delegatingConstructorCall.getValueArgument(it.index))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private abstract inner class InEnumEntry(private val enumEntry: IrEnumEntry) : EnumConstructorCallTransformer {
|
||||
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val name = enumEntry.name.asString()
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry.descriptor)
|
||||
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
|
||||
val enumConstructor = enumConstructorCall.symbol.owner
|
||||
val loweredConstructor = loweredEnumConstructors.getOrElse(enumConstructor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $enumConstructor")
|
||||
}
|
||||
|
||||
val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol)
|
||||
|
||||
result.putValueArgument(0,
|
||||
IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name))
|
||||
result.putValueArgument(1,
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
|
||||
|
||||
enumConstructor.valueParameters.forEach {
|
||||
result.putValueArgument(it.loweredIndex, enumConstructorCall.getValueArgument(it.index))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression {
|
||||
throw AssertionError("Unexpected delegating constructor call within enum entry: $enumEntry")
|
||||
}
|
||||
|
||||
abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrMemberAccessExpression
|
||||
}
|
||||
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
loweredConstructor: IrConstructorSymbol
|
||||
) = IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredConstructor
|
||||
)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) =
|
||||
IrCallImpl(startOffset, endOffset, loweredConstructor.owner.returnType, loweredConstructor)
|
||||
}
|
||||
|
||||
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
|
||||
private var enumConstructorCallTransformer: EnumConstructorCallTransformer? = null
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
if (declaration.kind == ClassKind.ENUM_CLASS)
|
||||
return declaration
|
||||
return super.visitClass(declaration)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry): IrStatement {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
|
||||
enumConstructorCallTransformer = InEnumEntryInitializer(declaration)
|
||||
|
||||
declaration.initializerExpression = declaration.initializerExpression?.transform(this, data = null)
|
||||
|
||||
enumConstructorCallTransformer = null
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
val containingClass = declaration.parentAsClass
|
||||
|
||||
// TODO local (non-enum) class in enum class constructor?
|
||||
val previous = enumConstructorCallTransformer
|
||||
|
||||
if (containingClass.kind == ClassKind.ENUM_ENTRY) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
val entry = irClass.declarations.filterIsInstance<IrEnumEntry>().single { it.correspondingClass == containingClass }
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(entry)
|
||||
} else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
||||
}
|
||||
|
||||
val result = super.visitConstructor(declaration)
|
||||
|
||||
enumConstructorCallTransformer = previous
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (expression.symbol.owner.parentAsClass.kind == ClassKind.ENUM_CLASS) {
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val parameter = expression.symbol.owner
|
||||
val loweredParameter = loweredEnumConstructorParameters[parameter]
|
||||
return if (loweredParameter == null) {
|
||||
expression
|
||||
} else {
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter.type,
|
||||
loweredParameter.symbol, expression.origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val IrValueParameter.loweredIndex: Int get() = index + 2
|
||||
|
||||
private class ParameterMapper(superConstructor: IrConstructor,
|
||||
val constructor: IrConstructor,
|
||||
val useLoweredIndex: Boolean) : IrElementTransformerVoid() {
|
||||
private val valueParameters = superConstructor.valueParameters.toSet()
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
|
||||
val superParameter = expression.symbol.owner as? IrValueParameter ?: return expression
|
||||
if (valueParameters.contains(superParameter)) {
|
||||
val index = if (useLoweredIndex) superParameter.loweredIndex else superParameter.index
|
||||
val parameter = constructor.valueParameters[index]
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -488,7 +488,7 @@ internal object DataFlowIR {
|
||||
}, data = null)
|
||||
}
|
||||
|
||||
private fun IrClass.isFinal() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
|
||||
private fun IrClass.isFinal() = modality == Modality.FINAL
|
||||
|
||||
fun mapClassReferenceType(irClass: IrClass, eraseLocalObjects: Boolean = true): Type {
|
||||
// Do not try to devirtualize ObjC classes.
|
||||
|
||||
Reference in New Issue
Block a user