[Interop][Linker] Full support for metadata-only interop
Add support for IdSignatures to interop declarations from metadata-only libraries.
This commit is contained in:
committed by
Sergey Bogolepov
parent
ac5fd80cb4
commit
dde5eced87
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.backend.konan.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
|
|
||||||
|
// The code here is intentionally copy-pasted from DeclarationStubGenerator with
|
||||||
|
// minor changes.
|
||||||
|
// "Find descriptor by IdSignature" task appears to be common and should be unified later.
|
||||||
|
class DescriptorByIdSignatureFinder(
|
||||||
|
private val moduleDescriptor: ModuleDescriptor
|
||||||
|
) {
|
||||||
|
fun findDescriptorBySignature(signature: IdSignature): DeclarationDescriptor? = when (signature) {
|
||||||
|
is IdSignature.AccessorSignature -> findDescriptorForAccessorSignature(signature)
|
||||||
|
is IdSignature.PublicSignature -> findDescriptorForPublicSignature(signature)
|
||||||
|
else -> error("only PublicSignature or AccessorSignature should reach this point, got $signature")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? {
|
||||||
|
val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor
|
||||||
|
?: return null
|
||||||
|
return propertyDescriptor.accessors.singleOrNull {
|
||||||
|
it.name == signature.accessorSignature.declarationFqn.shortName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? {
|
||||||
|
val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName())
|
||||||
|
val pathSegments = signature.declarationFqn.pathSegments()
|
||||||
|
val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() }
|
||||||
|
.filter { it.name == pathSegments.first() }
|
||||||
|
val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
|
||||||
|
acc.flatMap { container ->
|
||||||
|
val classDescriptor = container as? ClassDescriptor
|
||||||
|
?: return@flatMap emptyList<DeclarationDescriptor>()
|
||||||
|
val nextStepCandidates = classDescriptor.constructors +
|
||||||
|
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } +
|
||||||
|
// Static scope is required only for Enum.values() and Enum.valueOf().
|
||||||
|
classDescriptor.staticScope.getContributedDescriptors { name -> name == current }
|
||||||
|
nextStepCandidates.filter { it.name == current }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (candidates.size) {
|
||||||
|
1 -> candidates.first()
|
||||||
|
else -> {
|
||||||
|
findDescriptorByHash(candidates, signature.id)
|
||||||
|
?: error("No descriptor found for $signature")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findDescriptorByHash(candidates: List<DeclarationDescriptor>, id: Long?): DeclarationDescriptor? =
|
||||||
|
candidates.firstOrNull { candidate ->
|
||||||
|
if (id == null) {
|
||||||
|
// We don't compute id for typealiases and classes.
|
||||||
|
candidate is ClassDescriptor || candidate is TypeAliasDescriptor
|
||||||
|
} else {
|
||||||
|
val candidateHash = with(KonanManglerDesc) { candidate.signatureMangle }
|
||||||
|
candidateHash == id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -1,12 +1,31 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.serialization
|
package org.jetbrains.kotlin.backend.konan.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable
|
import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.signature.DescToIrIdSignatureComputer
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
|
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
class KonanGlobalDeclarationTable(signatureSerializer: IdSignatureSerializer, builtIns: IrBuiltIns) : GlobalDeclarationTable(signatureSerializer, KonanManglerIr) {
|
class KonanGlobalDeclarationTable(signatureSerializer: IdSignatureSerializer, builtIns: IrBuiltIns) : GlobalDeclarationTable(signatureSerializer, KonanManglerIr) {
|
||||||
init {
|
init {
|
||||||
loadKnownBuiltins(builtIns)
|
loadKnownBuiltins(builtIns)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KonanDeclarationTable(
|
||||||
|
globalDeclarationTable: GlobalDeclarationTable
|
||||||
|
) : DeclarationTable(globalDeclarationTable) {
|
||||||
|
|
||||||
|
private val signatureIdComposer = DescToIrIdSignatureComputer(KonanIdSignaturer(KonanManglerDesc))
|
||||||
|
|
||||||
|
// TODO: We should get rid of this extension point in favor of proper support in IR-based mangler.
|
||||||
|
override fun tryComputeBackendSpecificSignature(declaration: IrDeclaration): IdSignature? =
|
||||||
|
if (declaration.descriptor.module.isFromInteropLibrary()) {
|
||||||
|
signatureIdComposer.computeSignature(declaration)
|
||||||
|
} else null
|
||||||
}
|
}
|
||||||
+1
-1
@@ -29,5 +29,5 @@ class KonanIrModuleSerializer(
|
|||||||
file.fileEntry.name != IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName
|
file.fileEntry.name != IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName
|
||||||
|
|
||||||
override fun createSerializerForFile(file: IrFile): KonanIrFileSerializer =
|
override fun createSerializerForFile(file: IrFile): KonanIrFileSerializer =
|
||||||
KonanIrFileSerializer(logger, DeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects)
|
KonanIrFileSerializer(logger, KonanDeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -48,6 +48,8 @@ class KonanIrLinker(
|
|||||||
exportedDependencies: List<ModuleDescriptor>
|
exportedDependencies: List<ModuleDescriptor>
|
||||||
) : KotlinIrLinker(logger, builtIns, symbolTable, exportedDependencies, forwardModuleDescriptor) {
|
) : KotlinIrLinker(logger, builtIns, symbolTable, exportedDependencies, forwardModuleDescriptor) {
|
||||||
|
|
||||||
|
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinder(currentModule)
|
||||||
|
|
||||||
override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) =
|
override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) =
|
||||||
moduleDescriptor.konanLibrary!!.irDeclaration(idSigIndex, fileIndex)
|
moduleDescriptor.konanLibrary!!.irDeclaration(idSigIndex, fileIndex)
|
||||||
|
|
||||||
@@ -93,6 +95,9 @@ class KonanIrLinker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun resolvePlatformDescriptor(idSig: IdSignature): DeclarationDescriptor? {
|
override fun resolvePlatformDescriptor(idSig: IdSignature): DeclarationDescriptor? {
|
||||||
|
if (idSig.isInteropSignature()) {
|
||||||
|
return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig)
|
||||||
|
}
|
||||||
if (!idSig.isForwardDeclarationSignature()) return null
|
if (!idSig.isForwardDeclarationSignature()) return null
|
||||||
|
|
||||||
val fwdModule = forwardModuleDescriptor ?: error("Forward declaration module should not be null")
|
val fwdModule = forwardModuleDescriptor ?: error("Forward declaration module should not be null")
|
||||||
|
|||||||
Reference in New Issue
Block a user