From 18abebe387214e066f38fbe5326f86f898726b58 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Tue, 14 Jul 2020 14:17:19 +0700 Subject: [PATCH] [Interop][Metadata] Do not emit UniqId We don't need to emit UniqId on cinterop side anymore because IR linker computes IdSignature (which supersedes UniId) by itself when resolves interop descriptor (dde5eced877bc5c1c317850a2f9f64737d750bd3). --- .../native/interop/gen/InteropMangler.kt | 105 ------------ .../interop/gen/StubIrMetadataEmitter.kt | 11 +- .../interop/gen/StubIrUniqIdProvider.kt | 105 ------------ .../native/interop/gen/ManglingSmokeTests.kt | 162 ------------------ 4 files changed, 1 insertion(+), 382 deletions(-) delete mode 100644 Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropMangler.kt delete mode 100644 Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrUniqIdProvider.kt delete mode 100644 Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ManglingSmokeTests.kt 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 deleted file mode 100644 index 037abaeb92d..00000000000 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropMangler.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2010-2019 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.native.interop.gen - -import org.jetbrains.kotlin.native.interop.indexer.* - -/** - * Allows to nest declaration mangles. - */ -sealed class ManglingContext { - - abstract val prefix: String - - class Module(name: String) : ManglingContext() { - override val prefix: String = "$name." - } - - /** - * Used to represent containers like structures, classes, etc. - */ - class Entity(name: String, parentContext: ManglingContext = Empty) : ManglingContext() { - override val prefix: String = "${parentContext.prefix}$name." - } - - object Empty : ManglingContext() { - override val prefix: String = "" - } -} - -/** - * We need a way to refer external declarations from Kotlin Libraries - * by stable unique identifier. To be able to do it, we mangle them. - */ -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 - val ObjCProtocol.metaClassUniqueSymbolName: String - val ObjCMethod.uniqueSymbolName: String - val ObjCProperty.uniqueSymbolName: String - val TypedefDef.uniqueSymbolName: String - val FunctionDecl.uniqueSymbolName: String - val ConstantDef.uniqueSymbolName: String - val WrappedMacroDef.uniqueSymbolName: String - val GlobalDecl.uniqueSymbolName: String -} - -/** - * Mangler that mimics behaviour of the one from the Kotlin compiler. - */ -class KotlinLikeInteropMangler(context: ManglingContext = ManglingContext.Empty) : InteropMangler { - - private val prefix = context.prefix - - override val StructDecl.uniqueSymbolName: String - get() = "structdecl:$prefix$spelling" - - 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" - - override val ObjCClass.metaClassUniqueSymbolName: String - get() = "objcmetaclass:$prefix$name" - - override val ObjCProtocol.uniqueSymbolName: String - get() = "objcprotocol:$prefix$name" - - override val ObjCProtocol.metaClassUniqueSymbolName: String - get() = "objcmetaprotocol:$prefix$name" - - override val ObjCMethod.uniqueSymbolName: String - get() = "objcmethod:$prefix$selector" - - override val ObjCProperty.uniqueSymbolName: String - get() = "objcproperty:$prefix$name" - - override val TypedefDef.uniqueSymbolName: String - get() = "typedef:$prefix$name" - - override val FunctionDecl.uniqueSymbolName: String - get() = "funcdecl:$prefix$functionName" - - override val ConstantDef.uniqueSymbolName: String - get() = "macrodef:$prefix$name" - - override val WrappedMacroDef.uniqueSymbolName: String - get() = "macrodef:$prefix$name" - - override val GlobalDecl.uniqueSymbolName: String - get() = "globaldecl:$prefix$name" - - private val FunctionDecl.functionName: String - get() = name -} \ No newline at end of file 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 72a5a37a372..3f47a08766c 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 @@ -50,8 +50,7 @@ internal class ModuleMetadataEmitter( ) { fun emit(): KmModuleFragment { - val uniqIdProvider = StubIrUniqIdProvider(ManglingContext.Module(packageFqName)) - val context = VisitingContext(uniqIds = uniqIdProvider, bridgeBuilderResult = bridgeBuilderResult) + val context = VisitingContext(bridgeBuilderResult = bridgeBuilderResult) val elements = KmElements(visitor.visitSimpleStubContainer(module, context)) return writeModule(elements) } @@ -87,7 +86,6 @@ internal class ModuleMetadataEmitter( */ private data class VisitingContext( val container: StubContainer? = null, - val uniqIds: StubIrUniqIdProvider, val typeParametersInterner: Interner = Interner(), val bridgeBuilderResult: BridgeBuilderResult ) { @@ -110,7 +108,6 @@ internal class ModuleMetadataEmitter( override fun visitClass(element: ClassStub, data: VisitingContext): List { val classVisitingContext = VisitingContext( container = element, - uniqIds = data.uniqIds.createChild(element.nestedName()), typeParametersInterner = Interner(data.typeParametersInterner), bridgeBuilderResult = data.bridgeBuilderResult ) @@ -131,7 +128,6 @@ internal class ModuleMetadataEmitter( km.functions += elements.functions.toList() km.constructors += elements.constructors.toList() km.companionObject = element.companion?.nestedName() - km.uniqId = data.uniqIds.uniqIdForClass(element) if (element is ClassStub.Enum) { element.entries.mapTo(km.klibEnumEntries) { mapEnumEntry(it, classVisitingContext) } } @@ -144,7 +140,6 @@ internal class ModuleMetadataEmitter( override fun visitTypealias(element: TypealiasStub, data: VisitingContext): KmTypeAlias = data.withMappingExtensions { KmTypeAlias(element.flags, element.alias.topLevelName).also { km -> - km.uniqId = data.uniqIds.uniqIdForTypeAlias(element) km.underlyingType = element.aliasee.map(shouldExpandTypeAliases = false) km.expandedType = element.aliasee.map() } @@ -166,7 +161,6 @@ internal class ModuleMetadataEmitter( function.parameters.mapTo(km.valueParameters) { it.map() } function.annotations.mapTo(km.annotations) { it.map() } km.returnType = function.returnType.map() - km.uniqId = data.uniqIds.uniqIdForFunction(function) } } @@ -184,7 +178,6 @@ internal class ModuleMetadataEmitter( val name = getPropertyNameInScope(property, data.container) KmProperty(property.flags, name, kind.getterFlags, kind.setterFlags).also { km -> property.annotations.mapTo(km.annotations) { it.map() } - km.uniqId = data.uniqIds.uniqIdForProperty(property) km.receiverParameterType = property.receiverType?.map() km.returnType = property.type.map() if (kind is PropertyStub.Kind.Var) { @@ -208,7 +201,6 @@ internal class ModuleMetadataEmitter( KmConstructor(constructorStub.flags).apply { constructorStub.parameters.mapTo(valueParameters, { it.map() }) constructorStub.annotations.mapTo(annotations, { it.map() }) - uniqId = data.uniqIds.uniqIdForConstructor(constructorStub) } } @@ -224,7 +216,6 @@ internal class ModuleMetadataEmitter( data.withMappingExtensions { KlibEnumEntry( name = enumEntry.name, - uniqId = data.uniqIds.uniqIdForEnumEntry(enumEntry, data.container as ClassStub.Enum), ordinal = enumEntry.ordinal, annotations = mutableListOf(enumEntry.constant.mapToConstantAnnotation()) ) 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 deleted file mode 100644 index 81285f6b6a0..00000000000 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrUniqIdProvider.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2010-2019 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.native.interop.gen - -import kotlinx.metadata.klib.UniqId -import org.jetbrains.kotlin.backend.common.serialization.cityHash64 - -/** - * Returns stable [UniqId] for the given element of StubIr. - */ -internal class StubIrUniqIdProvider(private val context: ManglingContext) { - private val mangler: InteropMangler = KotlinLikeInteropMangler(context) - - fun createChild(suffix: String): StubIrUniqIdProvider = - StubIrUniqIdProvider(ManglingContext.Entity(suffix, context)) - - fun uniqIdForFunction(function: FunctionStub): UniqId = with(mangler) { - when (function.origin) { - 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() - } - - fun uniqIdForProperty(property: PropertyStub): UniqId = with (mangler) { - when (property.origin) { - is StubOrigin.ObjCProperty -> property.origin.property.uniqueSymbolName - is StubOrigin.Constant -> property.origin.constantDef.uniqueSymbolName - is StubOrigin.Global -> property.origin.global.uniqueSymbolName - // 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() - } - - private fun InteropMangler.uniqSymbolNameForTypeAlias(origin: StubOrigin): String? = when (origin) { - is StubOrigin.TypeDef -> origin.typedefDef.uniqueSymbolName - is StubOrigin.Enum -> origin.enum.uniqueSymbolName - is StubOrigin.VarOf -> uniqSymbolNameForTypeAlias(origin.typeOrigin)?.let { "$it#Var" } - else -> null - } - - fun uniqIdForTypeAlias(typeAlias: TypealiasStub): UniqId = with (mangler) { - uniqSymbolNameForTypeAlias(typeAlias.origin) - ?: error("Unexpected origin ${typeAlias.origin} for typealias ${typeAlias.alias.fqName}.") - }.toUniqId() - - private fun InteropMangler.uniqSymbolNameForClass(origin: StubOrigin): String? = when (origin) { - is StubOrigin.ObjCClass -> if (origin.isMeta) { - origin.clazz.metaClassUniqueSymbolName - } else { - origin.clazz.uniqueSymbolName - } - is StubOrigin.ObjCProtocol -> if (origin.isMeta) { - origin.protocol.metaClassUniqueSymbolName - } else { - origin.protocol.uniqueSymbolName - } - is StubOrigin.Struct -> origin.struct.uniqueSymbolName - is StubOrigin.Enum -> origin.enum.uniqueSymbolName - is StubOrigin.VarOf -> "${uniqSymbolNameForClass(origin.typeOrigin)}#Var" - else -> null - } - - fun uniqIdForClass(classStub: ClassStub): UniqId = with (mangler) { - when (classStub) { - is ClassStub.Simple, - is ClassStub.Enum -> uniqSymbolNameForClass(classStub.origin) - is ClassStub.Companion -> "${context.prefix}#Companion" - } ?: error("Unexpected origin ${classStub.origin} for class ${classStub.classifier.fqName}.") - }.toUniqId() - - private fun InteropMangler.uniqSymbolNameForConstructor(origin: StubOrigin): String? = when (origin) { - 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" - else -> null - } - - fun uniqIdForConstructor(constructorStub: ConstructorStub): UniqId = with (mangler) { - uniqSymbolNameForConstructor(constructorStub.origin) - ?: 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 - */ - private fun Long.markAsPublic() = this or (1L shl 63) - - private fun String.toUniqId() = UniqId(cityHash64().markAsPublic()) -} \ No newline at end of file diff --git a/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ManglingSmokeTests.kt b/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ManglingSmokeTests.kt deleted file mode 100644 index e0540d21332..00000000000 --- a/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ManglingSmokeTests.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2010-2019 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.native.interop.gen - -import org.jetbrains.kotlin.native.interop.indexer.* -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals - -private val fakeLocation = Location(HeaderId("doesntmatter")) - -private class FakeObjCClass(name: String) : ObjCClass(name) { - override val location: Location = fakeLocation - override val protocols: List = emptyList() - override val methods: List = emptyList() - override val properties: List = emptyList() - override val isForwardDeclaration: Boolean = false - override val binaryName: String? = null - override val baseClass: ObjCClass? = null -} - -private class FakeStructDecl(spelling: String) : StructDecl(spelling) { - override val def: StructDef? = null - - override val location: Location = fakeLocation -} -class ManglingSmokeTests { - - private val mangler: InteropMangler = KotlinLikeInteropMangler() - - private val nsStringClass = FakeObjCClass("NSString") - - private val int32Type = IntegerType(32, true, "int32_t") - - @Test - fun `typedef should not affect mangling`() { - - val cBoolTypedef = Typedef(TypedefDef(CBoolType, "MyBool", fakeLocation)) - - val functions = listOf( - FunctionDecl("a", listOf(Parameter("a", CBoolType, false)), CBoolType, "", false, false), - FunctionDecl("a", listOf(Parameter("b", CBoolType, false)), cBoolTypedef, "", false, false), - FunctionDecl("a", listOf(Parameter("a", cBoolTypedef, false)), CBoolType, "", false, false), - FunctionDecl("a", listOf(Parameter("a", cBoolTypedef, false)), cBoolTypedef, "", false, false) - ) - with (mangler) { - functions.reduce { left, right -> - assertEquals(left.uniqueSymbolName, right.uniqueSymbolName) - left - } - } - } - - @Test - fun `mangling should not depend on parameter names`() { - - val functionDeclarationA = FunctionDecl("a", listOf(Parameter("a", CBoolType, false)), CBoolType, "", false, false) - val functionDeclarationB = FunctionDecl("a", listOf(Parameter("b", CBoolType, false)), CBoolType, "", false, false) - with (mangler) { - assertEquals(functionDeclarationA.uniqueSymbolName, functionDeclarationB.uniqueSymbolName) - } - } - - @Test - fun `parameter type name embedded in function name`() { - val functionDeclarationA = FunctionDecl("a", listOf(Parameter("a", CharType, false)), CBoolType, "", false, false) - val functionDeclarationB = FunctionDecl("achar", emptyList(), CBoolType, "", false, false) - with (mangler) { - assertNotEquals(functionDeclarationA.uniqueSymbolName, functionDeclarationB.uniqueSymbolName) - } - } - - @Test - fun `objc methods with same names but different parameters`() { - val nsStringPtrType = ObjCObjectPointer(nsStringClass, ObjCPointer.Nullability.Nullable, listOf()) - - val methodA = ObjCMethod("name::", "v28@0:8@16i24", - listOf(Parameter("name", nsStringPtrType, false), Parameter("age", int32Type, false)), VoidType, - false, false, false, false, false, false, false) - - val methodB = ObjCMethod("name:", "v20@0:8i16", - listOf(Parameter("age", int32Type, false)), VoidType, - false, false, false, false, false, false, false) - - with (mangler) { - assertNotEquals(methodA.uniqueSymbolName, methodB.uniqueSymbolName) - } - } - - @Test - fun `objc methods with same names but different parameter names`() { - val nsStringPtrType = ObjCObjectPointer(nsStringClass, ObjCPointer.Nullability.Nullable, listOf()) - - val methodA = ObjCMethod("desc:a:", "v28@0:8@16i24", - listOf(Parameter("name", int32Type, false), Parameter("a", int32Type, false)), VoidType, - false, false, false, false, false, false, false) - - val methodB = ObjCMethod("desc:b:", "v28@0:8@16i24", - listOf(Parameter("name", int32Type, false), Parameter("b", int32Type, false)), VoidType, - false, false, false, false, false, false, false) - - with (mangler) { - assertNotEquals(methodA.uniqueSymbolName, methodB.uniqueSymbolName) - } - } - - @Test - fun `struct smoke`() { - val structA = FakeStructDecl("struct_name") - val structB = FakeStructDecl("structName") - with (mangler) { - assertNotEquals(structA.uniqueSymbolName, structB.uniqueSymbolName) - } - } - - @Test - fun `constants smoke`() { - val constant = IntegerConstantDef("DEBUG", CBoolType, 1) - val macro = WrappedMacroDef("DEBUG", CBoolType) - with (mangler) { - assertEquals(constant.uniqueSymbolName, macro.uniqueSymbolName) - } - } - - @Test - fun `different modules`() { - val moduleA = ManglingContext.Module("A") - val moduleB = ManglingContext.Module("B") - - val manglerA = KotlinLikeInteropMangler(moduleA) - val manglerB = KotlinLikeInteropMangler(moduleB) - - val declaration = WrappedMacroDef("DEBUG", CBoolType) - - assertNotEquals( - with(manglerA) { declaration.uniqueSymbolName }, - with(manglerB) { declaration.uniqueSymbolName } - ) - } - - @Test - fun `different classes`() { - val module = ManglingContext.Module("Foundation") - - val classA = ManglingContext.Entity("NSArray", module) - val classB = ManglingContext.Entity("NSMutableArray", module) - - val manglerA = KotlinLikeInteropMangler(classA) - val manglerB = KotlinLikeInteropMangler(classB) - - val getter = ObjCMethod("size", "Q16@0:8", emptyList(), IntegerType(64, false, "unsigned long"), - false, false, false, false, false, false, false) - val property = ObjCProperty("size", getter, null) - - assertNotEquals( - with(manglerA) { property.uniqueSymbolName }, - with(manglerB) { property.uniqueSymbolName } - ) - } -} \ No newline at end of file