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 index 5ab21ebf4bc..c89ff0b4be9 100644 --- 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 @@ -7,7 +7,10 @@ package org.jetbrains.kotlin.backend.konan.driver import kotlinx.cinterop.usingJvmCInteropCallbacks import org.jetbrains.kotlin.backend.konan.KonanConfig -import org.jetbrains.kotlin.backend.konan.driver.phases.* +import org.jetbrains.kotlin.backend.konan.driver.phases.runFrontend +import org.jetbrains.kotlin.backend.konan.driver.phases.runPsiToIr +import org.jetbrains.kotlin.backend.konan.driver.phases.runSerializer +import org.jetbrains.kotlin.backend.konan.driver.phases.writeKlib import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.util.usingNativeMemoryAllocator @@ -43,22 +46,11 @@ internal class DynamicCompilerDriver : CompilerDriver() { } private fun produceKlib(engine: PhaseEngine, config: KonanConfig, environment: KotlinCoreEnvironment) { - val frontendOutput = engine.useContext(FrontendContextImpl(config)) { it.runFrontend(environment) } - if (frontendOutput == FrontendPhaseOutput.ShouldNotGenerateCode) { - return - } - require(frontendOutput is FrontendPhaseOutput.Full) + val frontendOutput = engine.runFrontend(config, environment) ?: return 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) - psiToIrEngine.runSpecialBackendChecks(output) - output - } - engine.runPhase(CopyDefaultValuesToActualPhase, psiToIrOutput.irModule) - psiToIrOutput + engine.runPsiToIr(frontendOutput, isProducingLibrary = true) } val serializerOutput = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput) engine.writeKlib(serializerOutput) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/Machinery.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/Machinery.kt index 2efd4452156..ec54b32df3c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/Machinery.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/Machinery.kt @@ -80,8 +80,8 @@ internal open class BasicPhaseContext( * This way, PhaseEngine forces user to create more specialized contexts that have a limited lifetime. */ internal class PhaseEngine( - private val phaseConfig: PhaseConfigurationService, - private val phaserState: PhaserState, + val phaseConfig: PhaseConfigurationService, + val phaserState: PhaserState, val context: C ) { companion object { @@ -120,11 +120,15 @@ internal class PhaseEngine( } } - fun runPhase( - phase: AbstractNamedCompilerPhase, + fun > runPhase( + phase: P, input: Input ): Output { // We lose sticky postconditions here, but it should be ok, since type is changed. return phase.invoke(phaseConfig, phaserState.changePhaserStateType(), context, input) } + + fun > runPhase( + phase: P, + ): Output = runPhase(phase, Unit) } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/PortingFromStaticDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/PortingFromStaticDriver.kt new file mode 100644 index 00000000000..d60553f105f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/PortingFromStaticDriver.kt @@ -0,0 +1,37 @@ +/* + * 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.common.phaser.AbstractNamedCompilerPhase +import org.jetbrains.kotlin.backend.common.phaser.changePhaserStateType +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.NativeGenerationState + +/** + * This is a hack. + * + * It simplifies porting phases that are logically running in [NativeGenerationState] context, but + * for legacy reasons require [Context]. + * + * The idea is following: + * 1. Port everything from the static driver. + * 2. Adapt phases to use NativeGenerationState and pass additional input directly instead of taking it from Context. + * 3. Drop this hack. + * + * Idea of "parent context" might be appealing at the first sight. Unfortunately, it has serious drawbacks: + * 1. It couples child context with the parent one which makes it harder to reuse child context in different environment (e.g. tests). + * 2. It couples phases that are running in child context with the parent one. + */ +internal fun > PhaseEngine.runPhaseInParentContext( + phase: P, + input: Input +): Output { + return phase.invoke(phaseConfig, phaserState.changePhaserStateType(), context.context, input) +} + +internal fun > PhaseEngine.runPhaseInParentContext( + phase: P, +): Output = runPhaseInParentContext(phase, Unit) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt new file mode 100644 index 00000000000..9908d646ce2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt @@ -0,0 +1,38 @@ +/* + * 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.konan.KonanConfig +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext +import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment + +internal fun PhaseEngine.runFrontend(config: KonanConfig, environment: KotlinCoreEnvironment): FrontendPhaseOutput.Full? { + val frontendOutput = useContext(FrontendContextImpl(config)) { it.runFrontend(environment) } + return frontendOutput as? FrontendPhaseOutput.Full +} + +internal fun PhaseEngine.runPsiToIr( + frontendOutput: FrontendPhaseOutput.Full, + isProducingLibrary: Boolean, +): PsiToIrOutput = runPsiToIr(frontendOutput, isProducingLibrary, {}).first + +internal fun PhaseEngine.runPsiToIr( + frontendOutput: FrontendPhaseOutput.Full, + isProducingLibrary: Boolean, + produceAdditionalOutput: (PhaseEngine) -> T +): Pair { + val config = this.context.config + val psiToIrContext = PsiToIrContextImpl(config, frontendOutput.moduleDescriptor, frontendOutput.bindingContext) + val (psiToIrOutput, additionalOutput) = useContext(psiToIrContext) { psiToIrEngine -> + val additionalOutput = produceAdditionalOutput(psiToIrEngine) + val output = psiToIrEngine.runPsiToIr(frontendOutput, isProducingLibrary) + psiToIrEngine.runSpecialBackendChecks(output) + output to additionalOutput + } + runPhase(CopyDefaultValuesToActualPhase, psiToIrOutput.irModule) + return psiToIrOutput to additionalOutput +} \ No newline at end of file