[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:
committed by
Sergey Bogolepov
parent
d13bcef4f2
commit
18abebe387
-105
@@ -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
|
||||
}
|
||||
+1
-10
@@ -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())
|
||||
)
|
||||
|
||||
-105
@@ -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())
|
||||
}
|
||||
-162
@@ -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 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user