KLIB reader: uniform API for obtaining module descriptors from Kotlin/Native libraries (#1932)

This commit is contained in:
Dmitriy Dolovov
2018-08-25 18:24:07 +03:00
committed by GitHub
parent d5142220d2
commit dcb423a3ce
40 changed files with 682 additions and 447 deletions
-40
View File
@@ -1,40 +0,0 @@
buildscript {
ext.rootBuildDirectory = file('../..')
apply from: "$rootBuildDirectory/gradle/loadRootProperties.gradle"
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
}
apply plugin: 'kotlin'
group = 'org.jetbrains.kotlin'
version = konanVersion
repositories {
mavenCentral()
maven {
url kotlinCompilerRepo
}
}
sourceSets {
main.kotlin {
srcDir 'src/main/kotlin'
}
}
jar {
archiveName = "${project.name}.jar"
}
repositories {
maven {
url buildKotlinCompilerRepo
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
compile "org.jetbrains.kotlin:kotlin-compiler:$kotlinVersion"
}
@@ -1 +0,0 @@
rootProject.name = "konan.descriptors"
@@ -1,38 +0,0 @@
package org.jetbrains.kotlin.descriptors.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.StorageManager
fun createKonanModuleDescriptor(
name: Name,
storageManager: StorageManager,
origin: KonanModuleOrigin
): ModuleDescriptorImpl {
val builtIns = KonanBuiltIns(storageManager)
val moduleDescriptor = createKonanModuleDescriptor(name, storageManager, builtIns, origin)
builtIns.builtInsModule = moduleDescriptor
// It is mostly correct because any module should depend on stdlib.
return moduleDescriptor
}
fun createKonanModuleDescriptor(
name: Name,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
origin: KonanModuleOrigin
) = ModuleDescriptorImpl(
name, storageManager, builtIns,
capabilities = mapOf(KonanModuleOrigin.CAPABILITY to origin)
)
private val STDLIB_MODULE_NAME = Name.special("<$KONAN_STDLIB_NAME>")
fun ModuleDescriptor.isKonanStdlib() = name == STDLIB_MODULE_NAME
@@ -1,113 +0,0 @@
package org.jetbrains.kotlin.descriptors.konan.interop
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.SyntheticModulesOrigin
import org.jetbrains.kotlin.descriptors.konan.createKonanModuleDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
/**
* Creates module which "contains" forward declarations.
* Note: this module should be unique per compilation and should always be the last dependency of any module.
*/
fun createForwardDeclarationsModule(builtIns: KotlinBuiltIns, storageManager: StorageManager): ModuleDescriptorImpl {
val module = createKonanModuleDescriptor(
Name.special("<forward declarations>"),
storageManager,
builtIns,
origin = SyntheticModulesOrigin
)
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind = ClassKind.CLASS) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind
)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(InteropFqNames.cNamesStructs, "COpaque"),
createPackage(InteropFqNames.objCNamesClasses, "ObjCObjectBase"),
createPackage(InteropFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
module.initialize(packageFragmentProvider)
module.setDependencies(module)
return module
}
/**
* Package fragment which creates descriptors for forward declarations on demand.
*/
private class ForwardDeclarationsPackageFragmentDescriptor(
storageManager: StorageManager,
module: ModuleDescriptor, fqName: FqName, supertypeName: Name, classKind: ClassKind
) : PackageFragmentDescriptorImpl(module, fqName) {
private val memberScope = object : MemberScopeImpl() {
private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
private val supertype by storageManager.createLazyValue {
val descriptor = builtIns.builtInsModule.getPackage(InteropFqNames.packageName)
.memberScope
.getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
descriptor.defaultType
}
private fun createDeclaration(name: Name): ClassDescriptor {
return ClassDescriptorImpl(
this@ForwardDeclarationsPackageFragmentDescriptor,
name, Modality.FINAL, classKind,
listOf(supertype), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS
).apply {
this.initialize(MemberScope.Empty, emptySet(), null)
}
}
override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
override fun printScopeStructure(p: Printer) {
p.println(this::class.java.simpleName, "{}")
}
}
override fun getMemberScope(): MemberScope = memberScope
}
object InteropFqNames {
const val cPointerName = "CPointer"
const val nativePointedName = "NativePointed"
val packageName = FqName("kotlinx.cinterop")
val cPointer = packageName.child(Name.identifier(cPointerName)).toUnsafe()
val nativePointed = packageName.child(Name.identifier(nativePointedName)).toUnsafe()
val cNames = FqName("cnames")
val cNamesStructs = cNames.child(Name.identifier("structs"))
val objCNames = FqName("objcnames")
val objCNamesClasses = objCNames.child(Name.identifier("classes"))
val objCNamesProtocols = objCNames.child(Name.identifier("protocols"))
}
+3 -1
View File
@@ -34,6 +34,8 @@ repositories {
}
dependencies {
compile "org.jetbrains.kotlin:konan.descriptors:$konanVersion"
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
compile "org.jetbrains.kotlin:kotlin-compiler:$kotlinVersion"
compile "org.jetbrains.kotlin:konan.metadata:$konanVersion"
}
@@ -9,4 +9,3 @@ class KonanBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageMana
override fun getSuspendFunction(parameterCount: Int) =
getBuiltInClassByName(Name.identifier("SuspendFunction$parameterCount"))
}
@@ -0,0 +1,32 @@
package org.jetbrains.kotlin.descriptors.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.StorageManager
interface KonanModuleDescriptorFactory {
/**
* Base method for creation of any Kotlin/Native [ModuleDescriptor].
*/
fun createDescriptor(
name: Name,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
origin: KonanModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
): ModuleDescriptorImpl
/**
* Please use this method with care: As far as it creates an instance of [KotlinBuiltIns] it should be
* normally used for creation of the very first (e.g. "stdlib") module in the set of created modules.
*/
fun createDescriptorAndNewBuiltIns(
name: Name,
storageManager: StorageManager,
origin: KonanModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
): ModuleDescriptorImpl
}
@@ -0,0 +1,9 @@
package org.jetbrains.kotlin.descriptors.konan
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.name.Name
private val STDLIB_MODULE_NAME = Name.special("<$KONAN_STDLIB_NAME>")
fun ModuleDescriptor.isKonanStdlib() = name == STDLIB_MODULE_NAME
@@ -1,6 +1,7 @@
package org.jetbrains.kotlin.descriptors.konan
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.konan.library.KonanLibrary
sealed class KonanModuleOrigin {
@@ -11,8 +12,7 @@ sealed class KonanModuleOrigin {
sealed class CompiledKonanModuleOrigin: KonanModuleOrigin()
// FIXME(ddol): replace `Any` by `KonanLibrary` when ready
class DeserializedKonanModuleOrigin(val library: Any) : CompiledKonanModuleOrigin()
class DeserializedKonanModuleOrigin(val library: KonanLibrary) : CompiledKonanModuleOrigin()
object CurrentKonanModuleOrigin: CompiledKonanModuleOrigin()
@@ -0,0 +1,40 @@
package org.jetbrains.kotlin.descriptors.konan.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.StorageManager
internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory {
override fun createDescriptor(
name: Name,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
origin: KonanModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
) = ModuleDescriptorImpl(
name,
storageManager,
builtIns,
capabilities = customCapabilities + mapOf(KonanModuleOrigin.CAPABILITY to origin))
override fun createDescriptorAndNewBuiltIns(
name: Name,
storageManager: StorageManager,
origin: KonanModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
): ModuleDescriptorImpl {
val builtIns = KonanBuiltIns(storageManager)
val moduleDescriptor = createDescriptor(name, storageManager, builtIns, origin, customCapabilities)
builtIns.builtInsModule = moduleDescriptor
return moduleDescriptor
}
}
@@ -22,15 +22,15 @@ interface KonanLibrary {
val libraryName: String
val libraryFile: File
// whether this library is default (provided by Kotlin/Native distribution)
// Whether this library is default (provided by Kotlin/Native distribution)?
val isDefault: Boolean
// properties:
// Properties:
val manifestProperties: Properties
val abiVersion: String
val linkerOpts: List<String>
// paths:
// Paths:
val bitcodePaths: List<String>
val includedPaths: List<String>
@@ -3,7 +3,9 @@ package org.jetbrains.kotlin.konan.library
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.KonanTarget
// This scheme describes the Kotlin/Native Library (klib) layout.
/**
* This scheme describes the Kotlin/Native Library (KLIB) layout.
*/
interface KonanLibraryLayout {
val libraryName: String
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
fun File.unpackZippedKonanLibraryTo(newDir: File) {
// first run validity checks for the given KLIB file
// First, run validity checks for the given KLIB file.
zippedKonanLibraryChecks(this)
if (newDir.exists) {
@@ -33,10 +33,10 @@ private class UnzippedKonanLibraryLayout(override val libDir: File, override val
override val libraryName = libDir.path
}
// This class automatically extracts pieces of
// the library on first access. Use it if you need
// to pass extracted files to an external tool.
// Otherwise, stick to ZippedKonanLibrary.
/**
* This class automatically extracts pieces of the library on first access. Use it if you need
* to pass extracted files to an external tool. Otherwise, stick to [ZippedKonanLibraryLayout].
*/
private class FileExtractor(zippedLibraryLayout: KonanLibraryLayout): KonanLibraryLayout by zippedLibraryLayout {
override val manifestFile: File by lazy { extract(super.manifestFile) }
@@ -13,15 +13,15 @@ interface PackageAccessedHandler {
*/
interface KonanResolvedLibrary: PackageAccessedHandler {
// the library itself
// The library itself.
val library: KonanLibrary
// dependencies on other libraries
// Dependencies on other libraries.
val resolvedDependencies: List<KonanResolvedLibrary>
// if it's needed to linker
// Whether it is needed to linker.
val isNeededForLink: Boolean
// is provided by the distribution
// Is provided by the distribution?
val isDefault: Boolean
}
@@ -73,8 +73,8 @@ internal class KonanLibraryResolverImpl(
val rootLibraries = this.map { KonanResolvedLibraryImpl(it) }
// as far as the list of root libraries is known from the very beginning, the result can be
// constructed from the very beginning as well
// As far as the list of root libraries is known from the very beginning, the result can be
// constructed from the very beginning as well.
val result = KonanLibraryResolverResultImpl(rootLibraries)
val cache = mutableMapOf<File, KonanResolvedLibrary>()
@@ -3,14 +3,14 @@ package org.jetbrains.kotlin.konan.library.resolver.impl
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.konan.emptyPackages
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
internal class KonanResolvedLibraryImpl(
override val library: KonanLibrary
): KonanResolvedLibrary {
private val _resolvedDependencies = mutableListOf<KonanResolvedLibrary>()
private val _emptyPackages by lazy { emptyPackages(library.moduleHeaderData) }
private val _emptyPackages by lazy { parseModuleHeader(library.moduleHeaderData).emptyPackageList }
override val resolvedDependencies: List<KonanResolvedLibrary>
get() = _resolvedDependencies
@@ -0,0 +1,50 @@
package org.jetbrains.kotlin.konan.utils
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.descriptors.konan.impl.KonanModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedModuleDescriptorFactory
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptorsFactory
import org.jetbrains.kotlin.serialization.konan.impl.KonanDeserializedModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.serialization.konan.impl.KonanDeserializedPackageFragmentsFactoryImpl
import org.jetbrains.kotlin.serialization.konan.impl.KonanResolvedModuleDescriptorsFactoryImpl
/**
* The default Kotlin/Native factories.
*/
object KonanFactories {
/**
* The default [KonanModuleDescriptorFactory] factory instance.
*/
val DefaultDescriptorFactory: KonanModuleDescriptorFactory = KonanModuleDescriptorFactoryImpl
/**
* The default [KonanDeserializedPackageFragmentsFactory] factory instance.
*/
val DefaultPackageFragmentsFactory: KonanDeserializedPackageFragmentsFactory =
KonanDeserializedPackageFragmentsFactoryImpl
/**
* The default [KonanDeserializedModuleDescriptorFactory] factory instance.
*/
val DefaultDeserializedDescriptorFactory: KonanDeserializedModuleDescriptorFactory =
createDefaultKonanDeserializedModuleDescriptorFactory(
DefaultDescriptorFactory, DefaultPackageFragmentsFactory)
/**
* The default [KonanResolvedModuleDescriptorsFactory] factory instance.
*/
val DefaultResolvedDescriptorsFactory: KonanResolvedModuleDescriptorsFactory =
createDefaultKonanResolvedModuleDescriptorsFactory(DefaultDeserializedDescriptorFactory)
fun createDefaultKonanDeserializedModuleDescriptorFactory(
descriptorFactory: KonanModuleDescriptorFactory,
packageFragmentsFactory: KonanDeserializedPackageFragmentsFactory
): KonanDeserializedModuleDescriptorFactory =
KonanDeserializedModuleDescriptorFactoryImpl(descriptorFactory, packageFragmentsFactory)
fun createDefaultKonanResolvedModuleDescriptorsFactory(
moduleDescriptorFactory: KonanDeserializedModuleDescriptorFactory
): KonanResolvedModuleDescriptorsFactory = KonanResolvedModuleDescriptorsFactoryImpl(moduleDescriptorFactory)
}
@@ -2,10 +2,8 @@ package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
fun parsePackageFragment(packageData: ByteArray): KonanProtoBuf.LinkDataPackageFragment =
KonanProtoBuf.LinkDataPackageFragment.parseFrom(packageData, KonanSerializerProtocol.extensionRegistry)
fun parsePackageFragment(packageMetadata: ByteArray): KonanProtoBuf.LinkDataPackageFragment =
KonanProtoBuf.LinkDataPackageFragment.parseFrom(packageMetadata, KonanSerializerProtocol.extensionRegistry)
fun parseModuleHeader(libraryData: ByteArray): KonanProtoBuf.LinkDataLibrary =
KonanProtoBuf.LinkDataLibrary.parseFrom(libraryData, KonanSerializerProtocol.extensionRegistry)
fun emptyPackages(libraryData: ByteArray) = parseModuleHeader(libraryData).emptyPackageList
fun parseModuleHeader(libraryMetadata: ByteArray): KonanProtoBuf.LinkDataLibrary =
KonanProtoBuf.LinkDataLibrary.parseFrom(libraryMetadata, KonanSerializerProtocol.extensionRegistry)
@@ -0,0 +1,35 @@
package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
interface KonanDeserializedModuleDescriptorFactory {
val descriptorFactory: KonanModuleDescriptorFactory
val packageFragmentsFactory: KonanDeserializedPackageFragmentsFactory
fun createDescriptor(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
packageAccessedHandler: PackageAccessedHandler? = null
): ModuleDescriptorImpl
/**
* Please use this method with care: As far as it creates an instance of [KotlinBuiltIns] it should be
* normally used for creation of the very first (e.g. "stdlib") module in the set of created modules.
*/
fun createDescriptorAndNewBuiltIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
packageAccessedHandler: PackageAccessedHandler? = null
): ModuleDescriptorImpl
}
@@ -0,0 +1,24 @@
package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.storage.StorageManager
interface KonanDeserializedPackageFragmentsFactory {
fun createDeserializedPackageFragments(
library: KonanLibrary,
packageFragmentNames: List<String>,
moduleDescriptor: ModuleDescriptor,
packageAccessedHandler: PackageAccessedHandler?,
storageManager: StorageManager
): List<KonanPackageFragment>
fun createSyntheticPackageFragments(
library: KonanLibrary,
deserializedPackageFragments: List<KonanPackageFragment>,
moduleDescriptor: ModuleDescriptor
): List<PackageFragmentDescriptor>
}
@@ -1,143 +0,0 @@
package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.createKonanModuleDescriptor
import org.jetbrains.kotlin.descriptors.konan.interop.InteropFqNames
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.exportForwardDeclarations
import org.jetbrains.kotlin.konan.library.isInterop
import org.jetbrains.kotlin.konan.library.packageFqName
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
// FIXME(ddol): this is a temporary solution, to be refactored into some global resolution context
interface KonanModuleDescriptorFactory {
fun createModuleDescriptor(
library: KonanLibrary,
specifics: LanguageVersionSettings,
packageAccessedHandler: PackageAccessedHandler? = null,
storageManager: StorageManager = LockBasedStorageManager()
): ModuleDescriptor
}
object DefaultKonanModuleDescriptorFactory: KonanModuleDescriptorFactory {
override fun createModuleDescriptor(
library: KonanLibrary,
specifics: LanguageVersionSettings,
packageAccessedHandler: PackageAccessedHandler?,
storageManager: StorageManager
): ModuleDescriptorImpl {
val libraryProto = parseModuleHeader(library.moduleHeaderData)
val moduleName = libraryProto.moduleName
val moduleDescriptor = createKonanModuleDescriptor(
Name.special(moduleName),
storageManager,
origin = DeserializedKonanModuleOrigin(library)
)
val deserializationConfiguration = CompilerDeserializationConfiguration(specifics)
val provider = createPackageFragmentProvider(
library,
packageAccessedHandler,
libraryProto.packageFragmentNameList,
storageManager,
moduleDescriptor,
deserializationConfiguration)
moduleDescriptor.initialize(provider)
return moduleDescriptor
}
private fun createPackageFragmentProvider(
library: KonanLibrary,
packageAccessedHandler: PackageAccessedHandler?,
fragmentNames: List<String>,
storageManager: StorageManager,
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration
): PackageFragmentProvider {
val deserializedPackageFragments = fragmentNames.map{
KonanPackageFragment(FqName(it), library, packageAccessedHandler, storageManager, moduleDescriptor)
}
val syntheticPackageFragments = getSyntheticPackageFragments(
library,
moduleDescriptor,
deserializedPackageFragments)
val provider = PackageFragmentProviderImpl(deserializedPackageFragments + syntheticPackageFragments)
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(
moduleDescriptor,
notFoundClasses,
KonanSerializerProtocol)
val components = DeserializationComponents(
storageManager,
moduleDescriptor,
configuration,
DeserializedClassDataFinder(provider),
annotationAndConstantLoader,
provider,
LocalClassifierTypeSettings.Default,
ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING,
NullFlexibleTypeDeserializer,
emptyList(),
notFoundClasses,
ContractDeserializer.DEFAULT,
extensionRegistryLite = KonanSerializerProtocol.extensionRegistry)
for (packageFragment in deserializedPackageFragments) {
packageFragment.initialize(components)
}
return provider
}
private fun getSyntheticPackageFragments(
library: KonanLibrary,
moduleDescriptor: ModuleDescriptor,
konanPackageFragments: List<KonanPackageFragment>
): List<PackageFragmentDescriptor> {
if (!library.isInterop) return emptyList()
val packageFqName = library.packageFqName
?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified")
val exportForwardDeclarations = library.exportForwardDeclarations
val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName }
val result = mutableListOf<PackageFragmentDescriptor>()
// Allow references to forwarding declarations to be resolved into classifiers declared in this library:
listOf(InteropFqNames.cNamesStructs, InteropFqNames.objCNamesClasses, InteropFqNames.objCNamesProtocols).mapTo(result) { fqName ->
ClassifierAliasingPackageFragmentDescriptor(interopPackageFragments, moduleDescriptor, fqName)
}
// TODO: use separate namespaces for structs, enums, Objective-C protocols etc.
result.add(ExportedForwardDeclarationsPackageFragmentDescriptor(moduleDescriptor, packageFqName, exportForwardDeclarations))
return result
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolveResult
import org.jetbrains.kotlin.storage.StorageManager
interface KonanResolvedModuleDescriptorsFactory {
val moduleDescriptorFactory: KonanDeserializedModuleDescriptorFactory
fun createResolved(
resolvedLibraries: KonanLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KonanLibrary, ModuleDescriptorImpl) -> Unit)? = null
): KonanResolvedModuleDescriptors
}
class KonanResolvedModuleDescriptors(
val resolvedDescriptors: List<ModuleDescriptorImpl>,
/**
* This is a module which "contains" forward declarations.
* Note: this module should be unique per compilation and should always be the last dependency of any module.
*/
val forwardDeclarationsModule: ModuleDescriptorImpl
)
@@ -0,0 +1,120 @@
package org.jetbrains.kotlin.serialization.konan.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.PackageFragmentProviderImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.konan.*
import org.jetbrains.kotlin.storage.StorageManager
internal class KonanDeserializedModuleDescriptorFactoryImpl(
override val descriptorFactory: KonanModuleDescriptorFactory,
override val packageFragmentsFactory: KonanDeserializedPackageFragmentsFactory
): KonanDeserializedModuleDescriptorFactory {
override fun createDescriptor(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
packageAccessedHandler: PackageAccessedHandler?
) = createDescriptorOptionalBuiltIns(library, languageVersionSettings, storageManager, builtIns, packageAccessedHandler)
override fun createDescriptorAndNewBuiltIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
packageAccessedHandler: PackageAccessedHandler?
) = createDescriptorOptionalBuiltIns(library, languageVersionSettings, storageManager, null, packageAccessedHandler)
private fun createDescriptorOptionalBuiltIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessedHandler: PackageAccessedHandler?
): ModuleDescriptorImpl {
val libraryProto = parseModuleHeader(library.moduleHeaderData)
val moduleName = Name.special(libraryProto.moduleName)
val moduleOrigin = DeserializedKonanModuleOrigin(library)
val moduleDescriptor = if (builtIns != null )
descriptorFactory.createDescriptor(moduleName, storageManager, builtIns, moduleOrigin)
else
descriptorFactory.createDescriptorAndNewBuiltIns(moduleName, storageManager, moduleOrigin)
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
val provider = createPackageFragmentProvider(
library,
packageAccessedHandler,
libraryProto.packageFragmentNameList,
storageManager,
moduleDescriptor,
deserializationConfiguration)
moduleDescriptor.initialize(provider)
return moduleDescriptor
}
private fun createPackageFragmentProvider(
library: KonanLibrary,
packageAccessedHandler: PackageAccessedHandler?,
packageFragmentNames: List<String>,
storageManager: StorageManager,
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration
): PackageFragmentProvider {
val deserializedPackageFragments = packageFragmentsFactory.createDeserializedPackageFragments(
library, packageFragmentNames, moduleDescriptor, packageAccessedHandler, storageManager)
val syntheticPackageFragments = packageFragmentsFactory.createSyntheticPackageFragments(
library, deserializedPackageFragments, moduleDescriptor)
val provider = PackageFragmentProviderImpl(deserializedPackageFragments + syntheticPackageFragments)
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(
moduleDescriptor,
notFoundClasses,
KonanSerializerProtocol)
val components = DeserializationComponents(
storageManager,
moduleDescriptor,
configuration,
DeserializedClassDataFinder(provider),
annotationAndConstantLoader,
provider,
LocalClassifierTypeSettings.Default,
ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING,
NullFlexibleTypeDeserializer,
emptyList(),
notFoundClasses,
ContractDeserializer.DEFAULT,
extensionRegistryLite = KonanSerializerProtocol.extensionRegistry)
for (packageFragment in deserializedPackageFragments) {
packageFragment.initialize(components)
}
return provider
}
}
@@ -1,16 +1,63 @@
package org.jetbrains.kotlin.serialization.konan
package org.jetbrains.kotlin.serialization.konan.impl
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.exportForwardDeclarations
import org.jetbrains.kotlin.konan.library.isInterop
import org.jetbrains.kotlin.konan.library.packageFqName
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
internal object KonanDeserializedPackageFragmentsFactoryImpl: KonanDeserializedPackageFragmentsFactory {
override fun createDeserializedPackageFragments(
library: KonanLibrary,
packageFragmentNames: List<String>,
moduleDescriptor: ModuleDescriptor,
packageAccessedHandler: PackageAccessedHandler?,
storageManager: StorageManager
) = packageFragmentNames.map {
KonanPackageFragment(FqName(it), library, packageAccessedHandler, storageManager, moduleDescriptor)
}
override fun createSyntheticPackageFragments(
library: KonanLibrary,
deserializedPackageFragments: List<KonanPackageFragment>,
moduleDescriptor: ModuleDescriptor
): List<PackageFragmentDescriptor> {
if (!library.isInterop) return emptyList()
val mainPackageFqName = library.packageFqName
?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified")
val exportForwardDeclarations = library.exportForwardDeclarations
val aliasedPackageFragments = deserializedPackageFragments.filter { it.fqName == mainPackageFqName }
val result = mutableListOf<PackageFragmentDescriptor>()
listOf(ForwardDeclarationsFqNames.cNamesStructs, ForwardDeclarationsFqNames.objCNamesClasses, ForwardDeclarationsFqNames.objCNamesProtocols).mapTo(result) { fqName ->
ClassifierAliasingPackageFragmentDescriptor(aliasedPackageFragments, moduleDescriptor, fqName)
}
result.add(ExportedForwardDeclarationsPackageFragmentDescriptor(moduleDescriptor, mainPackageFqName, exportForwardDeclarations))
return result
}
}
/**
* The package fragment to export forward declarations from interop package namespace, i.e.
* redirect "$pkg.$name" to e.g. "cnames.structs.$name".
@@ -0,0 +1,181 @@
package org.jetbrains.kotlin.serialization.konan.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.SyntheticModulesOrigin
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolveResult
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.konan.util.profile
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedModuleDescriptorFactory
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptors
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptorsFactory
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
class KonanResolvedModuleDescriptorsFactoryImpl(
override val moduleDescriptorFactory: KonanDeserializedModuleDescriptorFactory
): KonanResolvedModuleDescriptorsFactory {
override fun createResolved(
resolvedLibraries: KonanLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KonanLibrary, ModuleDescriptorImpl) -> Unit)?
): KonanResolvedModuleDescriptors {
val moduleDescriptors = mutableListOf<ModuleDescriptorImpl>()
@Suppress("NAME_SHADOWING")
var builtIns = builtIns
// Build module descriptors.
resolvedLibraries.forEach { library, packageAccessedHandler ->
profile("Loading ${library.libraryName}") {
// MutableModuleContext needs ModuleDescriptorImpl, rather than ModuleDescriptor.
val moduleDescriptor = createDescriptorOptionalBuiltsIns(
library, languageVersionSettings, storageManager, builtIns, packageAccessedHandler)
builtIns = moduleDescriptor.builtIns
moduleDescriptors.add(moduleDescriptor)
customAction?.invoke(library, moduleDescriptor)
}
}
val forwardDeclarationsModule = createForwardDeclarationsModule(builtIns, storageManager)
// Set inter-dependencies between module descriptors, add forwarding declarations module.
for (module in moduleDescriptors) {
// Yes, just to all of them.
module.setDependencies(moduleDescriptors + forwardDeclarationsModule)
}
return KonanResolvedModuleDescriptors(moduleDescriptors, forwardDeclarationsModule)
}
private fun createForwardDeclarationsModule(
builtIns: KotlinBuiltIns?,
storageManager: StorageManager): ModuleDescriptorImpl {
val name = Name.special("<forward declarations>")
val module = createDescriptorOptionalBuiltsIns(name, storageManager, builtIns, SyntheticModulesOrigin)
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
module.initialize(packageFragmentProvider)
module.setDependencies(module)
return module
}
private fun createDescriptorOptionalBuiltsIns(
name: Name,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
moduleOrigin: KonanModuleOrigin
) = if (builtIns != null)
moduleDescriptorFactory.descriptorFactory.createDescriptor(name, storageManager, builtIns, moduleOrigin)
else
moduleDescriptorFactory.descriptorFactory.createDescriptorAndNewBuiltIns(name, storageManager, moduleOrigin)
private fun createDescriptorOptionalBuiltsIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessedHandler: PackageAccessedHandler?
) = if (builtIns != null)
moduleDescriptorFactory.createDescriptor(library, languageVersionSettings, storageManager, builtIns, packageAccessedHandler)
else
moduleDescriptorFactory.createDescriptorAndNewBuiltIns(library, languageVersionSettings, storageManager, packageAccessedHandler)
}
/**
* Package fragment which creates descriptors for forward declarations on demand.
*/
private class ForwardDeclarationsPackageFragmentDescriptor(
storageManager: StorageManager,
module: ModuleDescriptor,
fqName: FqName,
supertypeName: Name,
classKind: ClassKind
) : PackageFragmentDescriptorImpl(module, fqName) {
private val memberScope = object : MemberScopeImpl() {
private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
private val supertype by storageManager.createLazyValue {
val descriptor = builtIns.builtInsModule.getPackage(ForwardDeclarationsFqNames.packageName)
.memberScope
.getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
descriptor.defaultType
}
private fun createDeclaration(name: Name): ClassDescriptor {
return ClassDescriptorImpl(
this@ForwardDeclarationsPackageFragmentDescriptor,
name,
Modality.FINAL,
classKind,
listOf(supertype),
SourceElement.NO_SOURCE,
false,
LockBasedStorageManager.NO_LOCKS
).apply {
this.initialize(MemberScope.Empty, emptySet(), null)
}
}
override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
override fun printScopeStructure(p: Printer) {
p.println(this::class.java.simpleName, "{}")
}
}
override fun getMemberScope(): MemberScope = memberScope
}
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
internal object ForwardDeclarationsFqNames {
val packageName = FqName("kotlinx.cinterop")
val cNames = FqName("cnames")
val cNamesStructs = cNames.child(Name.identifier("structs"))
val objCNames = FqName("objcnames")
val objCNamesClasses = objCNames.child(Name.identifier("classes"))
val objCNamesProtocols = objCNames.child(Name.identifier("protocols"))
}