From bb34a0f22beaad802831758d319a51eb69fd6995 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Mon, 27 Jan 2020 13:05:00 +0700 Subject: [PATCH] [StubIr] Refactor origins 1. Get rid of useless origin for FunctionParameterStub. 2. Add origins for enum entries and struct members. 3. Put all synthetic origins under single sealed class. 4. Add mangling for enum entries. --- .../native/interop/gen/InteropMangler.kt | 4 ++ .../kotlin/native/interop/gen/ObjCStubs.kt | 2 +- .../kotlin/native/interop/gen/StubIr.kt | 45 +++++++++++++------ .../interop/gen/StubIrElementBuilders.kt | 19 ++++---- .../interop/gen/StubIrMetadataEmitter.kt | 2 +- .../interop/gen/StubIrUniqIdProvider.kt | 15 ++++++- 6 files changed, 60 insertions(+), 27 deletions(-) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropMangler.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropMangler.kt index cbde8f84f77..037abaeb92d 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropMangler.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropMangler.kt @@ -37,6 +37,7 @@ sealed class ManglingContext { interface InteropMangler { val StructDecl.uniqueSymbolName: String val EnumDef.uniqueSymbolName: String + val EnumConstant.uniqSymbolName: String val ObjCClass.uniqueSymbolName: String val ObjCClass.metaClassUniqueSymbolName: String val ObjCProtocol.uniqueSymbolName: String @@ -63,6 +64,9 @@ class KotlinLikeInteropMangler(context: ManglingContext = ManglingContext.Empty) override val EnumDef.uniqueSymbolName: String get() = "enumdef:$prefix$spelling" + override val EnumConstant.uniqSymbolName: String + get() = "enumconstant:$prefix$name" + override val ObjCClass.uniqueSymbolName: String get() = "objcclass:$prefix$name" diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt index 1d97a325d10..6f9b895f787 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt @@ -435,7 +435,7 @@ internal abstract class ObjCContainerStubBuilder( ConstructorStub( isPrimary = false, visibility = VisibilityModifier.PROTECTED, - origin = StubOrigin.SyntheticDefaultConstructor) + origin = StubOrigin.Synthetic.DefaultConstructor) } else null return Pair( diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt index f721b3f9ddc..bdec5b7e92f 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt @@ -91,13 +91,29 @@ sealed class StubOrigin { /** * Special case when element of IR was generated. */ - // TODO: All "synthetic" cases should be handled separately. - object Synthetic : StubOrigin() + sealed class Synthetic : StubOrigin() { + object CompanionObject : Synthetic() - /** - * Denotes default constructor that was generated and has no real origin. - */ - object SyntheticDefaultConstructor : StubOrigin() + /** + * Denotes default constructor that was generated and has no real origin. + */ + object DefaultConstructor : Synthetic() + + /** + * CEnum.Companion.byValue. + */ + class EnumByValue(val enum: EnumDef) : Synthetic() + + /** + * CEnum.value. + */ + class EnumValueField(val enum: EnumDef) : Synthetic() + + /** + * E.CEnumVar.value. + */ + class EnumVarValueField(val enum: EnumDef) : Synthetic() + } class ObjCCategoryInitMethod( val method: org.jetbrains.kotlin.native.interop.indexer.ObjCMethod @@ -125,13 +141,16 @@ sealed class StubOrigin { class Enum(val enum: EnumDef) : StubOrigin() + class EnumEntry(val constant: EnumConstant) : StubOrigin() + class Function(val function: FunctionDecl) : StubOrigin() - // TODO: Unused, remove. - class FunctionParameter(val parameter: Parameter) : StubOrigin() - class Struct(val struct: StructDecl) : StubOrigin() + class StructMember( + val member: org.jetbrains.kotlin.native.interop.indexer.StructMember + ) : StubOrigin() + class Constant(val constantDef: ConstantDef): StubOrigin() class Global(val global: GlobalDecl) : StubOrigin() @@ -283,7 +302,7 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde override val superClassInit: SuperClassInit? = null, override val interfaces: List = emptyList(), override val properties: List = emptyList(), - override val origin: StubOrigin = StubOrigin.Synthetic, + override val origin: StubOrigin = StubOrigin.Synthetic.CompanionObject, override val annotations: List = emptyList(), override val childrenClasses: List = emptyList(), override val simpleContainers: List = emptyList() @@ -328,8 +347,7 @@ class FunctionParameterStub( val name: String, val type: StubType, override val annotations: List = emptyList(), - val isVararg: Boolean = false, - val origin: StubOrigin = StubOrigin.Synthetic + val isVararg: Boolean = false ) : AnnotationHolder enum class MemberStubModality { @@ -454,7 +472,8 @@ class ConstructorStub( class EnumEntryStub( val name: String, val constant: IntegralConstantStub, - val aliases: List + val aliases: List, + val origin: StubOrigin.EnumEntry ) { class Alias(val name: String) } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt index 3f8eaf3419b..f84c56f1e8c 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt @@ -73,7 +73,7 @@ internal class StructStubBuilder( val offset = field.offset / 8 val fieldRefType = context.mirror(field.type) val unwrappedFieldType = field.type.unwrapTypedefs() - val origin = StubOrigin.Synthetic + val origin = StubOrigin.StructMember(field) if (unwrappedFieldType is ArrayType) { val type = (fieldRefType as TypeMirror.ByValue).valueType val annotations = if (platform == KotlinPlatform.JVM) { @@ -115,7 +115,7 @@ internal class StructStubBuilder( context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo) context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo) val kind = PropertyStub.Kind.Var(readBits, writeBits) - PropertyStub(field.name, kotlinType.toStubIrType(), kind, origin = StubOrigin.Synthetic) + PropertyStub(field.name, kotlinType.toStubIrType(), kind, origin = StubOrigin.StructMember(field)) } val superClass = context.platform.getRuntimeType("CStructVar") @@ -215,7 +215,7 @@ internal class EnumStubBuilder( type = baseType, kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.GetConstructorParameter(constructorParameter)), modality = MemberStubModality.OPEN, - origin = StubOrigin.Synthetic, + origin = StubOrigin.Synthetic.EnumValueField(enumDef), isOverride = true) val canonicalsByValue = enumDef.constants @@ -233,7 +233,7 @@ internal class EnumStubBuilder( val literal = context.tryCreateIntegralStub(enumDef.baseType, constant.value) ?: error("Cannot create enum value ${constant.value} of type ${enumDef.baseType}") val aliases = aliasConstants.filter { it.value == constant.value }.map { EnumEntryStub.Alias(it.name) } - EnumEntryStub(constant.name, literal, aliases) + EnumEntryStub(constant.name, literal, aliases, StubOrigin.EnumEntry(constant)) } val origin = StubOrigin.Enum(enumDef) val primaryConstructor = ConstructorStub(listOf(constructorParameter), emptyList(), isPrimary = true, origin = origin) @@ -303,7 +303,7 @@ internal class EnumStubBuilder( kind, MemberStubModality.FINAL, null, - origin = StubOrigin.Synthetic + origin = StubOrigin.EnumEntry(constant) ) } val container = SimpleStubContainer( @@ -333,7 +333,6 @@ internal class FunctionStubBuilder( } val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type) - val origin = StubOrigin.FunctionParameter(parameter) parameters += when { representCFunctionParameterAsString(func, parameter.type) -> { val annotations = when (platform) { @@ -341,7 +340,7 @@ internal class FunctionStubBuilder( KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.CString) } val type = KotlinTypes.string.makeNullable().toStubIrType() - val functionParameterStub = FunctionParameterStub(parameterName, type, annotations, origin = origin) + val functionParameterStub = FunctionParameterStub(parameterName, type, annotations) context.bridgeComponentsBuilder.cStringParameters += functionParameterStub functionParameterStub } @@ -351,17 +350,17 @@ internal class FunctionStubBuilder( KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.WCString) } val type = KotlinTypes.string.makeNullable().toStubIrType() - val functionParameterStub = FunctionParameterStub(parameterName, type, annotations, origin = origin) + val functionParameterStub = FunctionParameterStub(parameterName, type, annotations) context.bridgeComponentsBuilder.wCStringParameters += functionParameterStub functionParameterStub } representAsValuesRef != null -> { - FunctionParameterStub(parameterName, representAsValuesRef.toStubIrType(), origin = origin) + FunctionParameterStub(parameterName, representAsValuesRef.toStubIrType()) } else -> { val mirror = context.mirror(parameter.type) val type = mirror.argType.toStubIrType() - FunctionParameterStub(parameterName, type, origin = origin) + FunctionParameterStub(parameterName, type) } } } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt index b649974f4a0..32aac55c013 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt @@ -83,7 +83,7 @@ internal class ModuleMetadataEmitter( typeParametersInterner = Interner(data.typeParametersInterner) ) val children = element.children + if (element is ClassStub.Companion) { - listOf(ConstructorStub(isPrimary = true, visibility = VisibilityModifier.PRIVATE, origin = StubOrigin.SyntheticDefaultConstructor)) + listOf(ConstructorStub(isPrimary = true, visibility = VisibilityModifier.PRIVATE, origin = StubOrigin.Synthetic.DefaultConstructor)) } else emptyList() val elements = KmElements(children.map { it.accept(this, classVisitingContext) }) val kmClass = with (MappingExtensions(data.typeParametersInterner)) { diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrUniqIdProvider.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrUniqIdProvider.kt index e108ade4baf..81285f6b6a0 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrUniqIdProvider.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrUniqIdProvider.kt @@ -21,6 +21,7 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) { is StubOrigin.Function -> function.origin.function.uniqueSymbolName is StubOrigin.ObjCMethod -> function.origin.method.uniqueSymbolName is StubOrigin.ObjCCategoryInitMethod -> "${function.origin.method.uniqueSymbolName}#Create" + is StubOrigin.Synthetic.EnumByValue -> "${function.origin.enum.uniqueSymbolName}#ByValue" else -> error("Unexpected origin ${function.origin} for function ${function.name}.") }.toUniqId() } @@ -30,7 +31,12 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) { is StubOrigin.ObjCProperty -> property.origin.property.uniqueSymbolName is StubOrigin.Constant -> property.origin.constantDef.uniqueSymbolName is StubOrigin.Global -> property.origin.global.uniqueSymbolName - // TODO: What to do with origin for enum entries and struct fields? + // TODO: Is it correct for entries that are emitted as top-level constants? + // Should we emit the same uniq id for constants and enum entries? + is StubOrigin.EnumEntry -> property.origin.constant.uniqSymbolName + is StubOrigin.Synthetic.EnumValueField -> "${property.origin.enum.uniqueSymbolName}#Value" + is StubOrigin.StructMember -> property.origin.member.name + is StubOrigin.Synthetic.EnumVarValueField -> "${property.origin.enum.uniqueSymbolName}#Var" else -> error("Unexpected origin ${property.origin} for property ${property.name}.") }.toUniqId() } @@ -60,6 +66,7 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) { } is StubOrigin.Struct -> origin.struct.uniqueSymbolName is StubOrigin.Enum -> origin.enum.uniqueSymbolName + is StubOrigin.VarOf -> "${uniqSymbolNameForClass(origin.typeOrigin)}#Var" else -> null } @@ -72,7 +79,7 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) { }.toUniqId() private fun InteropMangler.uniqSymbolNameForConstructor(origin: StubOrigin): String? = when (origin) { - is StubOrigin.SyntheticDefaultConstructor -> "${context.prefix}#Constructor" + is StubOrigin.Synthetic.DefaultConstructor -> "${context.prefix}#Constructor" is StubOrigin.Enum -> "${origin.enum.uniqueSymbolName}#Constructor" is StubOrigin.Struct -> "${origin.struct.uniqueSymbolName}#Constructor" is StubOrigin.ObjCMethod -> "${origin.method.uniqueSymbolName}#Constructor" @@ -84,6 +91,10 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) { ?: error("Unexpected origin ${constructorStub.origin} for constructor.") }.toUniqId() + fun uniqIdForEnumEntry(enumEntry: EnumEntryStub, enum: ClassStub.Enum): UniqId = with (mangler) { + "${uniqSymbolNameForClass(enum.origin)}#${enumEntry.origin.constant.name}" + }.toUniqId() + /** * MSB should be set to 1 for public declarations. * @see org.jetbrains.kotlin.ir.util.UniqId