[K/N] Extract cache management in linker to a separate file

Also, more meaningful names.
This commit is contained in:
Sergey Bogolepov
2023-01-25 13:26:30 +02:00
committed by Space Team
parent 2f1e9844df
commit e6081e5851
2 changed files with 61 additions and 44 deletions
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.konan.target.LinkerOutputKind
/**
* Check if we should link static caches into an object file before running full linkage.
*/
internal fun shouldPerformPreLink(config: KonanConfig, caches: ResolvedCacheBinaries, linkerOutputKind: LinkerOutputKind): Boolean {
// Pre-link is only useful when producing static library. Otherwise its just a waste of time.
val isStaticLibrary = linkerOutputKind == LinkerOutputKind.STATIC_LIBRARY &&
config.isFinalBinary
val enabled = config.cacheSupport.preLinkCaches
val nonEmptyCaches = caches.static.isNotEmpty()
return isStaticLibrary && enabled && nonEmptyCaches
}
/**
* List of cache binaries that are required for the final artifact.
* [static] is a list of static libraries (e.g. "libcache.a")
* [dynamic] is a list of dynamic libraries (e.g. "libcache.dylib")
*/
internal class ResolvedCacheBinaries(val static: List<String>, val dynamic: List<String>)
/**
* Find binary files for compiler caches that are actually required for the linkage.
*/
internal fun resolveCacheBinaries(
cachedLibraries: CachedLibraries,
dependenciesTrackingResult: DependenciesTrackingResult,
): ResolvedCacheBinaries {
val staticCaches = mutableListOf<String>()
val dynamicCaches = mutableListOf<String>()
dependenciesTrackingResult.allCachedBitcodeDependencies.forEach { dependency ->
val library = dependency.library
val cache = cachedLibraries.getLibraryCache(library)
// Maybe turn it into a warning and continue linkage without caches?
?: error("Library $library is expected to be cached")
val list = when (cache.kind) {
CachedLibraries.Kind.DYNAMIC -> dynamicCaches
CachedLibraries.Kind.STATIC -> staticCaches
}
list += if (dependency.kind is DependenciesTracker.DependencyKind.CertainFiles && cache is CachedLibraries.Cache.PerFile)
dependency.kind.files.map { cache.getFileBinaryPath(it) }
else cache.binariesPaths
}
return ResolvedCacheBinaries(static = staticCaches, dynamic = dynamicCaches)
}
@@ -1,9 +1,6 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
import org.jetbrains.kotlin.backend.konan.serialization.ClassFieldsSerializer
import org.jetbrains.kotlin.backend.konan.serialization.EagerInitializedPropertySerializer
import org.jetbrains.kotlin.backend.konan.serialization.InlineFunctionBodyReferenceSerializer
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
import org.jetbrains.kotlin.konan.TempFiles
import org.jetbrains.kotlin.konan.exec.Command
@@ -166,33 +163,24 @@ internal class Linker(
return executable
}
private fun shouldPerformPreLink(caches: CachesToLink, linkerOutputKind: LinkerOutputKind): Boolean {
// Pre-link is only useful when producing static library. Otherwise its just a waste of time.
val isStaticLibrary = linkerOutputKind == LinkerOutputKind.STATIC_LIBRARY &&
config.isFinalBinary
val enabled = config.cacheSupport.preLinkCaches
val nonEmptyCaches = caches.static.isNotEmpty()
return isStaticLibrary && enabled && nonEmptyCaches
}
private fun determineLinkerInput(
objectFiles: List<ObjectFile>,
linkerOutputKind: LinkerOutputKind,
dependenciesTrackingResult: DependenciesTrackingResult,
): LinkerInput {
val caches = determineCachesToLink(context, dependenciesTrackingResult)
val caches = resolveCacheBinaries(context.config.cachedLibraries, dependenciesTrackingResult)
// Since we have several linker stages that involve caching,
// we should detect cache usage early to report errors correctly.
val cachingInvolved = caches.static.isNotEmpty() || caches.dynamic.isNotEmpty()
return when {
config.produce == CompilerOutputKind.STATIC_CACHE -> {
// Do not link static cache dependencies.
LinkerInput(objectFiles, CachesToLink(emptyList(), caches.dynamic), emptyList(), cachingInvolved)
LinkerInput(objectFiles, ResolvedCacheBinaries(emptyList(), caches.dynamic), emptyList(), cachingInvolved)
}
shouldPerformPreLink(caches, linkerOutputKind) -> {
shouldPerformPreLink(config, caches, linkerOutputKind) -> {
val preLinkResult = tempFiles.create("withStaticCaches", ".o").absolutePath
val preLinkCommands = linker.preLinkCommands(objectFiles + caches.static, preLinkResult)
LinkerInput(listOf(preLinkResult), CachesToLink(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved)
LinkerInput(listOf(preLinkResult), ResolvedCacheBinaries(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved)
}
else -> LinkerInput(objectFiles, caches, emptyList(), cachingInvolved)
}
@@ -201,33 +189,7 @@ internal class Linker(
private class LinkerInput(
val objectFiles: List<ObjectFile>,
val caches: CachesToLink,
val caches: ResolvedCacheBinaries,
val preLinkCommands: List<Command>,
val cachingInvolved: Boolean
)
private class CachesToLink(val static: List<String>, val dynamic: List<String>)
private fun determineCachesToLink(
context: PhaseContext,
dependenciesTrackingResult: DependenciesTrackingResult,
): CachesToLink {
val staticCaches = mutableListOf<String>()
val dynamicCaches = mutableListOf<String>()
dependenciesTrackingResult.allCachedBitcodeDependencies.forEach { dependency ->
val library = dependency.library
val cache = context.config.cachedLibraries.getLibraryCache(library)
?: error("Library $library is expected to be cached")
val list = when (cache.kind) {
CachedLibraries.Kind.DYNAMIC -> dynamicCaches
CachedLibraries.Kind.STATIC -> staticCaches
}
list += if (dependency.kind is DependenciesTracker.DependencyKind.CertainFiles && cache is CachedLibraries.Cache.PerFile)
dependency.kind.files.map { cache.getFileBinaryPath(it) }
else cache.binariesPaths
}
return CachesToLink(static = staticCaches, dynamic = dynamicCaches)
}
)