From 28c03a36ccfdf79c44985c0fb39c2a5560ce73df Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Tue, 25 Apr 2017 16:23:17 +0300 Subject: [PATCH] Collected pieces of library management in KonanLibrary interface. In anticipation of klib implementation. --- .../kotlin/backend/konan/KonanConfig.kt | 28 ++++---- .../kotlin/backend/konan/KonanLibrary.kt | 69 +++++++++++++++++++ .../kotlin/backend/konan/LinkStage.kt | 3 +- .../backend/konan/llvm/MetadataGenerator.kt | 37 ++++------ 4 files changed, 97 insertions(+), 40 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrary.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 989da4ce011..f9a3a4d07b8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.backend.konan import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.backend.konan.llvm.loadMetadata import org.jetbrains.kotlin.backend.konan.util.profile import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration @@ -26,9 +25,12 @@ import java.io.File class KonanConfig(val project: Project, val configuration: CompilerConfiguration) { + val moduleId: String + get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME) + internal val distribution = Distribution(configuration) - internal val libraries: List + private val libraryNames: List get() { val fromCommandLine = configuration.getList(KonanConfigKeys.LIBRARY_FILES) if (configuration.get(KonanConfigKeys.NOSTDLIB) ?: false) { @@ -37,25 +39,23 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration return fromCommandLine + distribution.stdlib } - private val loadedDescriptors = loadLibMetadata(libraries) + internal val libraries: List by lazy { + // Here we have chosen a particular .kt.bc KonanLibrary implementation + libraryNames.map{it -> KtBcLibrary(it, configuration)} + } + + private val loadedDescriptors = loadLibMetadata() internal val nativeLibraries: List = configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES) - val moduleId: String - get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME) - fun loadLibMetadata(libraries: List): List { + fun loadLibMetadata(): List { val allMetadata = mutableListOf() - for (path in libraries) { - val filePath = File(path) - if (!filePath.exists()) { - error("Path '" + path + "' does not exist") - } - - profile("Loading ${filePath}") { - val moduleDescriptor = loadMetadata(configuration, filePath) + for (klib in libraries) { + profile("Loading ${klib.libraryName}") { + val moduleDescriptor = klib.moduleDescriptor allMetadata.add(moduleDescriptor) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrary.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrary.kt new file mode 100644 index 00000000000..e13d46c9330 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrary.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.backend.konan.llvm.MetadataReader +import org.jetbrains.kotlin.backend.konan.llvm.loadSerializedModule +import org.jetbrains.kotlin.backend.konan.llvm.loadSerializedPackageFragment +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.backend.konan.serialization.Base64 +import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule +import java.io.File + +interface KonanLibrary { + val libraryName: String + val moduleName: String + val moduleDescriptor: ModuleDescriptorImpl + val bitcodePaths: List +} + +class KtBcLibrary(val file: File, val configuration: CompilerConfiguration): KonanLibrary { + constructor(path: String, configuration: CompilerConfiguration) : this(File(path), configuration) + init { + if (!file.exists()) + error("Path '" + file.path + "' does not exist") + } + + override val libraryName: String + get() = file.path + + override val bitcodePaths: List + get() = listOf(libraryName) + + private val reader = MetadataReader(file) + + private val namedModuleData by lazy { + val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION)!! + reader.loadSerializedModule(currentAbiVersion) + } + override val moduleName = namedModuleData.name + + private val tableOfContentsAsString = namedModuleData.base64 + + private fun packageMetadata(fqName: String): Base64 = + reader.loadSerializedPackageFragment(fqName) + + override val moduleDescriptor: ModuleDescriptorImpl by lazy { + deserializeModule(configuration, + {it -> packageMetadata(it)}, + tableOfContentsAsString, moduleName) + } +} + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index e5aec0011ac..e7f2d30b369 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -266,7 +266,8 @@ internal class LinkStage(val context: Context) { context.log{"# Compiler root: ${distribution.konanHome}"} val bitcodeFiles = listOf(emitted, distribution.start, - distribution.runtime, distribution.launcher) + libraries + distribution.runtime, distribution.launcher) + + libraries.map{it -> it.bitcodePaths}.flatten() var objectFiles: List = listOf() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/MetadataGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/MetadataGenerator.kt index cb98665e2eb..b5d9169533f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/MetadataGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/MetadataGenerator.kt @@ -20,57 +20,44 @@ import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanConfigKeys -import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import java.io.Closeable import java.io.File -fun loadMetadata(configuration: CompilerConfiguration, file: File): ModuleDescriptorImpl { +class NamedModuleData(val name:String, val base64: String) - val reader = MetadataReader(file) - - var moduleName: String? = null - val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION) - - val (nodeCount, kmetadataNodeArg) = reader.namedMetadataNode("kmetadata") +fun MetadataReader.loadSerializedModule(currentAbiVersion: Int): NamedModuleData { + val (nodeCount, kmetadataNodeArg) = namedMetadataNode("kmetadata") if (nodeCount != 1) { throw Error("Unknown metadata format. The 'kmetadata' node has ${nodeCount} arguments. Don't know what to do.") } - val operands = reader.metadataNodeOperands(kmetadataNodeArg) + val operands = metadataNodeOperands(kmetadataNodeArg) val abiNode = operands[0] val nameNode = operands[1] val dataNode = operands[2] - val abiVersion = reader.string(abiNode).toInt() - + val abiVersion = string(abiNode).toInt() if (abiVersion != currentAbiVersion) { throw Error("Expected ABI version ${currentAbiVersion}, but the binary is ${abiVersion}") } - moduleName = reader.string(nameNode) - - val tableOfContentsAsString = reader.string(dataNode) - - val moduleDescriptor = - deserializeModule(configuration, {it->loadPackageFragment(reader, it)}, tableOfContentsAsString, moduleName) - - return moduleDescriptor + val moduleName = string(nameNode) + val tableOfContentsAsString = string(dataNode) + return NamedModuleData(moduleName, tableOfContentsAsString) } -fun loadPackageFragment(reader: MetadataReader, fqName: String): String { - val (nodeCount, kpackageNodeArg) = reader.namedMetadataNode("kpackage:$fqName") +fun MetadataReader.loadSerializedPackageFragment(fqName: String): String { + val (nodeCount, kpackageNodeArg) = namedMetadataNode("kpackage:$fqName") if (nodeCount != 1) { throw Error("The 'kpackage:$fqName' node has ${nodeCount} arguments.") } - val operands = reader.metadataNodeOperands(kpackageNodeArg) + val operands = metadataNodeOperands(kpackageNodeArg) val dataNode = operands[0] - val base64 = reader.string(dataNode) + val base64 = string(dataNode) return base64 }