diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt index a554320cd82..dc581664874 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt @@ -6,24 +6,17 @@ package org.jetbrains.kotlin.backend.konan import com.intellij.openapi.project.Project -import kotlinx.cinterop.usingJvmCInteropCallbacks -import org.jetbrains.kotlin.analyzer.AnalysisResult -import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase -import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.serialization.codedInputStream import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.backend.konan.driver.CompilerDriver +import org.jetbrains.kotlin.backend.konan.driver.DynamicCompilerDriver +import org.jetbrains.kotlin.backend.konan.driver.StaticCompilerDriver import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.library.impl.createKonanLibrary -import org.jetbrains.kotlin.konan.target.CompilerOutputKind -import org.jetbrains.kotlin.konan.util.usingNativeMemoryAllocator import org.jetbrains.kotlin.library.uniqueName import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite -import org.jetbrains.kotlin.utils.addToStdlib.cast class KonanDriver(val project: Project, val environment: KotlinCoreEnvironment, val configuration: CompilerConfiguration) { fun run() { @@ -43,12 +36,9 @@ class KonanDriver(val project: Project, val environment: KotlinCoreEnvironment, configuration.put(KonanConfigKeys.FILES_TO_CACHE, fileNames) } - KonanConfig(project, configuration).runTopLevelPhases() - } - - private fun KonanConfig.runTopLevelPhases() { - ensureModuleName(this) - runTopLevelPhases(this, environment) + val konanConfig = KonanConfig(project, configuration) + ensureModuleName(konanConfig) + pickCompilerDriver().run(konanConfig, environment) } private fun ensureModuleName(config: KonanConfig) { @@ -62,62 +52,13 @@ class KonanDriver(val project: Project, val environment: KotlinCoreEnvironment, } } } -} -private fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironment) { - - val config = konanConfig.configuration - - val targets = konanConfig.targetManager - if (config.get(KonanConfigKeys.LIST_TARGETS) ?: false) { - targets.list() - } - - val context = Context(konanConfig) - context.environment = environment - context.phaseConfig.konanPhasesConfig(konanConfig) // TODO: Wrong place to call it - - if (konanConfig.infoArgsOnly) return - - if (!context.frontendPhase()) return - - usingNativeMemoryAllocator { - usingJvmCInteropCallbacks { - try { - toplevelPhase.cast>().invokeToplevel(context.phaseConfig, context, Unit) - } finally { - context.disposeGenerationState() - } + private fun pickCompilerDriver(): CompilerDriver { + // Dynamic driver is WIP, so it might not support all possible configurations. + return if (DynamicCompilerDriver.supportsConfig()) { + DynamicCompilerDriver() + } else { + StaticCompilerDriver() } } -} - -// returns true if should generate code. -internal fun Context.frontendPhase(): Boolean { - lateinit var analysisResult: AnalysisResult - - do { - val analyzerWithCompilerReport = AnalyzerWithCompilerReport( - messageCollector, - environment.configuration.languageVersionSettings, - environment.configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) - ) - - // Build AST and binding info. - analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles()) { - TopDownAnalyzerFacadeForKonan.analyzeFiles(environment.getSourceFiles(), this) - } - if (analyzerWithCompilerReport.hasErrors()) { - throw KonanCompilationException() - } - analysisResult = analyzerWithCompilerReport.analysisResult - if (analysisResult is AnalysisResult.RetryWithAdditionalRoots) { - environment.addKotlinSourceRoots(analysisResult.additionalKotlinRoots) - } - } while(analysisResult is AnalysisResult.RetryWithAdditionalRoots) - - moduleDescriptor = analysisResult.moduleDescriptor - bindingContext = analysisResult.bindingContext - - return analysisResult.shouldGenerateCode -} +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/CompilerDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/CompilerDriver.kt new file mode 100644 index 00000000000..72d8f3009bb --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/CompilerDriver.kt @@ -0,0 +1,19 @@ +/* + * 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 + +import org.jetbrains.kotlin.backend.konan.KonanConfig +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment + +/** + * Compiler driver orchestrates and connects different parts of compiler into a complete pipeline. + */ +internal sealed class CompilerDriver { + /** + * Entry point for compilation pipeline. + */ + abstract fun run(config: KonanConfig, environment: KotlinCoreEnvironment) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt new file mode 100644 index 00000000000..1313536f25a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt @@ -0,0 +1,34 @@ +/* + * 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 + +import org.jetbrains.kotlin.backend.konan.KonanConfig +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.konan.target.CompilerOutputKind + +/** + * Dynamic driver does not "know" upfront which phases will be executed. + */ +internal class DynamicCompilerDriver : CompilerDriver() { + + companion object { + // Will become non-trivial in the future. + fun supportsConfig(): Boolean = + false + } + + override fun run(config: KonanConfig, environment: KotlinCoreEnvironment) = when (config.produce) { + CompilerOutputKind.PROGRAM -> error("Dynamic compiler driver does not support `program` output yet.") + CompilerOutputKind.DYNAMIC -> error("Dynamic compiler driver does not support `dynamic` output yet.") + CompilerOutputKind.STATIC -> error("Dynamic compiler driver does not support `static` output yet.") + CompilerOutputKind.FRAMEWORK -> error("Dynamic compiler driver does not support `framework` output yet.") + CompilerOutputKind.LIBRARY -> error("Dynamic compiler driver does not support `library` output yet.") + 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() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/StaticCompilerDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/StaticCompilerDriver.kt new file mode 100644 index 00000000000..6408d906f4a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/StaticCompilerDriver.kt @@ -0,0 +1,87 @@ +/* + * 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 + +import kotlinx.cinterop.usingJvmCInteropCallbacks +import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase +import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.konan.util.usingNativeMemoryAllocator +import org.jetbrains.kotlin.utils.addToStdlib.cast + +/** + * Static compiler uses statically-defined compilation pipeline and a single Context during whole compilation. + * Superseded by [DynamicCompilerDriver] and will be removed once dynamic driver become complete. + */ +internal class StaticCompilerDriver : CompilerDriver() { + override fun run(config: KonanConfig, environment: KotlinCoreEnvironment) { + runTopLevelPhases(config, environment) + } + + private fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironment) { + + val config = konanConfig.configuration + + val targets = konanConfig.targetManager + if (config.get(KonanConfigKeys.LIST_TARGETS) ?: false) { + targets.list() + } + + val context = Context(konanConfig) + context.environment = environment + context.phaseConfig.konanPhasesConfig(konanConfig) // TODO: Wrong place to call it + + if (konanConfig.infoArgsOnly) return + + if (!context.frontendPhase()) return + + usingNativeMemoryAllocator { + usingJvmCInteropCallbacks { + try { + toplevelPhase.cast>().invokeToplevel(context.phaseConfig, context, Unit) + } finally { + context.disposeGenerationState() + } + } + } + } + + // returns true if should generate code. + private fun Context.frontendPhase(): Boolean { + lateinit var analysisResult: AnalysisResult + + do { + val analyzerWithCompilerReport = AnalyzerWithCompilerReport( + messageCollector, + environment.configuration.languageVersionSettings, + environment.configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) + ) + + // Build AST and binding info. + analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles()) { + TopDownAnalyzerFacadeForKonan.analyzeFiles(environment.getSourceFiles(), this) + } + if (analyzerWithCompilerReport.hasErrors()) { + throw KonanCompilationException() + } + analysisResult = analyzerWithCompilerReport.analysisResult + if (analysisResult is AnalysisResult.RetryWithAdditionalRoots) { + environment.addKotlinSourceRoots(analysisResult.additionalKotlinRoots) + } + } while(analysisResult is AnalysisResult.RetryWithAdditionalRoots) + + moduleDescriptor = analysisResult.moduleDescriptor + bindingContext = analysisResult.bindingContext + + return analysisResult.shouldGenerateCode + } + +} \ No newline at end of file