Collected pieces of library management in KonanLibrary interface.

In anticipation of klib implementation.
This commit is contained in:
Alexander Gorshenev
2017-04-25 16:23:17 +03:00
committed by alexander-gorshenev
parent f56e68e255
commit 28c03a36cc
4 changed files with 97 additions and 40 deletions
@@ -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<String>
private val libraryNames: List<String>
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<KonanLibrary> 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<String> = configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
val moduleId: String
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
fun loadLibMetadata(libraries: List<String>): List<ModuleDescriptorImpl> {
fun loadLibMetadata(): List<ModuleDescriptorImpl> {
val allMetadata = mutableListOf<ModuleDescriptorImpl>()
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)
}
}
@@ -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<String>
}
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<String>
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)
}
}
@@ -266,7 +266,8 @@ internal class LinkStage(val context: Context) {
context.log{"# Compiler root: ${distribution.konanHome}"}
val bitcodeFiles = listOf<BitcodeFile>(emitted, distribution.start,
distribution.runtime, distribution.launcher) + libraries
distribution.runtime, distribution.launcher) +
libraries.map{it -> it.bitcodePaths}.flatten()
var objectFiles: List<String> = listOf()
@@ -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
}