diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt index 41efb6bd32d..e3e76608d93 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt @@ -1,10 +1,21 @@ package org.jetbrains.kotlin.backend.konan.ir +import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjectionImpl +import org.jetbrains.kotlin.types.TypeSubstitutor import java.io.StringWriter @@ -76,3 +87,50 @@ fun ir2stringWhole(ir: IrElement?): String { return strWriter.toString() } +internal fun ClassDescriptor.createSimpleDelegatingConstructor(superConstructorDescriptor: ClassConstructorDescriptor) + : Pair { + val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( + this, + Annotations.EMPTY, + superConstructorDescriptor.isPrimary, + SourceElement.NO_SOURCE) + val valueParameters = superConstructorDescriptor.valueParameters.map { + it.copy(constructorDescriptor, it.name, it.index) + } + constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility) + constructorDescriptor.returnType = superConstructorDescriptor.returnType + + val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + listOf( + IrDelegatingConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, superConstructorDescriptor).apply { + valueParameters.forEachIndexed { idx, parameter -> + putValueArgument(idx, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter)) + } + }, + IrInstanceInitializerCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this) + ) + ) + val constructor = IrConstructorImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, constructorDescriptor, body) + + return Pair(constructorDescriptor, constructor) +} + +internal fun Context.createArrayOfExpression(arrayElementType: KotlinType, + arrayElements: List): IrExpression { + val kotlinPackage = irModule!!.descriptor.getPackage(FqName("kotlin")) + val genericArrayOfFun = kotlinPackage.memberScope.getContributedFunctions(Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND).first() + val typeParameter0 = genericArrayOfFun.typeParameters[0] + val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType))) + val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!! + + val typeArguments = mapOf(typeParameter0 to arrayElementType) + + val valueParameter0 = substitutedArrayOfFun.valueParameters[0] + val arg0VarargType = valueParameter0.type + val arg0VarargElementType = valueParameter0.varargElementType!! + val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements) + + return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply { + putValueArgument(0, arg0) + } +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index 92ec6d904b5..bad27a526ec 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -2,13 +2,20 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.jvm.descriptors.initialize import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.OverriddenFunctionDescriptor +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.* @@ -18,9 +25,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.* internal class ClassDelegationLowering(val context: Context) : DeclarationContainerLoweringPass { override fun lower(irDeclarationContainer: IrDeclarationContainer) { @@ -89,7 +94,35 @@ internal class ClassDelegationLowering(val context: Context) : DeclarationContai } internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass { + private val kotlinReflectPackage = context.irModule!!.descriptor.getPackage(FqName.fromSegments(listOf("kotlin", "reflect"))) + private val genericKPropertyImplType = kotlinReflectPackage.memberScope.getContributedClassifier(Name.identifier("KPropertyImpl"), + NoLookupLocation.FROM_BACKEND) as ClassDescriptor + + private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) + private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + + fun getKPropertyImplConstructorDescriptorWithProjection(type: KotlinType): ClassConstructorDescriptor { + val typeParameterT = genericKPropertyImplType.declaredTypeParameters[0] + val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(type))) + return genericKPropertyImplType.unsubstitutedPrimaryConstructor!!.substitute(typeSubstitutor)!! + } + + fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType { + return this.defaultType.replace(type.map(::TypeProjectionImpl)) + } + override fun lower(irFile: IrFile) { + val kProperties = mutableListOf() + + val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single() + val typeParameterT = genericArrayType.declaredTypeParameters[0] + val kPropertyImplType = genericKPropertyImplType.replace(context.builtIns.anyType) + val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(kPropertyImplType))) + val substitutedGetter = getter.substitute(typeSubstitutor)!! + + val kPropertiesField = createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, genericArrayType.replace(kPropertyImplType)) + + irFile.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitFunction(declaration: IrFunction): IrStatement { return super.visitFunction(declaration) @@ -124,26 +157,43 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa return declaration } - private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName.fromSegments(listOf("kotlin", "reflect"))) - private val genericKPropertyImplType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("KPropertyImpl"), - NoLookupLocation.FROM_BACKEND) as ClassDescriptor - private fun transformBridgeToDelegate(name: String, type: KotlinType, irFunction: IrFunction?): IrFunction? { irFunction?.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitCallableReference(expression: IrCallableReference): IrExpression { - val typeParameterT = genericKPropertyImplType.declaredTypeParameters[0] - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(type))) - val kPropertyImplType = genericKPropertyImplType.substitute(typeSubstitutor) - return IrCallImpl(expression.startOffset, expression.endOffset, - kPropertyImplType.defaultType, kPropertyImplType.unsubstitutedPrimaryConstructor!!, null).apply { - putValueArgument(0, IrConstImpl(expression.startOffset, expression.endOffset, + val fieldInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + getKPropertyImplConstructorDescriptorWithProjection(type)).apply { + putValueArgument(0, IrConstImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.builtIns.stringType, IrConstKind.String, name)) } + + val index = kProperties.size + kProperties.add(fieldInitializer) + + return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply { + dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField) + putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, index)) + } } }) return irFunction } + }) + + irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, + kPropertiesField, + IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.createArrayOfExpression(kPropertyImplType, kProperties)))) + } + + private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : + IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION") + + private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: SimpleType): PropertyDescriptorImpl { + return PropertyDescriptorImpl.create(containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE, + false, "KPROPERTIES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, + false, false, false, false, false, false).initialize(fieldType) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index d64b9dd1dfd..e96b03e1445 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -10,6 +10,8 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanPlatform import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression +import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructor import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl @@ -171,7 +173,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { descriptor.constructors.forEach { val loweredEnumConstructor = loweredEnumConstructors[it]!! - val (constructorDescriptor, constructor) = createSimpleDelegatingConstructor(defaultClassDescriptor, loweredEnumConstructor) + val (constructorDescriptor, constructor) = defaultClassDescriptor.createSimpleDelegatingConstructor(loweredEnumConstructor) constructors.add(constructorDescriptor) defaultClass.declarations.add(constructor) defaultEnumEntryConstructors.put(loweredEnumConstructor, constructorDescriptor) @@ -233,7 +235,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val memberScope = MemberScope.Empty val constructorOfAny = irClass.descriptor.module.builtIns.any.constructors.first() - val (constructorDescriptor, constructor) = createSimpleDelegatingConstructor(implObjectDescriptor, constructorOfAny) + val (constructorDescriptor, constructor) = implObjectDescriptor.createSimpleDelegatingConstructor(constructorOfAny) implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor) @@ -260,34 +262,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { return newDescriptor } - private fun createSimpleDelegatingConstructor(classDescriptor: ClassDescriptor, - superConstructorDescriptor: ClassConstructorDescriptor) - : Pair { - val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( - classDescriptor, - Annotations.EMPTY, - superConstructorDescriptor.isPrimary, - SourceElement.NO_SOURCE) - val valueParameters = superConstructorDescriptor.valueParameters.map { - it.copy(constructorDescriptor, it.name, it.index) - } - constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility) - constructorDescriptor.returnType = superConstructorDescriptor.returnType - - val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - listOf( - IrDelegatingConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, superConstructorDescriptor).apply { - valueParameters.forEachIndexed { idx, parameter -> - putValueArgument(idx, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter)) - } - }, - IrInstanceInitializerCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, classDescriptor) - ) - ) - val constructor = IrConstructorImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, constructorDescriptor, body) - return Pair(constructorDescriptor, constructor) - } - private fun createSyntheticValuesFieldDeclaration(implObjectDescriptor: ClassDescriptor, enumEntries: List): IrFieldImpl { val valuesArrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.descriptor.defaultType) @@ -304,7 +278,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val loweredEnumEntry = LoweredEnumEntry(implObjectDescriptor, valuesFieldDescriptor, substitutedValueOf, entriesMap) loweredEnumEntries.put(irClass.descriptor, loweredEnumEntry) - val irValuesInitializer = createArrayOfExpression(irClass.descriptor.defaultType, enumEntries.map { it.initializerExpression }) + val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType, enumEntries.map { it.initializerExpression }) val irField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, valuesFieldDescriptor, @@ -321,31 +295,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) - private val genericArrayOfFun = kotlinPackage.memberScope.getContributedFunctions(Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND).first() - private val genericValueOfFun = context.builtIns.getKonanInternalFunctions("valueOfForEnum").single() private val genericValuesFun = context.builtIns.getKonanInternalFunctions("valuesForEnum").single() private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - private fun createArrayOfExpression(arrayElementType: KotlinType, arrayElements: List): IrExpression { - val typeParameter0 = genericArrayOfFun.typeParameters[0] - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType))) - val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!! - - val typeArguments = mapOf(typeParameter0 to arrayElementType) - - val valueParameter0 = substitutedArrayOfFun.valueParameters[0] - val arg0VarargType = valueParameter0.type - val arg0VarargElementType = valueParameter0.varargElementType!! - val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements) - - return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply { - putValueArgument(0, arg0) - } - } - private fun createSyntheticValuesMethodDeclaration(companionObjectDescriptor: ClassDescriptor): IrFunction { val typeParameterT = genericValuesFun.typeParameters[0] val enumClassType = irClass.descriptor.defaultType