diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 7aedc140528..37ccbf824e4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -27,7 +27,7 @@ val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) { CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false } -internal fun produceOutput(context: Context) { +internal fun produceOutput(context: Context, phaser: PhaseManager) { val llvmModule = context.llvmModule!! val config = context.config.configuration @@ -56,7 +56,7 @@ internal fun produceOutput(context: Context) { context.config.defaultNativeLibraries + generatedBitcodeFiles - PhaseManager(context).phase(KonanPhase.BITCODE_LINKER) { + phaser.phase(KonanPhase.BITCODE_LINKER) { for (library in nativeLibraries) { val libraryModule = parseBitcodeFile(library) val failed = LLVMLinkModules2(llvmModule, libraryModule) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt index f3e2ab7f978..79a36bd39cb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt @@ -52,7 +52,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme val analyzerWithCompilerReport = AnalyzerWithCompilerReport(context.messageCollector, environment.configuration.languageVersionSettings) - val phaser = PhaseManager(context) + val phaser = PhaseManager(context, null) phaser.phase(KonanPhase.FRONTEND) { // Build AST and binding info. @@ -84,21 +84,23 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme // validateIrModule(context, module) } - phaser.phase(KonanPhase.SERIALIZER) { + phaser.phase(KonanPhase.GEN_SYNTHETIC_FIELDS) { markBackingFields(context) + } + phaser.phase(KonanPhase.SERIALIZER) { val serializer = KonanSerializationUtil(context, context.config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!) context.serializedLinkData = serializer.serializeModule(context.moduleDescriptor) } phaser.phase(KonanPhase.BACKEND) { phaser.phase(KonanPhase.LOWER) { - KonanLower(context).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) - produceOutput(context) + emitLLVM(context, phaser) + produceOutput(context, phaser) } // We always verify bitcode to prevent hard to debug bugs. context.verifyBitCode() @@ -109,7 +111,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme } phaser.phase(KonanPhase.LINK_STAGE) { - LinkStage(context).linkStage() + LinkStage(context, phaser).linkStage() } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 9ef4a9c143b..019d7032e16 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -28,25 +28,23 @@ 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) { +internal class KonanLower(val context: Context, val parentPhaser: PhaseManager) { fun lower() { val irModule = context.irModule!! // Phases to run against whole module. - lowerModule(irModule) + lowerModule(irModule, parentPhaser) // Phases to run against a file. irModule.files.forEach { - lowerFile(it) + lowerFile(it, PhaseManager(context, parentPhaser)) } irModule.checkDeclarationParents() } - private fun lowerModule(irModule: IrModuleFragment) { - val phaser = PhaseManager(context) - + private fun lowerModule(irModule: IrModuleFragment, phaser: PhaseManager) { phaser.phase(KonanPhase.REMOVE_EXPECT_DECLARATIONS) { irModule.files.forEach(ExpectDeclarationsRemoving(context)::lower) } @@ -90,9 +88,7 @@ internal class KonanLower(val context: Context) { // validateIrModule(context, irModule) // Temporarily disabled until moving to new IR finished. } - private fun lowerFile(irFile: IrFile) { - val phaser = PhaseManager(context) - + private fun lowerFile(irFile: IrFile, phaser: PhaseManager) { phaser.phase(KonanPhase.LOWER_STRING_CONCAT) { StringConcatenationLowering(context).lower(irFile) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt index ecf7af8c3ce..e9663be130a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt @@ -25,7 +25,8 @@ enum class KonanPhase(val description: String, var verbose: Boolean = false) { /* */ FRONTEND("Frontend builds AST"), /* */ PSI_TO_IR("Psi to IR conversion"), - /* */ SERIALIZER("Serialize descriptor tree and inline IR bodies"), + /* */ GEN_SYNTHETIC_FIELDS("Generate synthetic fields"), + /* */ SERIALIZER("Serialize descriptor tree and inline IR bodies", GEN_SYNTHETIC_FIELDS), /* */ BACKEND("All backend"), /* ... */ LOWER("IR Lowering"), /* ... ... */ REMOVE_EXPECT_DECLARATIONS("Expect declarations removing"), @@ -49,7 +50,7 @@ enum class KonanPhase(val description: String, /* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUMS), /* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES, LOWER_DEFAULT_PARAMETER_EXTENT), /* ... ... */ LOWER_COMPILE_TIME_EVAL("Compile time evaluation lowering", LOWER_VARARG), - /* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT), + /* ... ... */ 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_TYPE_OPERATORS("Type operators lowering", LOWER_COROUTINES), @@ -115,16 +116,21 @@ object KonanPhases { } } -internal class PhaseManager(val context: Context) { +internal class PhaseManager(val context: Context, val parent: PhaseManager? = null) { val previousPhases = mutableSetOf() - internal fun phase(phase: KonanPhase, body: () -> Unit) { + 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 (!previousPhases.contains(it)) + if (!checkPrerequisite(it)) throw Error("$phase requires $it") } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index cff9072a462..8a63b661302 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -26,7 +26,7 @@ typealias BitcodeFile = String typealias ObjectFile = String typealias ExecutableFile = String -internal class LinkStage(val context: Context) { +internal class LinkStage(val context: Context, val phaser: PhaseManager) { private val config = context.config.configuration private val target = context.config.target @@ -228,7 +228,6 @@ internal class LinkStage(val context: Context) { val objectFiles: MutableList = mutableListOf() - val phaser = PhaseManager(context) phaser.phase(KonanPhase.OBJECT_FILES) { objectFiles.add( when (platform.configurables) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 4d4b26f13e6..7729ca45707 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -51,7 +51,7 @@ private val threadLocalAnnotationFqName = FqName("konan.ThreadLocal") val IrClassSymbol.objectIsShared get() = !descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) -internal fun emitLLVM(context: Context) { +internal fun emitLLVM(context: Context, phaser: PhaseManager) { val irModule = context.irModule!! // Note that we don't set module target explicitly. @@ -64,8 +64,6 @@ internal fun emitLLVM(context: Context) { context.debugInfo.builder = DICreateBuilder(llvmModule) context.llvmDeclarations = createLlvmDeclarations(context) - val phaser = PhaseManager(context) - phaser.phase(KonanPhase.RTTI) { irModule.acceptVoid(RTTIGeneratorVisitor(context)) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt index b656c875970..b18b4cfea1c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -32,7 +32,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.util.addChild import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver @@ -56,9 +55,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { } private fun createOuterThisField() { - val field = context.specialDeclarationsFactory.getOuterThisField(irClass) - outerThisFieldSymbol = field.symbol - irClass.addChild(field) + outerThisFieldSymbol = context.specialDeclarationsFactory.getOuterThisField(irClass).symbol } private fun lowerConstructors() { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt index f5ecfe9b883..fbff792e143 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt @@ -17,13 +17,12 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.addChild import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -34,6 +33,8 @@ internal class BackingFieldVisitor(val context: Context) : IrElementVisitorVoid } override fun visitProperty(declaration: IrProperty) { + super.visitProperty(declaration) + if (declaration.isDelegated) { val irClass = declaration.parent as? IrClass val list = irClass?.let { context.ir.classesDelegatedBackingFields.getOrPut(irClass.descriptor) { mutableListOf() } } @@ -46,10 +47,15 @@ internal class BackingFieldVisitor(val context: Context) : IrElementVisitorVoid } override fun visitClass(declaration: IrClass) { + if (declaration.isInner) + declaration.addChild(context.specialDeclarationsFactory.getOuterThisField(declaration)) + + // Mark all dangling fields (they are created when class is inherited via delegation). declaration.declarations.filterIsInstance().forEach { val list = context.ir.classesDelegatedBackingFields.getOrPut(declaration.descriptor) { mutableListOf() } list.add(it.descriptor) } + super.visitClass(declaration) } }