[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
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
|
||||
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.konan.descriptors.isFromInteropLibrary
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
|
||||
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) {
|
||||
init {
|
||||
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
|
||||
|
||||
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>
|
||||
) : KotlinIrLinker(logger, builtIns, symbolTable, exportedDependencies, forwardModuleDescriptor) {
|
||||
|
||||
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinder(currentModule)
|
||||
|
||||
override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) =
|
||||
moduleDescriptor.konanLibrary!!.irDeclaration(idSigIndex, fileIndex)
|
||||
|
||||
@@ -93,6 +95,9 @@ class KonanIrLinker(
|
||||
}
|
||||
|
||||
override fun resolvePlatformDescriptor(idSig: IdSignature): DeclarationDescriptor? {
|
||||
if (idSig.isInteropSignature()) {
|
||||
return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig)
|
||||
}
|
||||
if (!idSig.isForwardDeclarationSignature()) return null
|
||||
|
||||
val fwdModule = forwardModuleDescriptor ?: error("Forward declaration module should not be null")
|
||||
|
||||
Reference in New Issue
Block a user