Use CompilerPhase from main repo

This commit is contained in:
Georgy Bronnikov
2018-12-10 12:11:01 +03:00
committed by alexander-gorshenev
parent 7380c2c718
commit 8764f650f7
11 changed files with 818 additions and 583 deletions
@@ -20,19 +20,20 @@ val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false
}
internal fun produceOutput(context: Context, phaser: PhaseManager) {
internal fun produceCStubs(context: Context) {
val llvmModule = context.llvmModule!!
context.cStubsManager.compile(context.config.clang, context.messageCollector, context.inVerbosePhase)?.let {
parseAndLinkBitcodeFile(llvmModule, it.absolutePath)
}
}
internal fun produceOutput(context: Context) {
val llvmModule = context.llvmModule!!
val config = context.config.configuration
val tempFiles = context.config.tempFiles
val produce = config.get(KonanConfigKeys.PRODUCE)
phaser.phase(KonanPhase.C_STUBS) {
context.cStubsManager.compile(context.config.clang, context.messageCollector, context.phase!!.verbose)?.let {
parseAndLinkBitcodeFile(llvmModule, it.absolutePath)
}
}
when (produce) {
CompilerOutputKind.STATIC,
CompilerOutputKind.DYNAMIC,
@@ -55,10 +56,8 @@ internal fun produceOutput(context: Context, phaser: PhaseManager) {
context.config.defaultNativeLibraries +
generatedBitcodeFiles
phaser.phase(KonanPhase.BITCODE_LINKER) {
for (library in nativeLibraries) {
parseAndLinkBitcodeFile(llvmModule, library)
}
for (library in nativeLibraries) {
parseAndLinkBitcodeFile(llvmModule, library)
}
LLVMWriteBitcodeToFile(llvmModule, output)
@@ -10,6 +10,7 @@ import llvm.LLVMModuleRef
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.validateIrModule
import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
@@ -18,6 +19,9 @@ import org.jetbrains.kotlin.backend.konan.library.LinkData
import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
import org.jetbrains.kotlin.backend.konan.optimizations.Devirtualization
import org.jetbrains.kotlin.backend.konan.optimizations.ExternalModulesDFG
import org.jetbrains.kotlin.backend.konan.optimizations.ModuleDFG
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
@@ -35,12 +39,14 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
@@ -204,6 +210,9 @@ internal class SpecialDeclarationsFactory(val context: Context) {
}
internal class Context(config: KonanConfig) : KonanBackendContext(config) {
lateinit var environment: KotlinCoreEnvironment
lateinit var bindingContext: BindingContext
override val declarationFactory
get() = TODO("not implemented")
@@ -217,6 +226,10 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
moduleDescriptor.builtIns as KonanBuiltIns
}
override val configuration get() = config.configuration
val phaseConfig = PhaseConfig(toplevelPhase, config.configuration)
private val packageScope by lazy { builtIns.builtInsModule.getPackage(KonanFqNames.internalPackageName).memberScope }
val nativePtr by lazy { packageScope.getContributedClassifier(NATIVE_PTR_NAME) as ClassDescriptor }
@@ -321,9 +334,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
val cStubsManager = CStubsManager()
var phase: KonanPhase? = null
var depth: Int = 0
lateinit var privateFunctions: List<Pair<IrFunction, DataFlowIR.FunctionSymbol.Declared>>
lateinit var privateClasses: List<Pair<IrClass, DataFlowIR.Type.Declared>>
@@ -342,7 +352,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
if (!::moduleDescriptor.isInitialized)
return
separator("Descriptors after: ${phase?.description}")
separator("Descriptors:")
moduleDescriptor.deepPrint()
}
@@ -353,19 +363,19 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
fun printIr() {
if (irModule == null) return
separator("IR after: ${phase?.description}")
separator("IR:")
irModule!!.accept(DumpIrTreeVisitor(out), "")
}
fun printIrWithDescriptors() {
if (irModule == null) return
separator("IR after: ${phase?.description}")
separator("IR:")
irModule!!.accept(DumpIrTreeWithDescriptorsVisitor(out), "")
}
fun printLocations() {
if (irModule == null) return
separator("Locations after: ${phase?.description}")
separator("Locations:")
irModule!!.acceptVoid(object: IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
@@ -407,7 +417,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
fun printBitCode() {
if (llvmModule == null) return
separator("BitCode after: ${phase?.description}")
separator("BitCode:")
LLVMDumpModule(llvmModule!!)
}
@@ -446,13 +456,19 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
override var inVerbosePhase = false
override fun log(message: () -> String) {
if (phase?.verbose ?: false) {
if (inVerbosePhase) {
println(message())
}
}
lateinit var debugInfo: DebugInfo
var moduleDFG: ModuleDFG? = null
var externalModulesDFG: ExternalModulesDFG? = null
lateinit var lifetimes: MutableMap<IrElement, Lifetime>
lateinit var codegenVisitor: CodeGeneratorVisitor
var devirtualizationAnalysisResult: Devirtualization.AnalysisResult? = null
val isNativeLibrary: Boolean by lazy {
val kind = config.configuration.get(KonanConfigKeys.PRODUCE)
@@ -461,6 +477,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
internal val stdlibModule
get() = this.builtIns.any.module
lateinit var linkStage: LinkStage
}
private fun MemberScope.getContributedClassifier(name: String) =
@@ -5,23 +5,8 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
import org.jetbrains.kotlin.backend.konan.serialization.*
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.konan.library.impl.CombinedIrFileWriter
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironment) {
@@ -32,118 +17,16 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme
targets.list()
}
KonanPhases.config(konanConfig)
val context = Context(konanConfig)
context.environment = environment
context.phaseConfig.konanPhasesConfig(konanConfig) // TODO: Wrong place to call it
if (config.get(KonanConfigKeys.LIST_PHASES) ?: false) {
KonanPhases.list()
context.phaseConfig.list()
}
if (konanConfig.infoArgsOnly) return
val context = Context(konanConfig)
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(context.messageCollector,
environment.configuration.languageVersionSettings)
val phaser = PhaseManager(context, null)
phaser.phase(KonanPhase.FRONTEND) {
// Build AST and binding info.
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles()) {
TopDownAnalyzerFacadeForKonan.analyzeFiles(environment.getSourceFiles(), konanConfig)
}
if (analyzerWithCompilerReport.hasErrors()) {
throw KonanCompilationException()
}
context.moduleDescriptor = analyzerWithCompilerReport.analysisResult.moduleDescriptor
}
val bindingContext = analyzerWithCompilerReport.analysisResult.bindingContext
phaser.phase(KonanPhase.PSI_TO_IR) {
// Translate AST to high level IR.
val translator = Psi2IrTranslator(context.config.configuration.languageVersionSettings,
Psi2IrConfiguration(false))
val generatorContext = translator.createGeneratorContext(context.moduleDescriptor, bindingContext)
@Suppress("DEPRECATION")
context.psi2IrGeneratorContext = generatorContext
val forwardDeclarationsModuleDescriptor = context.moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule }
val deserializer = KonanIrModuleDeserializer(
context.moduleDescriptor,
context as LoggingContext,
generatorContext.irBuiltIns,
generatorContext.symbolTable,
forwardDeclarationsModuleDescriptor
)
val irModules = context.moduleDescriptor.allDependencyModules.map {
val library = it.konanLibrary
if (library == null) {
return@map null
}
library.irHeader?.let { header -> deserializer.deserializeIrModule(it, header) }
}.filterNotNull()
val symbols = KonanSymbols(context, generatorContext.symbolTable, generatorContext.symbolTable.lazyWrapper)
val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles(), deserializer)
irModules.forEach {
it.patchDeclarationParents()
}
context.irModule = module
context.ir.symbols = symbols
// validateIrModule(context, module)
}
phaser.phase(KonanPhase.IR_GENERATOR_PLUGINS) {
val extensions = IrGenerationExtension.getInstances(context.config.project)
extensions.forEach { extension ->
context.irModule!!.files.forEach { irFile -> extension.generate(irFile, context, bindingContext) }
}
}
phaser.phase(KonanPhase.GEN_SYNTHETIC_FIELDS) {
markBackingFields(context)
}
// TODO: We copy default value expressions from expects to actuals before IR serialization,
// because the current infrastructure doesn't allow us to get them at deserialization stage.
// That equires some design and implementation work.
phaser.phase(KonanPhase.COPY_DEFAULT_VALUES_TO_ACTUAL) {
context.irModule!!.files.forEach(ExpectToActualDefaultValueCopier(context)::lower)
}
context.irModule!!.patchDeclarationParents() // why do we need it?
phaser.phase(KonanPhase.SERIALIZER) {
val declarationTable = DeclarationTable(context.irModule!!.irBuiltins, DescriptorTable())
val serializedIr = IrModuleSerializer(
context, declarationTable, bodiesOnlyForInlines = context.config.isInteropStubs).serializedIrModule(context.irModule!!)
val serializer = KonanSerializationUtil(context, context.config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
context.serializedLinkData =
serializer.serializeModule(context.moduleDescriptor, /*if (!context.config.isInteropStubs) serializedIr else null*/ serializedIr)
}
phaser.phase(KonanPhase.BACKEND) {
phaser.phase(KonanPhase.LOWER) {
KonanLower(context, phaser).lower()
// validateIrModule(context, context.ir.irModule) // Temporarily disabled until moving to new IR finished.
context.ir.moduleIndexForCodegen = ModuleIndex(context.ir.irModule)
}
phaser.phase(KonanPhase.BITCODE) {
emitLLVM(context, phaser)
produceOutput(context, phaser)
}
// We always verify bitcode to prevent hard to debug bugs.
context.verifyBitCode()
if (context.shouldPrintBitCode()) {
context.printBitCode()
}
}
phaser.phase(KonanPhase.LINK_STAGE) {
LinkStage(context, phaser).linkStage()
}
toplevelPhase.invokeToplevel(context.phaseConfig, context, Unit)
}
@@ -1,151 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.LocalDelegatedPropertiesLowering
import org.jetbrains.kotlin.backend.konan.lower.*
import org.jetbrains.kotlin.backend.konan.lower.ExpectDeclarationsRemoving
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
import org.jetbrains.kotlin.backend.konan.lower.VarargInjectionLowering
import org.jetbrains.kotlin.backend.konan.lower.loops.ForLoopsLowering
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.name
import org.jetbrains.kotlin.ir.util.checkDeclarationParents
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols
internal class KonanLower(val context: Context, val parentPhaser: PhaseManager) {
fun lower() {
val irModule = context.irModule!!
// Phases to run against whole module.
lowerModule(irModule, parentPhaser)
// Phases to run against a file.
irModule.files.forEach {
lowerFile(it, PhaseManager(context, parentPhaser))
}
irModule.checkDeclarationParents()
}
private fun lowerModule(irModule: IrModuleFragment, phaser: PhaseManager) {
phaser.phase(KonanPhase.REMOVE_EXPECT_DECLARATIONS) {
irModule.files.forEach(ExpectDeclarationsRemoving(context)::lower)
}
phaser.phase(KonanPhase.LOWER_BEFORE_INLINE) {
irModule.files.forEach(PreInlineLowering(context)::lower)
}
// Inlining must be run before other phases.
phaser.phase(KonanPhase.LOWER_INLINE) {
FunctionInlining(context).inline(irModule)
}
phaser.phase(KonanPhase.LOWER_AFTER_INLINE) {
irModule.files.forEach(PostInlineLowering(context)::lower)
// TODO: Seems like this should be deleted in PsiToIR.
irModule.files.forEach(ContractsDslRemover(context)::lower)
}
phaser.phase(KonanPhase.LOWER_INTEROP_PART1) {
irModule.files.forEach(InteropLoweringPart1(context)::lower)
}
irModule.patchDeclarationParents()
// validateIrModule(context, irModule) // Temporarily disabled until moving to new IR finished.
}
private fun lowerFile(irFile: IrFile, phaser: PhaseManager) {
phaser.phase(KonanPhase.LOWER_LATEINIT) {
LateinitLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
StringConcatenationLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_ENUM_CONSTRUCTORS) {
EnumConstructorsLowering(context).run(irFile)
}
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
InitializersLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
SharedVariablesLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
LocalDelegatedPropertiesLowering().lower(irFile)
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_TAILREC) {
TailrecLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_DEFAULT_PARAMETER_EXTENT) {
DefaultArgumentStubGenerator(context, skipInlineMethods = false).runOnFilePostfix(irFile)
KonanDefaultParameterInjector(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_INNER_CLASSES) {
InnerClassLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_FOR_LOOPS) {
ForLoopsLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_DATA_CLASSES) {
DataClassOperatorsLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_BUILTIN_OPERATORS) {
BuiltinOperatorLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_FINALLY) {
FinallyBlocksLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.TEST_PROCESSOR) {
TestProcessor(context).process(irFile)
}
phaser.phase(KonanPhase.LOWER_ENUMS) {
EnumClassLowering(context).run(irFile)
}
phaser.phase(KonanPhase.LOWER_DELEGATION) {
PropertyDelegationLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_CALLABLES) {
CallableReferenceLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_INTEROP_PART2) {
InteropLoweringPart2(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_VARARG) {
VarargInjectionLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_COMPILE_TIME_EVAL) {
CompileTimeEvaluateLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_COROUTINES) {
SuspendFunctionsLowering(context).lower(irFile)
}
phaser.phase(KonanPhase.LOWER_TYPE_OPERATORS) {
TypeOperatorLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
BridgesBuilding(context).runOnFilePostfix(irFile)
WorkersBridgesBuilding(context).lower(irFile)
}
phaser.phase(KonanPhase.AUTOBOX) {
// validateIrFile(context, irFile) // Temporarily disabled until moving to new IR finished.
Autoboxing(context).lower(irFile)
}
phaser.phase(KonanPhase.RETURNS_INSERTION) {
ReturnsInsertionLowering(context).lower(irFile)
}
}
}
@@ -0,0 +1,309 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex
import org.jetbrains.kotlin.backend.konan.lower.*
import org.jetbrains.kotlin.backend.konan.lower.ExpectDeclarationsRemoving
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
import org.jetbrains.kotlin.backend.konan.lower.loops.ForLoopsLowering
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.checkDeclarationParents
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
private fun makeKonanFileLoweringPhase(
lowering: (Context) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet()
) = makeIrFilePhase(lowering, name, description, prerequisite)
private fun makeKonanModuleLoweringPhase(
lowering: (Context) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet()
) = makeIrModulePhase(lowering, name, description, prerequisite)
internal fun makeKonanFileOpPhase(
op: (Context, IrFile) -> Unit,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet()
) = namedIrFilePhase(
name, description, prerequisite, nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, IrFile> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrFile): IrFile {
op(context, input)
return input
}
}
)
internal fun makeKonanModuleOpPhase(
op: (Context, IrModuleFragment) -> Unit,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet()
) = namedIrModulePhase(
name, description, prerequisite, nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrModuleFragment): IrModuleFragment {
op(context, input)
return input
}
}
)
internal val removeExpectDeclarationsPhase = makeKonanModuleLoweringPhase(
::ExpectDeclarationsRemoving,
name = "RemoveExpectDeclarations",
description = "Expect declarations removing"
)
internal val lowerBeforeInlinePhase = makeKonanModuleLoweringPhase(
::PreInlineLowering,
name = "LowerBeforeInline",
description = "Special operations processing before inlining"
)
internal val inlinePhase = namedIrModulePhase(
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrModuleFragment): IrModuleFragment {
FunctionInlining(context).inline(input)
return input
}
},
name = "Inline",
description = "Functions inlining",
prerequisite = setOf(lowerBeforeInlinePhase),
nlevels = 0
)
internal val lowerAfterInlinePhase = makeKonanModuleOpPhase(
{ context, irModule ->
irModule.files.forEach(PostInlineLowering(context)::lower)
// TODO: Seems like this should be deleted in PsiToIR.
irModule.files.forEach(ContractsDslRemover(context)::lower)
},
name = "LowerAfterInline",
description = "Special operations processing after inlining"
)
internal val interopPart1Phase = makeKonanModuleLoweringPhase(
::InteropLoweringPart1,
name = "InteropPart1",
description = "Interop lowering, part 1",
prerequisite = setOf(inlinePhase)
)
internal val patchDeclarationParents1Phase = makeKonanModuleOpPhase(
{ _, irModule -> irModule.patchDeclarationParents() },
name = "PatchDeclarationParents1",
description = "Patch declaration parents 1"
)
internal val checkDeclarationParentsPhase = makeKonanModuleOpPhase(
{ _, irModule -> irModule.checkDeclarationParents() },
name = "CheckDeclarationParents",
description = "Check declaration parents"
)
internal val validateIrModulePhase = makeKonanModuleOpPhase(
{ context, irModule -> validateIrModule(context, irModule) },
name = "ValidateIrModule",
description = "Validate generated module"
)
internal val moduleIndexForCodegenPhase = makeKonanModuleOpPhase(
{ context, irModule -> context.ir.moduleIndexForCodegen = ModuleIndex(irModule) },
name = "ModuleIndexForCodeGen",
description = "Generate module index for codegen"
)
/* IrFile phases */
internal val lateinitPhase = makeKonanFileLoweringPhase(
::LateinitLowering,
name = "Lateinit",
description = "Lateinit properties lowering",
prerequisite = setOf(inlinePhase)
)
internal val stringConcatenationPhase = makeKonanFileLoweringPhase(
::StringConcatenationLowering,
name = "StringConcatenation",
description = "String concatenation lowering"
)
internal val enumConstructorsPhase = makeKonanFileLoweringPhase(
::EnumConstructorsLowering,
name = "EnumConstructors",
description = "Enum constructors lowering"
)
internal val initializersPhase = makeKonanFileLoweringPhase(
::InitializersLowering,
name = "Initializers",
description = "Initializers lowering",
prerequisite = setOf(enumConstructorsPhase)
)
internal val sharedVariablesPhase = makeKonanFileLoweringPhase(
::SharedVariablesLowering,
name = "SharedVariables",
description = "Shared Variable Lowering",
prerequisite = setOf(initializersPhase)
)
internal val localFunctionsPhase = makeKonanFileOpPhase(
op = { context, irFile ->
LocalDelegatedPropertiesLowering().lower(irFile)
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
},
name = "LocalFunctions",
description = "Local Function Lowering",
prerequisite = setOf(sharedVariablesPhase)
)
internal val tailrecPhase = makeKonanFileLoweringPhase(
::TailrecLowering,
name = "Tailrec",
description = "tailrec lowering",
prerequisite = setOf(localFunctionsPhase)
)
internal val defaultParameterExtentPhase = makeKonanFileOpPhase(
{ context, irFile ->
DefaultArgumentStubGenerator(context, skipInlineMethods = false).runOnFilePostfix(irFile)
KonanDefaultParameterInjector(context).lower(irFile)
},
name = "DefaultParameterExtent",
description = "Default Parameter Extent Lowering",
prerequisite = setOf(tailrecPhase, enumConstructorsPhase)
)
internal val innerClassPhase = makeKonanFileLoweringPhase(
::InnerClassLowering,
name = "InnerClasses",
description = "Inner classes lowering",
prerequisite = setOf(defaultParameterExtentPhase, genSyntheticFieldsPhase )
)
internal val forLoopsPhase = makeKonanFileLoweringPhase(
::ForLoopsLowering,
name = "ForLoops",
description = "For loops lowering"
)
internal val dataClassesPhase = makeKonanFileLoweringPhase(
::DataClassOperatorsLowering,
name = "DataClasses",
description = "Data classes lowering"
)
internal val builtinOperatorPhase = makeKonanFileLoweringPhase(
::BuiltinOperatorLowering,
name = "BuiltinOperators",
description = "BuiltIn Operators Lowering",
prerequisite = setOf(defaultParameterExtentPhase)
)
internal val finallyBlocksPhase = makeKonanFileLoweringPhase(
::FinallyBlocksLowering,
name = "FinallyBlocks",
description = "Finally blocks lowering",
prerequisite = setOf(initializersPhase, localFunctionsPhase, tailrecPhase)
)
internal val testProcessorPhase = makeKonanFileOpPhase(
{ context, irFile -> TestProcessor(context).process(irFile) },
name = "TestProcessor",
description = "Unit test processor"
)
internal val enumClassPhase = makeKonanFileOpPhase(
{ context, irFile -> EnumClassLowering(context).run(irFile) },
name = "Enums",
description = "Enum classes lowering",
prerequisite = setOf(enumConstructorsPhase) // TODO: make weak dependency on `testProcessorPhase`
)
internal val delegationPhase = makeKonanFileLoweringPhase(
::PropertyDelegationLowering,
name = "Delegation",
description = "Delegation lowering"
)
internal val callableReferencePhase = makeKonanFileLoweringPhase(
::CallableReferenceLowering,
name = "CallableReference",
description = "Callable references Lowering",
prerequisite = setOf(delegationPhase) // TODO: make weak dependency on `testProcessorPhase`
)
internal val interopPart2Phase = makeKonanFileLoweringPhase(
::InteropLoweringPart2,
name = "InteropPart2",
description = "Interop lowering, part 2",
prerequisite = setOf(localFunctionsPhase)
)
internal val varargPhase = makeKonanFileLoweringPhase(
::VarargInjectionLowering,
name = "Vararg",
description = "Vararg lowering",
prerequisite = setOf(callableReferencePhase, defaultParameterExtentPhase)
)
internal val compileTimeEvaluatePhase = makeKonanFileLoweringPhase(
::CompileTimeEvaluateLowering,
name = "CompileTimeEvaluate",
description = "Compile time evaluation lowering",
prerequisite = setOf(varargPhase)
)
internal val coroutinesPhase = makeKonanFileLoweringPhase(
::SuspendFunctionsLowering,
name = "Coroutines",
description = "Coroutines lowering",
prerequisite = setOf(localFunctionsPhase, finallyBlocksPhase)
)
internal val typeOperatorPhase = makeKonanFileLoweringPhase(
::TypeOperatorLowering,
name = "TypeOperators",
description = "Type operators lowering",
prerequisite = setOf(coroutinesPhase)
)
internal val bridgesPhase = makeKonanFileOpPhase(
{ context, irFile ->
BridgesBuilding(context).runOnFilePostfix(irFile)
WorkersBridgesBuilding(context).lower(irFile)
},
name = "Bridges",
description = "Bridges building",
prerequisite = setOf(coroutinesPhase)
)
internal val autoboxPhase = makeKonanFileOpPhase(
{ context, irFile ->
// validateIrFile(context, irFile) // Temporarily disabled until moving to new IR finished.
Autoboxing(context).lower(irFile)
},
name = "Autobox",
description = "Autoboxing of primitive types",
prerequisite = setOf(bridgesPhase, coroutinesPhase)
)
internal val returnsInsertionPhase = makeKonanFileLoweringPhase(
::ReturnsInsertionLowering,
name = "ReturnsInsertion",
description = "Returns insertion for Unit functions",
prerequisite = setOf(autoboxPhase, coroutinesPhase, enumClassPhase)
)
@@ -1,169 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.konan.util.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
enum class KonanPhase(val description: String,
vararg prerequisite: KonanPhase,
var enabled: Boolean = true,
var verbose: Boolean = false) {
/* */ FRONTEND("Frontend builds AST"),
/* */ PSI_TO_IR("Psi to IR conversion"),
/* */ IR_GENERATOR_PLUGINS("Plugged-in ir generators"),
/* */ GEN_SYNTHETIC_FIELDS("Generate synthetic fields"),
/* */ COPY_DEFAULT_VALUES_TO_ACTUAL("Copy default values from expect to actual declarations"),
/* */ SERIALIZER("Serialize descriptor tree and inline IR bodies", GEN_SYNTHETIC_FIELDS),
/* */ BACKEND("All backend"),
/* ... */ LOWER("IR Lowering"),
/* ... ... */ REMOVE_EXPECT_DECLARATIONS("Expect declarations removing"),
/* ... ... */ TEST_PROCESSOR("Unit test processor"),
/* ... ... */ LOWER_BEFORE_INLINE("Special operations processing before inlining"),
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_BEFORE_INLINE),
/* ... ... */ LOWER_AFTER_INLINE("Special operations processing after inlining"),
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
/* ... ... */ LOWER_FOR_LOOPS("For loops lowering"),
/* ... ... */ LOWER_ENUM_CONSTRUCTORS("Enum constructors lowering"),
/* ... ... */ LOWER_ENUMS("Enum classes lowering", LOWER_ENUM_CONSTRUCTORS/*TODO: make weak dependence on TEST_PROCESSOR*/),
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUM_CONSTRUCTORS),
/* ... ... */ LOWER_LATEINIT("Lateinit properties lowering", LOWER_INLINE),
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_DELEGATION/*TODO: make weak dependence on TEST_PROCESSOR*/),
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
/* ... ... */ LOWER_INTEROP_PART2("Interop lowering, part 2", LOWER_LOCAL_FUNCTIONS),
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUM_CONSTRUCTORS),
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES, LOWER_DEFAULT_PARAMETER_EXTENT),
/* ... ... */ LOWER_COMPILE_TIME_EVAL("Compile time evaluation lowering", LOWER_VARARG, enabled = false),
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT, GEN_SYNTHETIC_FIELDS),
/* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", LOWER_DEFAULT_PARAMETER_EXTENT),
/* ... ... */ LOWER_COROUTINES("Coroutines lowering", LOWER_LOCAL_FUNCTIONS, LOWER_FINALLY),
/* ... ... */ LOWER_TYPE_OPERATORS("Type operators lowering", LOWER_COROUTINES),
/* ... ... */ BRIDGES_BUILDING("Bridges building", LOWER_COROUTINES),
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
/* ... ... */ LOWER_DATA_CLASSES("Data classes lowering"),
/* ... ... */ AUTOBOX("Autoboxing of primitive types", BRIDGES_BUILDING, LOWER_COROUTINES),
/* ... ... */ RETURNS_INSERTION("Returns insertion for Unit functions", AUTOBOX, LOWER_COROUTINES, LOWER_ENUMS),
/* ... */ BITCODE("LLVM BitCode Generation"),
/* ... ... */ RTTI("RTTI Generation"),
/* ... ... */ BUILD_DFG("Data flow graph building", enabled = false),
/* ... ... */ DESERIALIZE_DFG("Data flow graph deserializing", enabled = false),
/* ... ... */ DEVIRTUALIZATION("Devirtualization", BUILD_DFG, DESERIALIZE_DFG, enabled = false),
/* ... ... */ ESCAPE_ANALYSIS("Escape analysis", BUILD_DFG, DESERIALIZE_DFG, enabled = false), // TODO: Requires devirtualization.
/* ... ... */ SERIALIZE_DFG("Data flow graph serializing", BUILD_DFG, enabled = false), // TODO: Requires escape analysis.
/* ... ... */ CODEGEN("Code Generation"),
/* ... ... */ C_STUBS("C stubs compilation"),
/* ... ... */ BITCODE_LINKER("Bitcode linking"),
/* */ LINK_STAGE("Link stage"),
/* ... */ OBJECT_FILES("Bitcode to object file"),
/* ... */ LINKER("Linker");
val prerequisite = prerequisite.toSet()
}
object KonanPhases {
val phases = KonanPhase.values().associate { it.visibleName to it }
fun known(name: String): String {
if (phases[name] == null) {
error("Unknown phase: $name. Use --list_phases to see the list of phases.")
}
return name
}
fun config(config: KonanConfig) {
with (config.configuration) { with (KonanConfigKeys) {
// Don't serialize anything to a final executable.
KonanPhase.SERIALIZER.enabled =
(config.produce == CompilerOutputKind.LIBRARY)
KonanPhase.LINK_STAGE.enabled = config.produce.isNativeBinary
KonanPhase.TEST_PROCESSOR.enabled =
getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) != TestRunnerKind.NONE
val disabled = get(DISABLED_PHASES)
disabled?.forEach { phases[known(it)]!!.enabled = false }
val enabled = get(ENABLED_PHASES)
enabled?.forEach { phases[known(it)]!!.enabled = true }
val verbose = get(VERBOSE_PHASES)
verbose?.forEach { phases[known(it)]!!.verbose = true }
}}
}
fun list() {
phases.forEach { key, phase ->
val enabled = if (phase.enabled) "(Enabled)" else ""
val verbose = if (phase.verbose) "(Verbose)" else ""
println(String.format("%1$-30s%2$-30s%3$-10s", "${key}:", phase.description, "$enabled $verbose"))
}
}
}
internal class PhaseManager(val context: Context, val parent: PhaseManager? = null) {
val previousPhases = mutableSetOf<KonanPhase>()
fun createChild() = PhaseManager(context, this)
private fun checkPrerequisite(phase: KonanPhase): Boolean =
previousPhases.contains(phase) || parent?.checkPrerequisite(phase) == true
fun phase(phase: KonanPhase, body: () -> Unit) {
if (!phase.enabled) return
phase.prerequisite.forEach {
if (!checkPrerequisite(it))
throw Error("$phase requires $it")
}
previousPhases.add(phase)
val savePhase = context.phase
context.phase = phase
context.depth ++
with (context) {
profileIf(shouldProfilePhases(), "Phase ${nTabs(depth)} ${phase.name}") {
body()
}
if (shouldVerifyDescriptors()) {
verifyDescriptors()
}
if (shouldVerifyIr()) {
verifyIr()
}
if (shouldPrintDescriptors()) {
printDescriptors()
}
if (shouldPrintIr()) {
printIr()
}
if (shouldPrintIrWithDescriptors()) {
printIrWithDescriptors()
}
if (shouldPrintLocations()) {
printLocations()
}
}
context.depth --
context.phase = savePhase
}
}
@@ -15,7 +15,7 @@ typealias BitcodeFile = String
typealias ObjectFile = String
typealias ExecutableFile = String
internal class LinkStage(val context: Context, val phaser: PhaseManager) {
internal class LinkStage(val context: Context) {
private val config = context.config.configuration
private val target = context.config.target
@@ -122,7 +122,7 @@ internal class LinkStage(val context: Context, val phaser: PhaseManager) {
if (context.shouldProfilePhases()) {
flags += "-time-passes"
}
if (context.phase?.verbose == true) {
if (context.inVerbosePhase) {
flags += "-debug-pass=Structure"
}
return flags
@@ -197,33 +197,29 @@ internal class LinkStage(val context: Context, val phaser: PhaseManager) {
return executable
}
fun linkStage() {
val objectFiles = mutableListOf<String>()
fun makeObjectFiles() {
val bitcodeFiles = listOf(emitted) +
libraries.map { it.bitcodePaths }.flatten().filter { it.isBitcode }
objectFiles.add(when (platform.configurables) {
is WasmConfigurables
-> bitcodeToWasm(bitcodeFiles)
is ZephyrConfigurables
-> llvmLinkAndLlc(bitcodeFiles)
else
-> llvmLto(bitcodeFiles)
})
}
fun linkStage() {
val includedBinaries =
libraries.map { it.includedPaths }.flatten()
val libraryProvidedLinkerFlags =
libraries.map { it.linkerOpts }.flatten()
val objectFiles: MutableList<String> = mutableListOf()
phaser.phase(KonanPhase.OBJECT_FILES) {
objectFiles.add(
when (platform.configurables) {
is WasmConfigurables
-> bitcodeToWasm(bitcodeFiles)
is ZephyrConfigurables
-> llvmLinkAndLlc(bitcodeFiles)
else
-> llvmLto(bitcodeFiles)
}
)
}
phaser.phase(KonanPhase.LINKER) {
link(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
}
link(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
}
}
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.descriptors.konan.isKonanStdlib
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolveResult
import org.jetbrains.kotlin.konan.util.visibleName
import org.jetbrains.kotlin.konan.utils.KonanFactories
import org.jetbrains.kotlin.konan.utils.KonanFactories.DefaultDescriptorFactory
import org.jetbrains.kotlin.name.Name
@@ -28,16 +27,17 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProvid
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptors
import org.jetbrains.kotlin.storage.StorageManager
object TopDownAnalyzerFacadeForKonan {
internal object TopDownAnalyzerFacadeForKonan {
fun analyzeFiles(files: Collection<KtFile>, config: KonanConfig): AnalysisResult {
fun analyzeFiles(files: Collection<KtFile>, context: Context): AnalysisResult {
val config = context.config
val moduleName = Name.special("<${config.moduleId}>")
val projectContext = ProjectContext(config.project)
val module = DefaultDescriptorFactory.createDescriptorAndNewBuiltIns(
moduleName, projectContext.storageManager, origin = CurrentKonanModuleOrigin)
val context = MutableModuleContextImpl(module, projectContext)
val moduleContext = MutableModuleContextImpl(module, projectContext)
val resolvedDependencies = ResolvedDependencies(
config.resolvedLibraries,
@@ -51,28 +51,28 @@ object TopDownAnalyzerFacadeForKonan {
module.setDependencies(dependencies, resolvedDependencies.friends)
} else {
assert (resolvedDependencies.moduleDescriptors.resolvedDescriptors.isEmpty())
context.setDependencies(module)
moduleContext.setDependencies(module)
}
return analyzeFilesWithGivenTrace(files, BindingTraceContext(), context, config)
return analyzeFilesWithGivenTrace(files, BindingTraceContext(), moduleContext, context)
}
fun analyzeFilesWithGivenTrace(
files: Collection<KtFile>,
trace: BindingTrace,
moduleContext: ModuleContext,
config: KonanConfig
context: Context
): AnalysisResult {
// we print out each file we compile if frontend phase is verbose
files.takeIf { with (KonanPhases) {
phases[known(KonanPhase.FRONTEND.visibleName)]!!.verbose
}} ?.forEach(::println)
files.takeIf {
frontendPhase in context.phaseConfig.verbose
} ?.forEach(::println)
val analyzerForKonan = createTopDownAnalyzerForKonan(
moduleContext, trace,
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
config.configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!
context.config.configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!
)
analyzerForKonan.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
@@ -0,0 +1,262 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
import org.jetbrains.kotlin.backend.konan.serialization.*
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import java.util.Collections.emptySet
internal fun konanUnitPhase(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(),
op: Context.() -> Unit
) = namedOpUnitPhase(name, description, prerequisite, op)
internal val frontendPhase = konanUnitPhase(
op = {
val environment = environment
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector,
environment.configuration.languageVersionSettings)
// Build AST and binding info.
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles()) {
TopDownAnalyzerFacadeForKonan.analyzeFiles(environment.getSourceFiles(), this)
}
if (analyzerWithCompilerReport.hasErrors()) {
throw KonanCompilationException()
}
moduleDescriptor = analyzerWithCompilerReport.analysisResult.moduleDescriptor
bindingContext = analyzerWithCompilerReport.analysisResult.bindingContext
},
name = "Frontend",
description = "Frontend builds AST"
)
internal val psiToIrPhase = konanUnitPhase(
op = {
// Translate AST to high level IR.
val translator = Psi2IrTranslator(config.configuration.languageVersionSettings,
Psi2IrConfiguration(false))
val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext)
@Suppress("DEPRECATION")
psi2IrGeneratorContext = generatorContext
val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule }
val deserializer = KonanIrModuleDeserializer(
moduleDescriptor,
this as LoggingContext,
generatorContext.irBuiltIns,
generatorContext.symbolTable,
forwardDeclarationsModuleDescriptor
)
val irModules = moduleDescriptor.allDependencyModules.map {
val library = it.konanLibrary
if (library == null) {
return@map null
}
library.irHeader?.let { header -> deserializer.deserializeIrModule(it, header) }
}.filterNotNull()
val symbols = KonanSymbols(this, generatorContext.symbolTable, generatorContext.symbolTable.lazyWrapper)
val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles(), deserializer)
irModules.forEach {
it.patchDeclarationParents()
}
irModule = module
ir.symbols = symbols
// validateIrModule(this, module)
},
name = "Psi2Ir",
description = "Psi to IR conversion"
)
internal val irGeneratorPluginsPhase = konanUnitPhase(
op = {
val extensions = IrGenerationExtension.getInstances(config.project)
extensions.forEach { extension ->
irModule!!.files.forEach {
irFile -> extension.generate(irFile, this, bindingContext)
}
}
},
name = "IrGeneratorPlugins",
description = "Plugged-in ir generators"
)
internal val genSyntheticFieldsPhase = konanUnitPhase(
op = { markBackingFields(this) },
name = "GenSyntheticFields",
description = "Generate synthetic fields"
)
// TODO: We copy default value expressions from expects to actuals before IR serialization,
// because the current infrastructure doesn't allow us to get them at deserialization stage.
// That requires some design and implementation work.
internal val copyDefaultValuesToActualPhase = konanUnitPhase(
op = {
irModule!!.files.forEach(ExpectToActualDefaultValueCopier(this)::lower)
},
name = "CopyDefaultValuesToActual",
description = "Copy default values from expect to actual declarations"
)
internal val patchDeclarationParents0Phase = konanUnitPhase(
op = { irModule!!.patchDeclarationParents() }, // why do we need it?
name = "PatchDeclarationParents0",
description = "Patch declaration parents"
)
internal val serializerPhase = konanUnitPhase(
op = {
val declarationTable = DeclarationTable(irModule!!.irBuiltins, DescriptorTable())
val serializedIr = IrModuleSerializer(
this, declarationTable, bodiesOnlyForInlines = config.isInteropStubs).serializedIrModule(irModule!!)
val serializer = KonanSerializationUtil(this, config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
serializedLinkData =
serializer.serializeModule(moduleDescriptor, /*if (!config.isInteropStubs) serializedIr else null*/ serializedIr)
},
name = "Serializer",
description = "Serialize descriptor tree and inline IR bodies",
prerequisite = setOf(genSyntheticFieldsPhase)
)
internal val setUpLinkStagePhase = konanUnitPhase(
op = { linkStage = LinkStage(this) },
name = "SetUpLinkStage",
description = "Set up link stage"
)
internal val objectFilesPhase = konanUnitPhase(
op = { linkStage.makeObjectFiles() },
name = "ObjectFiles",
description = "Bitcode to object file"
)
internal val linkerPhase = konanUnitPhase(
op = { linkStage.linkStage() },
name = "Linker",
description = "Linker"
)
internal val linkPhase = namedUnitPhase(
name = "Link",
description = "Link stage",
lower = setUpLinkStagePhase then
objectFilesPhase then
linkerPhase
)
internal val toplevelPhase = namedUnitPhase(
name = "Compiler",
description = "The whole compilation process",
lower = frontendPhase then
psiToIrPhase then
irGeneratorPluginsPhase then
genSyntheticFieldsPhase then
copyDefaultValuesToActualPhase then
patchDeclarationParents0Phase then
serializerPhase then
namedUnitPhase(
name = "Backend",
description = "All backend",
lower = takeFromContext<Context, Unit, IrModuleFragment> { it.irModule!! } then
namedIrModulePhase(
name = "IrLowering",
description = "IR Lowering",
lower = removeExpectDeclarationsPhase then
lowerBeforeInlinePhase then
inlinePhase then
lowerAfterInlinePhase then
interopPart1Phase then
patchDeclarationParents1Phase then
performByIrFile(
name = "IrLowerByFile",
description = "IR Lowering by file",
lower = lateinitPhase then
stringConcatenationPhase then
enumConstructorsPhase then
initializersPhase then
sharedVariablesPhase then
localFunctionsPhase then
tailrecPhase then
defaultParameterExtentPhase then
innerClassPhase then
forLoopsPhase then
dataClassesPhase then
builtinOperatorPhase then
finallyBlocksPhase then
testProcessorPhase then
enumClassPhase then
delegationPhase then
callableReferencePhase then
interopPart2Phase then
varargPhase then
compileTimeEvaluatePhase then
coroutinesPhase then
typeOperatorPhase then
bridgesPhase then
autoboxPhase then
returnsInsertionPhase
) then
checkDeclarationParentsPhase then
// validateIrModulePhase then // Temporarily disabled until moving to new IR finished.
moduleIndexForCodegenPhase
) then
namedIrModulePhase(
name = "Bitcode",
description = "LLVM BitCode Generation",
lower = contextLLVMSetupPhase then
RTTIPhase then
generateDebugInfoHeaderPhase then
buildDFGPhase then
deserializeDFGPhase then
devirtualizationPhase then
escapeAnalysisPhase then
serializeDFGPhase then
codegenPhase then
finalizeDebugInfoPhase then
cStubsPhase then
bitcodeLinkerPhase
) then
verifyBitcodePhase then
printBitcodePhase
then
unitSink()
) then
linkPhase
)
internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
with(config.configuration) {
disable(compileTimeEvaluatePhase)
disable(buildDFGPhase)
disable(deserializeDFGPhase)
disable(devirtualizationPhase)
disable(escapeAnalysisPhase)
disable(serializeDFGPhase)
// Don't serialize anything to a final executable.
switch(serializerPhase, config.produce == CompilerOutputKind.LIBRARY)
switch(linkPhase, config.produce.isNativeBinary)
switch(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) != TestRunnerKind.NONE)
}
}
@@ -0,0 +1,175 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan.llvm
import llvm.*
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.optimizations.*
import org.jetbrains.kotlin.ir.visitors.acceptVoid
internal val contextLLVMSetupPhase = makeKonanModuleOpPhase(
name = "ContextLLVMSetup",
description = "Set up Context for LLVM bitcode generation",
op = { context, _ ->
// Note that we don't set module target explicitly.
// It is determined by the target of runtime.bc
// (see Llvm class in ContextUtils)
// Which in turn is determined by the clang flags
// used to compile runtime.bc.
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
context.llvmModule = llvmModule
context.debugInfo.builder = DICreateBuilder(llvmModule)
context.llvmDeclarations = createLlvmDeclarations(context)
context.lifetimes = mutableMapOf()
context.codegenVisitor = CodeGeneratorVisitor(context, context.lifetimes)
}
)
internal val RTTIPhase = makeKonanModuleOpPhase(
name = "RTTI",
description = "RTTI Generation",
op = { context, irModule -> irModule.acceptVoid(RTTIGeneratorVisitor(context)) }
)
internal val generateDebugInfoHeaderPhase = makeKonanModuleOpPhase(
name = "GenerateDebugInfoHeader",
description = "Generate debug info header",
op = { context, _ -> generateDebugInfoHeader(context) }
)
internal val buildDFGPhase = makeKonanModuleOpPhase(
name = "BuildDFG",
description = "Data flow graph building",
op = { context, irModule ->
context.moduleDFG = ModuleDFGBuilder(context, irModule).build()
}
)
internal val deserializeDFGPhase = makeKonanModuleOpPhase(
name = "DeserializeDFG",
description = "Data flow graph deserializing",
op = { context, _ ->
context.externalModulesDFG = DFGSerializer.deserialize(
context,
context.moduleDFG!!.symbolTable.privateTypeIndex,
context.moduleDFG!!.symbolTable.privateFunIndex
)
}
)
internal val devirtualizationPhase = makeKonanModuleOpPhase(
name = "Devirtualization",
description = "Devirtualization",
prerequisite = setOf(buildDFGPhase, deserializeDFGPhase),
op = { context, irModule ->
context.externalModulesDFG?.let { externalModulesDFG ->
context.devirtualizationAnalysisResult = Devirtualization.run(
irModule, context, context.moduleDFG!!, externalModulesDFG
)
val privateFunctions = context.moduleDFG!!.symbolTable.getPrivateFunctionsTableForExport()
privateFunctions.forEachIndexed { index, it ->
val function = context.codegenVisitor.codegen.llvmFunction(it.first)
LLVMAddAlias(
context.llvmModule,
function.type,
function,
irModule.descriptor.privateFunctionSymbolName(index, it.second.name)
)!!
}
context.privateFunctions = privateFunctions
val privateClasses = context.moduleDFG!!.symbolTable.getPrivateClassesTableForExport()
privateClasses.forEachIndexed { index, it ->
val typeInfoPtr = context.codegenVisitor.codegen.typeInfoValue(it.first)
LLVMAddAlias(
context.llvmModule,
typeInfoPtr.type,
typeInfoPtr,
irModule.descriptor.privateClassSymbolName(index, it.second.name)
)!!
}
context.privateClasses = privateClasses
}
}
)
internal val escapeAnalysisPhase = makeKonanModuleOpPhase(
// Disabled by default !!!!
name = "EscapeAnalysis",
description = "Escape analysis",
prerequisite = setOf(buildDFGPhase, deserializeDFGPhase), // TODO: Requires devirtualization.
op = { context, _ ->
context.externalModulesDFG?.let { externalModulesDFG ->
val callGraph = CallGraphBuilder(
context, context.moduleDFG!!,
externalModulesDFG,
context.devirtualizationAnalysisResult,
false
).build()
EscapeAnalysis.computeLifetimes(
context, context.moduleDFG!!, externalModulesDFG, callGraph, context.lifetimes
)
}
}
)
internal val serializeDFGPhase = makeKonanModuleOpPhase(
name = "SerializeDFG",
description = "Data flow graph serializing",
prerequisite = setOf(buildDFGPhase), // TODO: Requires escape analysis.
op = { context, _ ->
DFGSerializer.serialize(context, context.moduleDFG!!)
}
)
internal val codegenPhase = makeKonanModuleOpPhase(
name = "Codegen",
description = "Code Generation",
op = { context, irModule ->
irModule.acceptVoid(context.codegenVisitor)
}
)
internal val finalizeDebugInfoPhase = makeKonanModuleOpPhase(
name = "FinalizeDebugInfo",
description = "Finalize debug info",
op = { context, _ ->
if (context.shouldContainDebugInfo()) {
DIFinalize(context.debugInfo.builder)
}
}
)
internal val cStubsPhase = makeKonanModuleOpPhase(
name = "CStubs",
description = "C stubs compilation",
op = { context, _ -> produceCStubs(context) }
)
internal val bitcodeLinkerPhase = makeKonanModuleOpPhase(
name = "BitcodeLinker",
description = "Bitcode linking",
op = { context, _ -> produceOutput(context) }
)
internal val verifyBitcodePhase = makeKonanModuleOpPhase(
name = "VerifyBitcode",
description = "Verify bitcode",
op = { context, _ -> context.verifyBitCode() }
)
internal val printBitcodePhase = makeKonanModuleOpPhase(
name = "PrintBitcode",
description = "Print bitcode",
op = { context, _ ->
if (context.shouldPrintBitCode()) {
context.printBitCode()
}
}
)
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
@@ -80,92 +79,6 @@ val IrField.isMainOnlyNonPrimitive get() = when {
else -> storageClass == FieldStorage.MAIN_THREAD
}
internal fun emitLLVM(context: Context, phaser: PhaseManager) {
val irModule = context.irModule!!
// Note that we don't set module target explicitly.
// It is determined by the target of runtime.bc
// (see Llvm class in ContextUtils)
// Which in turn is determined by the clang flags
// used to compile runtime.bc.
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
context.llvmModule = llvmModule
context.debugInfo.builder = DICreateBuilder(llvmModule)
context.llvmDeclarations = createLlvmDeclarations(context)
phaser.phase(KonanPhase.RTTI) {
irModule.acceptVoid(RTTIGeneratorVisitor(context))
}
generateDebugInfoHeader(context)
var moduleDFG: ModuleDFG? = null
phaser.phase(KonanPhase.BUILD_DFG) {
moduleDFG = ModuleDFGBuilder(context, irModule).build()
}
val lifetimes = mutableMapOf<IrElement, Lifetime>()
val codegenVisitor = CodeGeneratorVisitor(context, lifetimes)
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
var externalModulesDFG: ExternalModulesDFG? = null
phaser.phase(KonanPhase.DESERIALIZE_DFG) {
externalModulesDFG = DFGSerializer.deserialize(context, moduleDFG!!.symbolTable.privateTypeIndex, moduleDFG!!.symbolTable.privateFunIndex)
}
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
var devirtualizationAnalysisResult: Devirtualization.AnalysisResult? = null
phaser.phase(KonanPhase.DEVIRTUALIZATION) {
externalModulesDFG?.let { externalModulesDFG ->
devirtualizationAnalysisResult = Devirtualization.run(irModule, context, moduleDFG!!, externalModulesDFG)
val privateFunctions = moduleDFG!!.symbolTable.getPrivateFunctionsTableForExport()
privateFunctions.forEachIndexed { index, it ->
val function = codegenVisitor.codegen.llvmFunction(it.first)
LLVMAddAlias(
context.llvmModule,
function.type,
function,
irModule.descriptor.privateFunctionSymbolName(index, it.second.name)
)!!
}
context.privateFunctions = privateFunctions
val privateClasses = moduleDFG!!.symbolTable.getPrivateClassesTableForExport()
privateClasses.forEachIndexed { index, it ->
val typeInfoPtr = codegenVisitor.codegen.typeInfoValue(it.first)
LLVMAddAlias(
context.llvmModule,
typeInfoPtr.type,
typeInfoPtr,
irModule.descriptor.privateClassSymbolName(index, it.second.name)
)!!
}
context.privateClasses = privateClasses
}
}
phaser.phase(KonanPhase.ESCAPE_ANALYSIS) {
externalModulesDFG?.let { externalModulesDFG ->
val callGraph = CallGraphBuilder(context, moduleDFG!!, externalModulesDFG, devirtualizationAnalysisResult, false).build()
EscapeAnalysis.computeLifetimes(context, moduleDFG!!, externalModulesDFG, callGraph, lifetimes)
}
}
phaser.phase(KonanPhase.SERIALIZE_DFG) {
DFGSerializer.serialize(context, moduleDFG!!)
}
phaser.phase(KonanPhase.CODEGEN) {
irModule.acceptVoid(codegenVisitor)
}
if (context.shouldContainDebugInfo()) {
DIFinalize(context.debugInfo.builder)
}
}
internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") {
memScoped {
val errorRef = allocPointerTo<ByteVar>()