[K/N][IR] Refactored enums lowering a bit

This commit is contained in:
Igor Chevdar
2021-04-21 16:07:16 +05:00
parent 01dd3d6ed4
commit 476b3befaf
@@ -5,12 +5,11 @@
package org.jetbrains.kotlin.backend.konan.lower 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.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.EnumWhenLowering 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.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody 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.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.MemoryModel import org.jetbrains.kotlin.backend.konan.MemoryModel
@@ -23,38 +22,32 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL 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.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.* 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
private class EnumSyntheticFunctionsBuilder(val context: Context) { private class EnumSyntheticFunctionsBuilder(val context: Context) {
fun buildValuesExpression(startOffset: Int, endOffset: Int, fun IrBuilderWithScope.enumValues(enumClass: IrClass): IrExpression {
enumClass: IrClass): IrExpression { val loweredEnum = this@EnumSyntheticFunctionsBuilder.context.specialDeclarationsFactory.getLoweredEnum(enumClass)
val values = loweredEnum.getValuesField(startOffset, endOffset)
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) return irCall(genericValuesSymbol, listOf(enumClass.defaultType)).apply {
putValueArgument(0, values)
return irCall(startOffset, endOffset, genericValuesSymbol.owner, listOf(enumClass.defaultType)) }
.apply {
putValueArgument(0, loweredEnum.getValuesField(startOffset, endOffset))
}
} }
fun buildValueOfExpression(startOffset: Int, endOffset: Int, fun IrBuilderWithScope.enumValueOf(enumClass: IrClass, value: IrExpression): IrExpression {
enumClass: IrClass, val loweredEnum = this@EnumSyntheticFunctionsBuilder.context.specialDeclarationsFactory.getLoweredEnum(enumClass)
value: IrExpression): IrExpression { val values = loweredEnum.getValuesField(startOffset, endOffset)
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) return irCall(genericValueOfSymbol, listOf(enumClass.defaultType)).apply {
putValueArgument(0, value)
return irCall(startOffset, endOffset, genericValueOfSymbol.owner, listOf(enumClass.defaultType)) putValueArgument(1, values)
.apply { }
putValueArgument(0, value)
putValueArgument(1, loweredEnum.getValuesField(startOffset, endOffset))
}
} }
private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum
@@ -63,65 +56,57 @@ private class EnumSyntheticFunctionsBuilder(val context: Context) {
} }
internal class EnumUsageLowering(val context: Context) internal class EnumUsageLowering(val context: Context)
: IrElementTransformerVoid(), FileLoweringPass { : IrElementTransformer<IrBuilderWithScope?>, FileLoweringPass {
private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context) private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context)
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
visitFile(irFile) visitFile(irFile, data = null)
} }
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { override fun visitDeclaration(declaration: IrDeclarationBase, data: IrBuilderWithScope?): IrStatement {
return super.visitDeclaration(declaration, context.createIrBuilder(declaration.symbol))
}
override fun visitGetEnumValue(expression: IrGetEnumValue, data: IrBuilderWithScope?): IrExpression {
val entry = expression.symbol.owner val entry = expression.symbol.owner
return loadEnumEntry( return data!!.at(expression).loadEnumEntry(entry.parentAsClass, entry.name)
expression.startOffset,
expression.endOffset,
entry.parentAsClass,
entry.name
)
} }
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall, data: IrBuilderWithScope?): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildren(this, data)
val intrinsicType = tryGetIntrinsicType(expression) val intrinsicType = tryGetIntrinsicType(expression)
if (intrinsicType != IntrinsicType.ENUM_VALUES && intrinsicType != IntrinsicType.ENUM_VALUE_OF) if (intrinsicType != IntrinsicType.ENUM_VALUES && intrinsicType != IntrinsicType.ENUM_VALUE_OF)
return expression return expression
val startOffset = expression.startOffset data!!.at(expression)
val endOffset = expression.endOffset
val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol
if (irClassSymbol == null || irClassSymbol == context.ir.symbols.enum) { if (irClassSymbol == null || irClassSymbol == context.ir.symbols.enum) {
// Either a type parameter or a type parameter erased to 'Enum'. // Either a type parameter or a type parameter erased to 'Enum'.
return irCall(startOffset, endOffset, context.ir.symbols.throwIllegalStateException.owner, emptyList()) return data.irCall(context.ir.symbols.throwIllegalStateException)
} }
val irClass = irClassSymbol.owner val irClass = irClassSymbol.owner
assert (irClass.kind == ClassKind.ENUM_CLASS) require(irClass.kind == ClassKind.ENUM_CLASS)
return if (intrinsicType == IntrinsicType.ENUM_VALUES) { return with(enumSyntheticFunctionsBuilder) {
enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass) if (intrinsicType == IntrinsicType.ENUM_VALUES)
} else { data.enumValues(irClass)
val value = expression.getValueArgument(0)!! else
enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value) data.enumValueOf(irClass, expression.getValueArgument(0)!!)
} }
} }
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression { private fun IrBuilderWithScope.loadEnumEntry(enumClass: IrClass, name: Name): IrExpression {
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) val loweredEnum = this@EnumUsageLowering.context.specialDeclarationsFactory.getLoweredEnum(enumClass)
val ordinal = loweredEnum.entriesMap.getValue(name) val ordinal = loweredEnum.entriesMap.getValue(name)
return IrCallImpl.fromSymbolDescriptor( return irCall(loweredEnum.itemGetterSymbol, enumClass.defaultType).apply {
startOffset, endOffset, enumClass.defaultType, dispatchReceiver = irCall(loweredEnum.valuesGetter)
loweredEnum.itemGetterSymbol.owner.symbol, putValueArgument(0, irInt(ordinal))
typeArgumentsCount = 0,
loweredEnum.itemGetterSymbol.owner.valueParameters.size
).apply {
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.returnType,
loweredEnum.valuesGetter.symbol, loweredEnum.valuesGetter.typeParameters.size,
loweredEnum.valuesGetter.valueParameters.size)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
} }
} }
} }
@@ -314,39 +299,14 @@ internal class EnumClassLowering(val context: Context) : FileLoweringPass {
(constructor.body as IrBlockBody).statements += valuesInitializer (constructor.body as IrBlockBody).statements += valuesInitializer
} }
private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody { private fun createSyntheticValuesMethodBody(declaration: IrFunction) =
val startOffset = irClass.startOffset context.createIrBuilder(declaration.symbol, irClass.startOffset, irClass.endOffset).irBlockBody {
val endOffset = irClass.endOffset +irReturn(with(enumSyntheticFunctionsBuilder) { enumValues(irClass) })
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass) }
return IrBlockBodyImpl(startOffset, endOffset).apply {
statements += IrReturnImpl(
startOffset,
endOffset,
context.irBuiltIns.nothingType,
declaration.symbol,
valuesExpression
)
}
}
private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody {
val startOffset = irClass.startOffset
val endOffset = irClass.endOffset
val parameter = declaration.valueParameters[0]
val value = IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol)
val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value)
return IrBlockBodyImpl(startOffset, endOffset).apply {
statements += IrReturnImpl(
startOffset,
endOffset,
context.irBuiltIns.nothingType,
declaration.symbol,
valueOfExpression
)
}
}
private fun createSyntheticValueOfMethodBody(declaration: IrFunction) =
context.createIrBuilder(declaration.symbol, irClass.startOffset, irClass.endOffset).irBlockBody {
+irReturn(with(enumSyntheticFunctionsBuilder) { enumValueOf(irClass, irGet(declaration.valueParameters[0])) })
}
} }
} }