[K/N] Support CompilerOutputKind.LIBRARY in the dynamic driver
This commit is contained in:
committed by
Space Team
parent
b828672a2e
commit
73a52b6081
+41
-10
@@ -5,9 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.driver
|
package org.jetbrains.kotlin.backend.konan.driver
|
||||||
|
|
||||||
|
import kotlinx.cinterop.usingJvmCInteropCallbacks
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.phases.*
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
import org.jetbrains.kotlin.konan.util.usingNativeMemoryAllocator
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic driver does not "know" upfront which phases will be executed.
|
* Dynamic driver does not "know" upfront which phases will be executed.
|
||||||
@@ -20,15 +23,43 @@ internal class DynamicCompilerDriver : CompilerDriver() {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun run(config: KonanConfig, environment: KotlinCoreEnvironment) = when (config.produce) {
|
override fun run(config: KonanConfig, environment: KotlinCoreEnvironment) {
|
||||||
CompilerOutputKind.PROGRAM -> error("Dynamic compiler driver does not support `program` output yet.")
|
usingNativeMemoryAllocator {
|
||||||
CompilerOutputKind.DYNAMIC -> error("Dynamic compiler driver does not support `dynamic` output yet.")
|
usingJvmCInteropCallbacks {
|
||||||
CompilerOutputKind.STATIC -> error("Dynamic compiler driver does not support `static` output yet.")
|
PhaseEngine.startTopLevel(config) { engine ->
|
||||||
CompilerOutputKind.FRAMEWORK -> error("Dynamic compiler driver does not support `framework` output yet.")
|
when (config.produce) {
|
||||||
CompilerOutputKind.LIBRARY -> error("Dynamic compiler driver does not support `library` output yet.")
|
CompilerOutputKind.PROGRAM -> error("Dynamic compiler driver does not support `program` output yet.")
|
||||||
CompilerOutputKind.BITCODE -> error("Dynamic compiler driver does not support `bitcode` output yet.")
|
CompilerOutputKind.DYNAMIC -> error("Dynamic compiler driver does not support `dynamic` output yet.")
|
||||||
CompilerOutputKind.DYNAMIC_CACHE -> error("Dynamic compiler driver does not support `dynamic_cache` output yet.")
|
CompilerOutputKind.STATIC -> error("Dynamic compiler driver does not support `static` output yet.")
|
||||||
CompilerOutputKind.STATIC_CACHE -> error("Dynamic compiler driver does not support `static_cache` output yet.")
|
CompilerOutputKind.FRAMEWORK -> error("Dynamic compiler driver does not support `framework` output yet.")
|
||||||
CompilerOutputKind.PRELIMINARY_CACHE -> TODO()
|
CompilerOutputKind.LIBRARY -> produceKlib(engine, config, environment)
|
||||||
|
CompilerOutputKind.BITCODE -> error("Dynamic compiler driver does not support `bitcode` output yet.")
|
||||||
|
CompilerOutputKind.DYNAMIC_CACHE -> error("Dynamic compiler driver does not support `dynamic_cache` output yet.")
|
||||||
|
CompilerOutputKind.STATIC_CACHE -> error("Dynamic compiler driver does not support `static_cache` output yet.")
|
||||||
|
CompilerOutputKind.PRELIMINARY_CACHE -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun produceKlib(engine: PhaseEngine<PhaseContext>, config: KonanConfig, environment: KotlinCoreEnvironment) {
|
||||||
|
val frontendOutput = engine.useContext(FrontendContextImpl(config)) { it.runFrontend(environment) }
|
||||||
|
if (frontendOutput is FrontendPhaseOutput.ShouldNotGenerateCode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require(frontendOutput is FrontendPhaseOutput.Full)
|
||||||
|
val psiToIrOutput = if (config.metadataKlib) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
val psiToIrContext = PsiToIrContextImpl(config, frontendOutput.moduleDescriptor, frontendOutput.bindingContext)
|
||||||
|
val psiToIrOutput = engine.useContext(psiToIrContext) { psiToIrEngine ->
|
||||||
|
val output = psiToIrEngine.runPsiToIr(frontendOutput, isProducingLibrary = true)
|
||||||
|
output
|
||||||
|
}
|
||||||
|
psiToIrOutput
|
||||||
|
}
|
||||||
|
val serializerOutput = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput)
|
||||||
|
engine.writeKlib(serializerOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.driver.phases
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
|
||||||
|
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
|
||||||
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||||
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
|
import org.jetbrains.kotlin.library.SerializedIrModule
|
||||||
|
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||||
|
|
||||||
|
internal data class SerializerInput(
|
||||||
|
val moduleDescriptor: ModuleDescriptor,
|
||||||
|
val psiToIrOutput: PsiToIrOutput?,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SerializerOutput(
|
||||||
|
val serializedMetadata: SerializedMetadata?,
|
||||||
|
val serializedIr: SerializedIrModule?,
|
||||||
|
val dataFlowGraph: ByteArray?,
|
||||||
|
val neededLibraries: List<KonanLibrary>
|
||||||
|
)
|
||||||
|
|
||||||
|
internal val SerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, SerializerInput, SerializerOutput>(
|
||||||
|
"Serializer", "IR serialzer",
|
||||||
|
outputIfNotEnabled = { _, _, _, _ -> SerializerOutput(null, null, null, emptyList()) }
|
||||||
|
) { context: PhaseContext, input: SerializerInput ->
|
||||||
|
val config = context.config
|
||||||
|
val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER) ?: false
|
||||||
|
val messageLogger = config.configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None
|
||||||
|
val relativePathBase = config.configuration.get(CommonConfigurationKeys.KLIB_RELATIVE_PATH_BASES) ?: emptyList()
|
||||||
|
val normalizeAbsolutePaths = config.configuration.get(CommonConfigurationKeys.KLIB_NORMALIZE_ABSOLUTE_PATH) ?: false
|
||||||
|
|
||||||
|
val serializedIr = input.psiToIrOutput?.let {
|
||||||
|
val ir = it.irModule
|
||||||
|
KonanIrModuleSerializer(
|
||||||
|
messageLogger, ir.irBuiltins, it.expectDescriptorToSymbol,
|
||||||
|
skipExpects = !expectActualLinker,
|
||||||
|
compatibilityMode = CompatibilityMode.CURRENT,
|
||||||
|
normalizeAbsolutePaths = normalizeAbsolutePaths,
|
||||||
|
sourceBaseDirs = relativePathBase,
|
||||||
|
).serializedIrModule(ir)
|
||||||
|
}
|
||||||
|
|
||||||
|
val serializer = KlibMetadataMonolithicSerializer(
|
||||||
|
config.configuration.languageVersionSettings,
|
||||||
|
config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!,
|
||||||
|
config.project,
|
||||||
|
exportKDoc = context.shouldExportKDoc(),
|
||||||
|
!expectActualLinker, includeOnlyModuleContent = true)
|
||||||
|
val serializedMetadata = serializer.serializeModule(input.moduleDescriptor)
|
||||||
|
val neededLibraries = config.librariesWithDependencies(input.moduleDescriptor)
|
||||||
|
SerializerOutput(serializedMetadata, serializedIr, null, neededLibraries)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : PhaseContext> PhaseEngine<T>.runSerializer(
|
||||||
|
moduleDescriptor: ModuleDescriptor,
|
||||||
|
psiToIrResult: PsiToIrOutput?,
|
||||||
|
): SerializerOutput {
|
||||||
|
val input = SerializerInput(moduleDescriptor, psiToIrResult)
|
||||||
|
return this.runPhase(SerializerPhase, input)
|
||||||
|
}
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.driver.phases
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
|
import org.jetbrains.kotlin.backend.konan.OutputFiles
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
|
||||||
|
import org.jetbrains.kotlin.konan.CURRENT
|
||||||
|
import org.jetbrains.kotlin.konan.CompilerVersion
|
||||||
|
import org.jetbrains.kotlin.konan.library.impl.buildLibrary
|
||||||
|
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||||
|
import org.jetbrains.kotlin.library.KotlinLibraryVersioning
|
||||||
|
|
||||||
|
internal val WriteKlibPhase = createSimpleNamedCompilerPhase<PhaseContext, SerializerOutput>(
|
||||||
|
"WriteKlib", "Write klib output",
|
||||||
|
) { context, input ->
|
||||||
|
val config = context.config
|
||||||
|
val configuration = config.configuration
|
||||||
|
val outputFiles = OutputFiles(config.outputPath, config.target, config.produce)
|
||||||
|
val nopack = configuration.getBoolean(KonanConfigKeys.NOPACK)
|
||||||
|
val output = outputFiles.klibOutputFileName(!nopack)
|
||||||
|
val libraryName = config.moduleId
|
||||||
|
val shortLibraryName = config.shortModuleName
|
||||||
|
val abiVersion = KotlinAbiVersion.CURRENT
|
||||||
|
val compilerVersion = CompilerVersion.CURRENT.toString()
|
||||||
|
val libraryVersion = configuration.get(KonanConfigKeys.LIBRARY_VERSION)
|
||||||
|
val metadataVersion = KlibMetadataVersion.INSTANCE.toString()
|
||||||
|
val irVersion = KlibIrVersion.INSTANCE.toString()
|
||||||
|
val versions = KotlinLibraryVersioning(
|
||||||
|
abiVersion = abiVersion,
|
||||||
|
libraryVersion = libraryVersion,
|
||||||
|
compilerVersion = compilerVersion,
|
||||||
|
metadataVersion = metadataVersion,
|
||||||
|
irVersion = irVersion
|
||||||
|
)
|
||||||
|
val target = config.target
|
||||||
|
val manifestProperties = config.manifestProperties
|
||||||
|
|
||||||
|
if (!nopack) {
|
||||||
|
val suffix = outputFiles.produce.suffix(target)
|
||||||
|
if (!output.endsWith(suffix)) {
|
||||||
|
error("please specify correct output: packed: ${!nopack}, $output$suffix")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildLibrary(
|
||||||
|
config.nativeLibraries,
|
||||||
|
config.includeBinaries,
|
||||||
|
input.neededLibraries,
|
||||||
|
input.serializedMetadata!!,
|
||||||
|
input.serializedIr,
|
||||||
|
versions,
|
||||||
|
target,
|
||||||
|
output,
|
||||||
|
libraryName,
|
||||||
|
nopack,
|
||||||
|
shortLibraryName,
|
||||||
|
manifestProperties,
|
||||||
|
input.dataFlowGraph
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : PhaseContext> PhaseEngine<T>.writeKlib(
|
||||||
|
serializationOutput: SerializerOutput,
|
||||||
|
) {
|
||||||
|
this.runPhase(WriteKlibPhase, serializationOutput)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user