KLIB reader: better isolation of implementation details (#1917)
KLIB reader: - better isolation of implementation details - rename entities closer to their meaning: KonanLibrary -> KonanLibraryLayout, KonanLibraryReader -> KonanLibrary
This commit is contained in:
@@ -138,8 +138,6 @@ dependencies {
|
||||
compilerCompile kotlinNativeInterop['llvm'].configuration
|
||||
compilerCompile kotlinNativeInterop['hash'].configuration
|
||||
compilerCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
compilerCompile "org.jetbrains.kotlin:konan.descriptors:$konanVersion"
|
||||
compilerCompile "org.jetbrains.kotlin:konan.metadata:$konanVersion"
|
||||
compilerCompile "org.jetbrains.kotlin:konan.serializer:$konanVersion"
|
||||
|
||||
cli_bcCompile kotlinCompilerModule
|
||||
|
||||
+7
-5
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.konan.interop.createForwardDeclarationsModule
|
||||
import org.jetbrains.kotlin.konan.TempFiles
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.profile
|
||||
@@ -93,8 +93,10 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES)
|
||||
private val resolver = defaultResolver(repositories, target, distribution)
|
||||
|
||||
internal val immediateLibraries: List<KonanLibraryReader> by lazy {
|
||||
val result = resolver.resolveImmediateLibraries(libraryNames, target,
|
||||
internal val immediateLibraries: List<KonanLibrary> by lazy {
|
||||
val result = resolver.resolveImmediateLibraries(
|
||||
libraryNames,
|
||||
target,
|
||||
currentAbiVersion,
|
||||
configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
|
||||
configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS),
|
||||
@@ -103,7 +105,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
result
|
||||
}
|
||||
|
||||
fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List<KonanLibraryReader> {
|
||||
fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List<KonanLibrary> {
|
||||
if (moduleDescriptor == null) error("purgeUnneeded() only works correctly after resolve is over, and we have successfully marked package files as needed or not needed.")
|
||||
|
||||
return immediateLibraries.purgeUnneeded(this).withResolvedDependencies()
|
||||
@@ -175,5 +177,5 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||
|
||||
private fun <T: KonanLibraryReader> List<T>.purgeUnneeded(config: KonanConfig): List<T> =
|
||||
private fun <T: KonanLibrary> List<T>.purgeUnneeded(config: KonanConfig): List<T> =
|
||||
this.filter{ (!it.isDefaultLibrary && !config.purgeUserLibs) || it.isNeededForLink }
|
||||
|
||||
+2
-2
@@ -17,14 +17,14 @@
|
||||
package org.jetbrains.kotlin.backend.konan.library
|
||||
|
||||
import llvm.LLVMModuleRef
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
|
||||
interface KonanLibraryWriter {
|
||||
fun addLinkData(linkData: LinkData)
|
||||
fun addNativeBitcode(library: String)
|
||||
fun addIncludedBinary(library: String)
|
||||
fun addKotlinBitcode(llvmModule: LLVMModuleRef)
|
||||
fun addLinkDependencies(libraries: List<KonanLibraryReader>)
|
||||
fun addLinkDependencies(libraries: List<KonanLibrary>)
|
||||
fun addManifestAddend(path: String)
|
||||
fun addDataFlowGraph(dataFlowGraph: ByteArray)
|
||||
val mainBitcodeFileName: String
|
||||
|
||||
+16
-15
@@ -17,15 +17,16 @@
|
||||
package org.jetbrains.kotlin.backend.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.SearchPathResolver
|
||||
import org.jetbrains.kotlin.konan.library.impl.LibraryReaderImpl
|
||||
import org.jetbrains.kotlin.konan.library.createKonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.unresolvedDependencies
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
const val KONAN_CURRENT_ABI_VERSION = 1
|
||||
|
||||
/**
|
||||
* Returns the list of [KonanLibraryReader]s given the list of user provided [libraryNames] along with
|
||||
* Returns the list of [KonanLibrary]s given the list of user provided [libraryNames] along with
|
||||
* other parameters: [target], [abiVersion], [noStdLib], [noDefaultLibs].
|
||||
*/
|
||||
fun SearchPathResolver.resolveImmediateLibraries(libraryNames: List<String>,
|
||||
@@ -33,13 +34,13 @@ fun SearchPathResolver.resolveImmediateLibraries(libraryNames: List<String>,
|
||||
abiVersion: Int = KONAN_CURRENT_ABI_VERSION,
|
||||
noStdLib: Boolean = false,
|
||||
noDefaultLibs: Boolean = false,
|
||||
logger: ((String) -> Unit)?): List<KonanLibraryReader> {
|
||||
logger: ((String) -> Unit)?): List<KonanLibrary> {
|
||||
val userProvidedLibraries = libraryNames
|
||||
.map { resolve(it) }
|
||||
.map{ LibraryReaderImpl(it, abiVersion, target) }
|
||||
.map{ createKonanLibraryReader(it, abiVersion, target) }
|
||||
|
||||
val defaultLibraries = defaultLinks(noStdLib = noStdLib, noDefaultLibs = noDefaultLibs).map {
|
||||
LibraryReaderImpl(it, abiVersion, target, isDefaultLibrary = true)
|
||||
createKonanLibraryReader(it, abiVersion, target, isDefaultLibrary = true)
|
||||
}
|
||||
|
||||
// Make sure the user provided ones appear first, so that
|
||||
@@ -64,16 +65,16 @@ private fun warnOnLibraryDuplicates(resolvedLibraries: List<File>, logger: ((Str
|
||||
|
||||
/**
|
||||
* For each of the given [immediateLibraries] fills in `resolvedDependencies` field with the
|
||||
* [KonanLibraryReader]s the library !!directly!! depends on.
|
||||
* [KonanLibrary]s the library !!directly!! depends on.
|
||||
*/
|
||||
fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<KonanLibraryReader>,
|
||||
fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<KonanLibrary>,
|
||||
target: KonanTarget,
|
||||
abiVersion: Int) {
|
||||
val cache = mutableMapOf<File, KonanLibraryReader>()
|
||||
val cache = mutableMapOf<File, KonanLibrary>()
|
||||
cache.putAll(immediateLibraries.map { it.libraryFile.absoluteFile to it })
|
||||
var newDependencies = cache.values.toList()
|
||||
do {
|
||||
newDependencies = newDependencies.map { library: KonanLibraryReader ->
|
||||
newDependencies = newDependencies.map { library: KonanLibrary ->
|
||||
library.unresolvedDependencies
|
||||
.map { resolve(it).absoluteFile }
|
||||
.mapNotNull {
|
||||
@@ -81,7 +82,7 @@ fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<KonanL
|
||||
library.resolvedDependencies.add(cache[it]!!)
|
||||
null
|
||||
} else {
|
||||
val reader = LibraryReaderImpl(it, abiVersion, target)
|
||||
val reader = createKonanLibraryReader(it, abiVersion, target)
|
||||
cache[it] = reader
|
||||
library.resolvedDependencies.add(reader)
|
||||
reader
|
||||
@@ -92,11 +93,11 @@ fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<KonanL
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given list of [KonanLibraryReader]s returns the list of [KonanLibraryReader]s
|
||||
* For the given list of [KonanLibrary]s returns the list of [KonanLibrary]s
|
||||
* that includes the same libraries plus all their (transitive) dependencies.
|
||||
*/
|
||||
fun List<KonanLibraryReader>.withResolvedDependencies(): List<KonanLibraryReader> {
|
||||
val result = mutableSetOf<KonanLibraryReader>()
|
||||
fun List<KonanLibrary>.withResolvedDependencies(): List<KonanLibrary> {
|
||||
val result = mutableSetOf<KonanLibrary>()
|
||||
result.addAll(this)
|
||||
var newDependencies = result.toList()
|
||||
do {
|
||||
@@ -112,7 +113,7 @@ fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List<String>,
|
||||
target: KonanTarget,
|
||||
abiVersion: Int = KONAN_CURRENT_ABI_VERSION,
|
||||
noStdLib: Boolean = false,
|
||||
noDefaultLibs: Boolean = false): List<KonanLibraryReader> {
|
||||
noDefaultLibs: Boolean = false): List<KonanLibrary> {
|
||||
val immediateLibraries = resolveImmediateLibraries(
|
||||
libraryNames = libraryNames,
|
||||
target = target,
|
||||
|
||||
+32
-29
@@ -16,31 +16,34 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import llvm.LLVMModuleRef
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
import org.jetbrains.kotlin.konan.library.*
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
abstract class FileBasedLibraryWriter (
|
||||
val file: File, val currentAbiVersion: Int): KonanLibraryWriter {
|
||||
}
|
||||
abstract class FileBasedLibraryWriter (val file: File, val currentAbiVersion: Int): KonanLibraryWriter
|
||||
|
||||
class LibraryWriterImpl(override val libDir: File, moduleName: String, currentAbiVersion: Int,
|
||||
override val target: KonanTarget?, val nopack: Boolean = false):
|
||||
FileBasedLibraryWriter(libDir, currentAbiVersion), KonanLibrary {
|
||||
/**
|
||||
* Requires non-null [target].
|
||||
*/
|
||||
class LibraryWriterImpl(
|
||||
override val libDir: File,
|
||||
moduleName: String,
|
||||
currentAbiVersion: Int,
|
||||
override val target: KonanTarget,
|
||||
val nopack: Boolean = false
|
||||
): FileBasedLibraryWriter(libDir, currentAbiVersion), KonanLibraryLayout {
|
||||
|
||||
public constructor(path: String, moduleName: String, currentAbiVersion: Int,
|
||||
target:KonanTarget?, nopack: Boolean):
|
||||
constructor(path: String, moduleName: String, currentAbiVersion: Int, target: KonanTarget, nopack: Boolean):
|
||||
this(File(path), moduleName, currentAbiVersion, target, nopack)
|
||||
|
||||
override val libraryName = libDir.path
|
||||
val klibFile
|
||||
get() = File("${libDir.path}.klib")
|
||||
get() = File("${libDir.path}.$KLIB_FILE_EXTENSION")
|
||||
|
||||
// TODO: Experiment with separate bitcode files.
|
||||
// Per package or per class.
|
||||
@@ -60,8 +63,8 @@ class LibraryWriterImpl(override val libDir: File, moduleName: String, currentAb
|
||||
includedDir.mkdirs()
|
||||
resourcesDir.mkdirs()
|
||||
// TODO: <name>:<hash> will go somewhere around here.
|
||||
manifestProperties.setProperty("unique_name", "$moduleName")
|
||||
manifestProperties.setProperty("abi_version", "$currentAbiVersion")
|
||||
manifestProperties.setProperty(KLIB_PROPERTY_UNIQUE_NAME, moduleName)
|
||||
manifestProperties.setProperty(KLIB_PROPERTY_ABI_VERSION, currentAbiVersion.toString())
|
||||
}
|
||||
|
||||
var llvmModule: LLVMModuleRef? = null
|
||||
@@ -85,14 +88,14 @@ class LibraryWriterImpl(override val libDir: File, moduleName: String, currentAb
|
||||
File(library).copyTo(File(includedDir, basename))
|
||||
}
|
||||
|
||||
override fun addLinkDependencies(libraries: List<KonanLibraryReader>) {
|
||||
override fun addLinkDependencies(libraries: List<KonanLibrary>) {
|
||||
if (libraries.isEmpty()) {
|
||||
manifestProperties.remove("depends")
|
||||
manifestProperties.remove(KLIB_PROPERTY_DEPENDS)
|
||||
// make sure there are no leftovers from the .def file.
|
||||
return
|
||||
} else {
|
||||
val newValue = libraries .map { it.uniqueName } . joinToString(" ")
|
||||
manifestProperties.setProperty("depends", newValue)
|
||||
val newValue = libraries.joinToString(" ") { it.uniqueName }
|
||||
manifestProperties.setProperty(KLIB_PROPERTY_DEPENDS, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,18 +118,18 @@ class LibraryWriterImpl(override val libDir: File, moduleName: String, currentAb
|
||||
}
|
||||
|
||||
internal fun buildLibrary(
|
||||
natives: List<String>,
|
||||
included: List<String>,
|
||||
linkDependencies: List<KonanLibraryReader>,
|
||||
linkData: LinkData,
|
||||
abiVersion: Int,
|
||||
target: KonanTarget,
|
||||
output: String,
|
||||
moduleName: String,
|
||||
llvmModule: LLVMModuleRef,
|
||||
nopack: Boolean,
|
||||
manifest: String?,
|
||||
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
||||
natives: List<String>,
|
||||
included: List<String>,
|
||||
linkDependencies: List<KonanLibrary>,
|
||||
linkData: LinkData,
|
||||
abiVersion: Int,
|
||||
target: KonanTarget,
|
||||
output: String,
|
||||
moduleName: String,
|
||||
llvmModule: LLVMModuleRef,
|
||||
nopack: Boolean,
|
||||
manifest: String?,
|
||||
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
||||
|
||||
val library = LibraryWriterImpl(output, moduleName, abiVersion, target, nopack)
|
||||
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||
|
||||
internal class MetadataWriterImpl(library: KonanLibrary): KonanLibrary by library {
|
||||
internal class MetadataWriterImpl(libraryLayout: KonanLibraryLayout): KonanLibraryLayout by libraryLayout {
|
||||
|
||||
fun addLinkData(linkData: LinkData) {
|
||||
moduleHeaderFile.writeBytes(linkData.module)
|
||||
|
||||
+3
-2
@@ -20,7 +20,7 @@ import llvm.LLVMTypeRef
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.isInlined
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.konan.library.uniqueName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
@@ -322,5 +323,5 @@ internal fun ModuleDescriptor.privateClassSymbolName(index: Int, className: Stri
|
||||
internal val String.moduleConstructorName
|
||||
get() = "_Konan_init_${this}"
|
||||
|
||||
internal val KonanLibraryReader.moduleConstructorName
|
||||
internal val KonanLibrary.moduleConstructorName
|
||||
get() = uniqueName.moduleConstructorName
|
||||
|
||||
+10
-10
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.findPackage
|
||||
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies
|
||||
import org.jetbrains.kotlin.descriptors.konan.CompiledKonanModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
|
||||
@@ -323,7 +323,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
return function
|
||||
}
|
||||
|
||||
private val usedLibraries = mutableSetOf<KonanLibraryReader>()
|
||||
private val usedLibraries = mutableSetOf<KonanLibrary>()
|
||||
|
||||
val imports = object : LlvmImports {
|
||||
|
||||
@@ -332,7 +332,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
override fun add(origin: CompiledKonanModuleOrigin) {
|
||||
val reader = when (origin) {
|
||||
CurrentKonanModuleOrigin -> return
|
||||
is DeserializedKonanModuleOrigin -> origin.reader as KonanLibraryReader
|
||||
is DeserializedKonanModuleOrigin -> origin.reader as KonanLibrary
|
||||
}
|
||||
|
||||
if (reader !in allLibraries) {
|
||||
@@ -343,19 +343,19 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
}
|
||||
}
|
||||
|
||||
val librariesToLink: List<KonanLibraryReader> by lazy {
|
||||
val librariesToLink: List<KonanLibrary> by lazy {
|
||||
context.config.immediateLibraries
|
||||
.filter { (!it.isDefaultLibrary && !context.config.purgeUserLibs) || it in usedLibraries }
|
||||
.withResolvedDependencies()
|
||||
.topoSort()
|
||||
}
|
||||
|
||||
private fun List<KonanLibraryReader>.topoSort(): List<KonanLibraryReader> {
|
||||
var sorted = mutableListOf<KonanLibraryReader>()
|
||||
val visited = mutableSetOf<KonanLibraryReader>()
|
||||
val tempMarks = mutableSetOf<KonanLibraryReader>()
|
||||
private fun List<KonanLibrary>.topoSort(): List<KonanLibrary> {
|
||||
var sorted = mutableListOf<KonanLibrary>()
|
||||
val visited = mutableSetOf<KonanLibrary>()
|
||||
val tempMarks = mutableSetOf<KonanLibrary>()
|
||||
|
||||
fun visit(node: KonanLibraryReader, result: MutableList<KonanLibraryReader>) {
|
||||
fun visit(node: KonanLibrary, result: MutableList<KonanLibrary>) {
|
||||
if (visited.contains(node)) return
|
||||
if (tempMarks.contains(node)) error("Cyclic dependency in library graph.")
|
||||
tempMarks.add(node)
|
||||
@@ -373,7 +373,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
return sorted
|
||||
}
|
||||
|
||||
val librariesForLibraryManifest: List<KonanLibraryReader> get() {
|
||||
val librariesForLibraryManifest: List<KonanLibrary> get() {
|
||||
// Note: library manifest should contain the list of all user libraries and frontend-used default libraries.
|
||||
// However this would result into linking too many default libraries into the application which uses current
|
||||
// library. This problem should probably be fixed by adding different kind of dependencies to library
|
||||
|
||||
Reference in New Issue
Block a user