[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 (dde5eced87).
This commit is contained in:
Sergey Bogolepov
2020-07-14 14:17:19 +07:00
committed by Sergey Bogolepov
parent d13bcef4f2
commit 18abebe387
4 changed files with 1 additions and 382 deletions
@@ -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
}
@@ -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<TypeParameterStub> = Interner(),
val bridgeBuilderResult: BridgeBuilderResult
) {
@@ -110,7 +108,6 @@ internal class ModuleMetadataEmitter(
override fun visitClass(element: ClassStub, data: VisitingContext): List<KmClass> {
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())
)
@@ -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())
}
@@ -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<ObjCProtocol> = emptyList()
override val methods: List<ObjCMethod> = emptyList()
override val properties: List<ObjCProperty> = 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 }
)
}
}