[K/N] Prepare dynamic driver for more output kinds
* Extract frontend and psi2ir into functions * Prepare hacks for porting old phases to the dynamic driver
This commit is contained in:
committed by
Space Team
parent
bb1acf729b
commit
bf89e27647
+6
-14
@@ -7,7 +7,10 @@ package org.jetbrains.kotlin.backend.konan.driver
|
|||||||
|
|
||||||
import kotlinx.cinterop.usingJvmCInteropCallbacks
|
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.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.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
|
import org.jetbrains.kotlin.konan.util.usingNativeMemoryAllocator
|
||||||
@@ -43,22 +46,11 @@ internal class DynamicCompilerDriver : CompilerDriver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun produceKlib(engine: PhaseEngine<PhaseContext>, config: KonanConfig, environment: KotlinCoreEnvironment) {
|
private fun produceKlib(engine: PhaseEngine<PhaseContext>, config: KonanConfig, environment: KotlinCoreEnvironment) {
|
||||||
val frontendOutput = engine.useContext(FrontendContextImpl(config)) { it.runFrontend(environment) }
|
val frontendOutput = engine.runFrontend(config, environment) ?: return
|
||||||
if (frontendOutput == FrontendPhaseOutput.ShouldNotGenerateCode) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
require(frontendOutput is FrontendPhaseOutput.Full)
|
|
||||||
val psiToIrOutput = if (config.metadataKlib) {
|
val psiToIrOutput = if (config.metadataKlib) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
val psiToIrContext = PsiToIrContextImpl(config, frontendOutput.moduleDescriptor, frontendOutput.bindingContext)
|
engine.runPsiToIr(frontendOutput, isProducingLibrary = true)
|
||||||
val psiToIrOutput = engine.useContext(psiToIrContext) { psiToIrEngine ->
|
|
||||||
val output = psiToIrEngine.runPsiToIr(frontendOutput, isProducingLibrary = true)
|
|
||||||
psiToIrEngine.runSpecialBackendChecks(output)
|
|
||||||
output
|
|
||||||
}
|
|
||||||
engine.runPhase(CopyDefaultValuesToActualPhase, psiToIrOutput.irModule)
|
|
||||||
psiToIrOutput
|
|
||||||
}
|
}
|
||||||
val serializerOutput = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput)
|
val serializerOutput = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput)
|
||||||
engine.writeKlib(serializerOutput)
|
engine.writeKlib(serializerOutput)
|
||||||
|
|||||||
+8
-4
@@ -80,8 +80,8 @@ internal open class BasicPhaseContext(
|
|||||||
* This way, PhaseEngine forces user to create more specialized contexts that have a limited lifetime.
|
* This way, PhaseEngine forces user to create more specialized contexts that have a limited lifetime.
|
||||||
*/
|
*/
|
||||||
internal class PhaseEngine<C : PhaseContext>(
|
internal class PhaseEngine<C : PhaseContext>(
|
||||||
private val phaseConfig: PhaseConfigurationService,
|
val phaseConfig: PhaseConfigurationService,
|
||||||
private val phaserState: PhaserState<Any>,
|
val phaserState: PhaserState<Any>,
|
||||||
val context: C
|
val context: C
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -120,11 +120,15 @@ internal class PhaseEngine<C : PhaseContext>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <Input, Output> runPhase(
|
fun <Input, Output, P : AbstractNamedCompilerPhase<C, Input, Output>> runPhase(
|
||||||
phase: AbstractNamedCompilerPhase<C, Input, Output>,
|
phase: P,
|
||||||
input: Input
|
input: Input
|
||||||
): Output {
|
): Output {
|
||||||
// We lose sticky postconditions here, but it should be ok, since type is changed.
|
// We lose sticky postconditions here, but it should be ok, since type is changed.
|
||||||
return phase.invoke(phaseConfig, phaserState.changePhaserStateType(), context, input)
|
return phase.invoke(phaseConfig, phaserState.changePhaserStateType(), context, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <Output, P : AbstractNamedCompilerPhase<C, Unit, Output>> runPhase(
|
||||||
|
phase: P,
|
||||||
|
): Output = runPhase(phase, Unit)
|
||||||
}
|
}
|
||||||
+37
@@ -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 <Input, Output, P : AbstractNamedCompilerPhase<Context, Input, Output>> PhaseEngine<NativeGenerationState>.runPhaseInParentContext(
|
||||||
|
phase: P,
|
||||||
|
input: Input
|
||||||
|
): Output {
|
||||||
|
return phase.invoke(phaseConfig, phaserState.changePhaserStateType(), context.context, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <Output, P : AbstractNamedCompilerPhase<Context, Unit, Output>> PhaseEngine<NativeGenerationState>.runPhaseInParentContext(
|
||||||
|
phase: P,
|
||||||
|
): Output = runPhaseInParentContext(phase, Unit)
|
||||||
+38
@@ -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<PhaseContext>.runFrontend(config: KonanConfig, environment: KotlinCoreEnvironment): FrontendPhaseOutput.Full? {
|
||||||
|
val frontendOutput = useContext(FrontendContextImpl(config)) { it.runFrontend(environment) }
|
||||||
|
return frontendOutput as? FrontendPhaseOutput.Full
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun PhaseEngine<PhaseContext>.runPsiToIr(
|
||||||
|
frontendOutput: FrontendPhaseOutput.Full,
|
||||||
|
isProducingLibrary: Boolean,
|
||||||
|
): PsiToIrOutput = runPsiToIr(frontendOutput, isProducingLibrary, {}).first
|
||||||
|
|
||||||
|
internal fun <T> PhaseEngine<PhaseContext>.runPsiToIr(
|
||||||
|
frontendOutput: FrontendPhaseOutput.Full,
|
||||||
|
isProducingLibrary: Boolean,
|
||||||
|
produceAdditionalOutput: (PhaseEngine<out PsiToIrContext>) -> T
|
||||||
|
): Pair<PsiToIrOutput, T> {
|
||||||
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user