From e3efd75e557874fe105e74bdd880b30a4b8e55ff Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 19 Feb 2019 12:43:37 +0500 Subject: [PATCH] Implemented code generation of combined IR of all libraries --- backend.native/build.gradle | 19 +- .../kotlin/backend/konan/CompilerOutput.kt | 14 +- .../jetbrains/kotlin/backend/konan/Context.kt | 27 +-- .../kotlin/backend/konan/KonanConfig.kt | 3 +- .../backend/konan/KonanLoweringPhases.kt | 2 +- .../kotlin/backend/konan/RuntimeNames.kt | 2 + .../kotlin/backend/konan/ToplevelPhases.kt | 212 +++++++++++------- .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 1 - .../konan/irasdescriptors/NewIrUtils.kt | 31 +-- .../library/impl/KonanLibraryWriterImpl.kt | 4 +- .../backend/konan/llvm/BinaryInterface.kt | 2 +- .../backend/konan/llvm/BitcodePhases.kt | 6 +- .../kotlin/backend/konan/llvm/ContextUtils.kt | 20 +- .../kotlin/backend/konan/llvm/EntryPoint.kt | 5 +- .../backend/konan/llvm/IntrinsicGenerator.kt | 8 + .../kotlin/backend/konan/llvm/IrToBitcode.kt | 9 - .../kotlin/backend/konan/llvm/LlvmUtils.kt | 2 +- .../backend/konan/llvm/StaticObjects.kt | 9 - .../lower/DeepCopyIrTreeWithDescriptors.kt | 2 +- .../backend/konan/lower/EnumClassLowering.kt | 2 +- .../konan/lower/EnumConstructorsLowering.kt | 2 +- .../backend/konan/lower/EnumWhenLowering.kt | 2 +- .../konan/lower/FinallyBlocksLowering.kt | 28 ++- .../backend/konan/lower/FunctionInlining.kt | 3 + .../backend/konan/lower/InnerClassLowering.kt | 1 + .../backend/konan/lower/InteropLowering.kt | 2 +- .../serialization/BackingFieldVisitor.kt | 54 ----- .../konan/serialization/IrModuleSerializer.kt | 26 +++ .../backend/konan/serialization/KonanIr.proto | 2 + .../KonanIrModuleDeserializer.kt | 25 ++- .../serialization/KonanSerializerExtension.kt | 2 - build.gradle | 5 - runtime/src/launcher/kotlin/konan/start.kt | 8 +- runtime/src/main/cpp/Exceptions.cpp | 2 +- .../kotlin/native/internal/IntrinsicType.kt | 1 + .../kotlin/konan/target/Distribution.kt | 2 +- 36 files changed, 268 insertions(+), 277 deletions(-) delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 7d3277adeaa..eab2e091f5f 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -153,7 +153,6 @@ classes.dependsOn 'compilerClasses', 'cli_bcClasses', 'bc_frontendClasses' // These are just a couple of aliases task stdlib(dependsOn: "${hostName}Stdlib") -task start(dependsOn: "${hostName}Start") def commonSrc = file('build/stdlib') @@ -180,7 +179,8 @@ final List stdLibSrc = [ project(':Interop:Runtime').file('src/main/kotlin'), project(':Interop:Runtime').file('src/native/kotlin'), project(':Interop:JsRuntime').file('src/main/kotlin'), - project(':runtime').file('src/main/kotlin') + project(':runtime').file('src/main/kotlin'), + project(':runtime').file('src/launcher/kotlin') ] task zipStdLibSources(type: Zip, dependsOn: unzipStdlibSources) { @@ -244,21 +244,6 @@ targetList.each { target -> dependsOn ":runtime:${target}Runtime" dependsOn ":distCompiler" } - - task("${target}Start", type: JavaExec) { - main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt' - classpath = project.configurations.cli_bc - jvmArgs = konanJvmArgs - args = [*konanArgs, '-produce', 'bitcode', - '-output', project(':runtime').file("build/${target}Start"), - '-library', project(':runtime').file("build/${target}Stdlib"), - project(':runtime').file('src/launcher/kotlin')] - - inputs.dir(project(':runtime').file('src/launcher/kotlin')) - outputs.file(project(':runtime').file("build/${target}Start.bc")) - - dependsOn ":runtime:${target}Runtime", "${target}Stdlib" - } } task run { 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 a475d8cfed5..04593f1bb0a 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 @@ -29,7 +29,6 @@ internal fun produceCStubs(context: Context) { 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) @@ -42,7 +41,7 @@ internal fun produceOutput(context: Context) { val output = tempFiles.nativeBinaryFileName context.bitcodeFileName = output - val generatedBitcodeFiles = + val generatedBitcodeFiles = if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) { produceCAdapterBitcode( context.config.clang, @@ -57,16 +56,15 @@ internal fun produceOutput(context: Context) { generatedBitcodeFiles for (library in nativeLibraries) { - parseAndLinkBitcodeFile(llvmModule, library) + parseAndLinkBitcodeFile(context.llvmModule!!, library) } - LLVMWriteBitcodeToFile(llvmModule, output) + LLVMWriteBitcodeToFile(context.llvmModule!!, output) } CompilerOutputKind.LIBRARY -> { val output = context.config.outputFiles.outputName val libraryName = context.config.moduleId - val neededLibraries - = context.llvm.librariesForLibraryManifest + val neededLibraries = context.librariesWithDependencies val abiVersion = KonanAbiVersion.CURRENT val compilerVersion = KonanVersion.CURRENT val libraryVersion = config.get(KonanConfigKeys.LIBRARY_VERSION) @@ -85,7 +83,7 @@ internal fun produceOutput(context: Context) { target, output, libraryName, - llvmModule, + null, nopack, manifestProperties, context.dataFlowGraph) @@ -96,7 +94,7 @@ internal fun produceOutput(context: Context) { CompilerOutputKind.BITCODE -> { val output = context.config.outputFile context.bitcodeFileName = output - LLVMWriteBitcodeToFile(llvmModule, output) + LLVMWriteBitcodeToFile(context.llvmModule!!, output) } } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index d90390d90c8..f6914dec856 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -99,7 +99,9 @@ internal class SpecialDeclarationsFactory(val context: Context) { DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS, descriptor, outerClass.defaultType - ) + ).apply { + parent = innerClass + } } fun getLoweredEnum(enumClass: IrClass): LoweredEnum { @@ -109,25 +111,8 @@ internal class SpecialDeclarationsFactory(val context: Context) { } } - private fun assignOrdinalsToEnumEntries(classDescriptor: ClassDescriptor): Map { - val enumEntryOrdinals = mutableMapOf() - classDescriptor.enumEntries.forEachIndexed { index, entry -> - enumEntryOrdinals[entry] = index - } - return enumEntryOrdinals - } - - fun getEnumEntryOrdinal(entryDescriptor: ClassDescriptor): Int { - val enumClassDescriptor = entryDescriptor.containingDeclaration as ClassDescriptor - // If enum came from another module then we need to get serialized ordinal number. - // We serialize ordinal because current serialization cannot preserve enum entry order. - if (enumClassDescriptor is DeserializedClassDescriptor) { - return enumClassDescriptor.classProto.enumEntryList - .first { entryDescriptor.name == enumClassDescriptor.c.nameResolver.getName(it.name) } - .getExtension(KonanProtoBuf.enumEntryOrdinal) - } - return ordinals.getOrPut(enumClassDescriptor) { assignOrdinalsToEnumEntries(enumClassDescriptor) }[entryDescriptor]!! - } + fun getEnumEntryOrdinal(enumEntry: IrEnumEntry) = + enumEntry.parentAsClass.declarations.filterIsInstance().indexOf(enumEntry) fun getBridge(overriddenFunction: OverriddenFunctionInfo): IrSimpleFunction { val irFunction = overriddenFunction.function @@ -295,6 +280,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { return true } + lateinit var irModules: Map + // TODO: make lateinit? var irModule: IrModuleFragment? = null set(module) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 69b93b83669..de3bf88da5f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.konan.properties.loadProperties import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.KonanAbiVersion import org.jetbrains.kotlin.konan.KonanVersion +import org.jetbrains.kotlin.konan.library.resolver.TopologicalLibraryOrder import org.jetbrains.kotlin.konan.library.toUnresolvedLibraries import org.jetbrains.kotlin.konan.parseKonanVersion @@ -105,7 +106,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List { if (moduleDescriptor == null) error("purgeUnneeded() only works correctly after resolve is over, and we have successfully marked package files as needed or not needed.") - return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList() + return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder) } internal val defaultNativeLibraries: List = mutableListOf().apply { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt index 28cc507e0b2..03345c64cc6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt @@ -190,7 +190,7 @@ internal val innerClassPhase = makeKonanFileLoweringPhase( ::InnerClassLowering, name = "InnerClasses", description = "Inner classes lowering", - prerequisite = setOf(defaultParameterExtentPhase, genSyntheticFieldsPhase ) + prerequisite = setOf(defaultParameterExtentPhase) ) internal val forLoopsPhase = makeKonanFileLoweringPhase( diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt index ac134587ed4..8c7de54b14c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt @@ -5,5 +5,7 @@ import org.jetbrains.kotlin.name.FqName object RuntimeNames { val symbolName = FqName("kotlin.native.SymbolName") val exportForCppRuntime = FqName("kotlin.native.internal.ExportForCppRuntime") + val exportForCompilerAnnotation = FqName("kotlin.native.internal.ExportForCompiler") + val exportTypeInfoAnnotation = FqName("kotlin.native.internal.ExportTypeInfo") val cCall = FqName("kotlinx.cinterop.internal.CCall") } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 9cdde6f52d9..9304542b723 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -12,6 +12,7 @@ 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.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.konan.target.CompilerOutputKind @@ -65,22 +66,39 @@ internal val psiToIrPhase = konanUnitPhase( forwardDeclarationsModuleDescriptor ) - val irModules = moduleDescriptor.allDependencyModules.map { - val library = it.konanLibrary - if (library == null) { - return@map null + val modules = mutableMapOf() + + var dependenciesCount = 0 + while (true) { + // context.config.librariesWithDependencies could change at each iteration. + val dependencies = moduleDescriptor.allDependencyModules.filter { + config.librariesWithDependencies(moduleDescriptor).contains(it.konanLibrary) } - library.irHeader?.let { header -> deserializer.deserializeIrModule(it, header) } - }.filterNotNull() + for (dependency in dependencies) { + val konanLibrary = dependency.konanLibrary!! + if (modules.containsKey(konanLibrary.libraryName)) continue + konanLibrary.irHeader?.let { header -> + val deserializationStrategy = when { + config.produce.isNativeBinary -> DeserializationStrategy.EXPLICITLY_EXPORTED + else -> DeserializationStrategy.ONLY_REFERENCED + } + modules[konanLibrary.libraryName] = deserializer.deserializeIrModuleHeader(dependency, header, deserializationStrategy) + } + } + if (dependencies.size == dependenciesCount) break + dependenciesCount = dependencies.size + } + val symbols = KonanSymbols(this, generatorContext.symbolTable, generatorContext.symbolTable.lazyWrapper) val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles(), deserializer) - irModules.forEach { + modules.values.forEach { it.patchDeclarationParents() } irModule = module + irModules = modules ir.symbols = symbols // validateIrModule(this, module) @@ -102,12 +120,6 @@ internal val irGeneratorPluginsPhase = konanUnitPhase( 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. @@ -128,15 +140,13 @@ internal val patchDeclarationParents0Phase = konanUnitPhase( internal val serializerPhase = konanUnitPhase( op = { val declarationTable = DeclarationTable(irModule!!.irBuiltins, DescriptorTable()) - val serializedIr = IrModuleSerializer( - this, declarationTable, bodiesOnlyForInlines = config.isInteropStubs).serializedIrModule(irModule!!) + val serializedIr = IrModuleSerializer(this, declarationTable).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) + description = "Serialize descriptor tree and inline IR bodies" ) internal val setUpLinkStagePhase = konanUnitPhase( @@ -165,13 +175,108 @@ internal val linkPhase = namedUnitPhase( linkerPhase ) +internal val allLoweringsPhase = 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 +// validateIrModulePhase // Temporarily disabled until moving to new IR finished. +) + +internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper( + name = "LowerLibIR", + description = "Lower library's IR", + prerequisite = emptySet(), + dumperVerifier = EmptyDumperVerifier(), + lower = object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, irModule: IrModuleFragment): IrModuleFragment { + + val files = mutableListOf() + files += irModule.files + irModule.files.clear() + + // TODO: KonanLibraryResolver.TopologicalLibraryOrder actually returns libraries in the reverse topological order. + context.librariesWithDependencies + .reversed() + .forEach { + val libModule = context.irModules[it.libraryName] + ?: return@forEach + + irModule.files += libModule.files + allLoweringsPhase.invoke(phaseConfig, phaserState, context, irModule) + + irModule.files.clear() + } + + // Save all files for codegen in reverse topological order. + // This guarantees that libraries initializers are emitted in correct order. + context.librariesWithDependencies + .forEach { + val libModule = context.irModules[it.libraryName] + ?: return@forEach + irModule.files += libModule.files + } + irModule.files += files + + return irModule + } + + }) + +internal val bitcodePhase = namedIrModulePhase( + name = "Bitcode", + description = "LLVM Bitcode generation", + lower = contextLLVMSetupPhase then + RTTIPhase then + generateDebugInfoHeaderPhase then + deserializeDFGPhase then + devirtualizationPhase then + escapeAnalysisPhase then + codegenPhase then + finalizeDebugInfoPhase then + cStubsPhase +) + 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 @@ -179,67 +284,16 @@ internal val toplevelPhase = namedUnitPhase( name = "Backend", description = "All backend", lower = takeFromContext { 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 + allLoweringsPhase then // Lower current module first. + dependenciesLowerPhase then // Then lower all libraries in topological order. + // With that we guarantee that inline functions are unlowered while being inlined. + moduleIndexForCodegenPhase then + buildDFGPhase then + serializeDFGPhase then + bitcodePhase then + produceOutputPhase then verifyBitcodePhase then - printBitcodePhase - then + printBitcodePhase then unitSink() ) then linkPhase @@ -256,6 +310,8 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) { // Don't serialize anything to a final executable. switch(serializerPhase, config.produce == CompilerOutputKind.LIBRARY) + switch(dependenciesLowerPhase, config.produce != CompilerOutputKind.LIBRARY) + switch(bitcodePhase, config.produce != CompilerOutputKind.LIBRARY) switch(linkPhase, config.produce.isNativeBinary) switch(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) != TestRunnerKind.NONE) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 63ab5191381..c5e194dab51 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt index 4132650a2f1..18702abb419 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt @@ -7,25 +7,22 @@ package org.jetbrains.kotlin.backend.konan.irasdescriptors import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull -import org.jetbrains.kotlin.backend.konan.descriptors.konanBackingField import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl -import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.isMarkedNullable import org.jetbrains.kotlin.ir.util.explicitParameters -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.ir.util.isFunction import org.jetbrains.kotlin.ir.util.isSuspendFunction +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor val IrConstructor.constructedClass get() = this.parent as IrClass @@ -95,23 +92,7 @@ fun IrClass.getSuperInterfaces() = this.superClasses.map { it.owner }.filter { i val IrProperty.konanBackingField: IrField? get() { assert(this.isReal) - this.backingField?.let { return it } - - (this.descriptor as? DeserializedPropertyDescriptor)?.konanBackingField?.let { backingFieldDescriptor -> - val result = IrFieldImpl( - this.startOffset, - this.endOffset, - IrDeclarationOrigin.PROPERTY_BACKING_FIELD, - backingFieldDescriptor, - this.getter!!.returnType - ).also { - it.parent = this.parent - } - this.backingField = result - return result - } - - return null + return this.backingField } val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt index 435dfad5dc5..39e3fd781a6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt @@ -121,14 +121,14 @@ internal fun buildLibrary( target: KonanTarget, output: String, moduleName: String, - llvmModule: LLVMModuleRef, + llvmModule: LLVMModuleRef?, nopack: Boolean, manifestProperties: Properties?, dataFlowGraph: ByteArray?): KonanLibraryWriter { val library = LibraryWriterImpl(File(output), moduleName, versions, target, nopack) - library.addKotlinBitcode(llvmModule) + llvmModule?.let { library.addKotlinBitcode(it) } library.addLinkData(linkData) natives.forEach { library.addNativeBitcode(it) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 5bd59008962..f6fadd21873 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -107,7 +107,7 @@ private val cnameAnnotation = FqName("kotlin.native.CName") private val exportForCppRuntimeAnnotation = RuntimeNames.exportForCppRuntime -private val exportForCompilerAnnotation = FqName("kotlin.native.internal.ExportForCompiler") +private val exportForCompilerAnnotation = RuntimeNames.exportForCompilerAnnotation private val publishedApiAnnotation = FqName("kotlin.PublishedApi") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt index c41e99d932c..0977c2628e6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt @@ -151,9 +151,9 @@ internal val cStubsPhase = makeKonanModuleOpPhase( op = { context, _ -> produceCStubs(context) } ) -internal val bitcodeLinkerPhase = makeKonanModuleOpPhase( - name = "BitcodeLinker", - description = "Bitcode linking", +internal val produceOutputPhase = makeKonanModuleOpPhase( + name = "ProduceOutput", + description = "Produce output", op = { context, _ -> produceOutput(context) } ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index edfe669fe56..b32c9f474ec 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -142,12 +142,7 @@ internal interface ContextUtils : RuntimeAware { get() = context.llvm.staticData fun isExternal(declaration: IrDeclaration): Boolean { - val pkg = declaration.findPackage() - return when (pkg) { - is IrFile -> pkg.packageFragmentDescriptor.containingDeclaration != context.moduleDescriptor - is IrExternalPackageFragment -> true - else -> error(pkg) - } + return false } /** @@ -367,19 +362,6 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { .getFullList(TopologicalLibraryOrder) } - val librariesForLibraryManifest: List - get() { - // Note: library manifest should contain the list of all user libraries and frontend-used default libraries. - // However this would result into linking too many default libraries into the application which uses current - // library. This problem should probably be fixed by adding different kind of dependencies to library - // manifest. - // Currently the problem is workarounded like this: - return this.librariesToLink - // This list contains all user libraries and the default libraries required for link (not frontend). - // That's why the workaround doesn't work only in very special cases, e.g. when `-nodefaultlibs` is enabled - // when compiling the application, while the library API uses types from default libs. - } - val staticData = StaticData(context) private val target = context.config.target diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt index 3a76ad37dd3..ad6b087ee15 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt @@ -40,10 +40,9 @@ internal fun findMainEntryPoint(context: Context): FunctionDescriptor? { candidates.singleOrNull { it.hasSingleArrayOfStringParameter } ?: candidates.singleOrNull { it.hasNoParameters } ?: context.reportCompilationError("Could not find '$entryName' in '$packageName' package.") - - if (main.isSuspend) { + + if (main.isSuspend) context.reportCompilationError("Entry point can not be a suspend function.") - } return main } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index a45dcfef116..b2ea95a8467 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -58,6 +58,7 @@ internal enum class IntrinsicType { IDENTITY, IMMUTABLE_BLOB, INIT_INSTANCE, + SELECT_ENTRY_POINT, // Coroutines GET_CONTINUATION, RETURN_IF_SUSPEND, @@ -218,6 +219,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv IntrinsicType.IDENTITY -> emitIdentity(args) IntrinsicType.GET_CONTINUATION -> emitGetContinuation() IntrinsicType.INTEROP_MEMORY_COPY -> emitMemoryCopy(callSite, args) + IntrinsicType.SELECT_ENTRY_POINT -> emitEntryPointSelection(args) IntrinsicType.RETURN_IF_SUSPEND, IntrinsicType.INTEROP_BITS_TO_FLOAT, IntrinsicType.INTEROP_BITS_TO_DOUBLE, @@ -246,6 +248,12 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv private fun FunctionGenerationContext.emitIdentity(args: List): LLVMValueRef = args.single() + private fun FunctionGenerationContext.emitEntryPointSelection(args: List): LLVMValueRef { + val entryPoint = context.ir.symbols.entryPoint?.owner ?: return unreachable()!! // TODO: Don't put start.kt in source set unless produce=PROGRAM. + return call(codegen.llvmFunction(entryPoint), args.take(entryPoint.valueParameters.size), + Lifetime.IRRELEVANT, environment.exceptionHandler) + } + private fun FunctionGenerationContext.emitListOfInternal(callSite: IrCall, args: List): LLVMValueRef { val varargExpression = callSite.getValueArgument(0) as IrVararg val vararg = args.single() 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 acfb13cbcad..8efecf6684b 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 @@ -324,7 +324,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map` with given values of fields. * diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt index 3794aa2473a..2a1f33a6291 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt @@ -59,7 +59,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context, override fun visitField(declaration: IrField) { // TODO: inlining a function returning an object - // we get PropertyDescriptors from whithin that object here. + // we get PropertyDescriptors from within that object here. // That is a bug, most probably. // We workaround the issue with question marks here. (declaration.descriptor as? WrappedFieldDescriptor)?.bind(declaration) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index db074a6edca..2e1298c728a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -136,10 +136,10 @@ internal class EnumUsageLowering(val context: Context) internal class EnumClassLowering(val context: Context) : ClassLoweringPass { fun run(irFile: IrFile) { - runOnFilePostfix(irFile) // EnumWhenLowering should be performed before EnumUsageLowering because // the latter performs lowering of IrGetEnumValue EnumWhenLowering(context).lower(irFile) + runOnFilePostfix(irFile) EnumUsageLowering(context).lower(irFile) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt index e81ddeac9f7..da585ceb317 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt @@ -238,7 +238,7 @@ internal class EnumConstructorsLowering(val context: Context) : ClassLoweringPas override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { val name = enumEntry.name.asString() - val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry.descriptor) + val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry) val startOffset = enumConstructorCall.startOffset val endOffset = enumConstructorCall.endOffset diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt index 0ab73435f7b..efb29443529 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt @@ -143,7 +143,7 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo if (lhs is IrValueAccessExpression && lhs.symbol.owner == topmostSubject && rhs is IrGetEnumValue && // Both entries should belong to the same class: topmostSubject.type.classifierOrNull?.owner == rhs.symbol.owner.parent) { - val entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.descriptor) + val entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.symbol.owner) val subjectOrdinal = topmostOrdinalProvider.value return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue.owner.returnType, areEqualByValue).apply { putValueArgument(0, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt index de8cad8f7cc..6fb822f7375 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -12,6 +12,10 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl import org.jetbrains.kotlin.backend.konan.irasdescriptors.file +import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* @@ -24,6 +28,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.util.defaultType @@ -169,6 +175,24 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir else -> error("Unknown ReturnTarget: $this") } + private fun createSyntheticFunctionDescriptor(name: String): SimpleFunctionDescriptor { + val descriptor = WrappedSimpleFunctionDescriptor() + descriptor.bind(IrFunctionImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(descriptor), + Name.identifier(name), + Visibilities.PUBLIC, + Modality.FINAL, + context.irBuiltIns.unitType, + false, + false, + false, + false) + ) + return descriptor + } + private fun performHighLevelJump(tryScopes: List, index: Int, jump: HighLevelJump, @@ -181,7 +205,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir val currentTryScope = tryScopes[index] currentTryScope.jumps.getOrPut(jump) { val type = (jump as? Return)?.target?.owner?.returnType ?: value.type - val symbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor()) + val symbol = IrReturnableBlockSymbolImpl(createSyntheticFunctionDescriptor("\$Finally$index")) with(currentTryScope) { irBuilder.run { val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression) @@ -252,7 +276,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir ) using(TryScope(syntheticTry, transformedFinallyExpression, this)) { val fallThroughType = aTry.type - val fallThroughSymbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor()) + val fallThroughSymbol = IrReturnableBlockSymbolImpl(createSyntheticFunctionDescriptor("\$Fallthrough")) val transformedResult = aTry.tryResult.transform(transformer, null) transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult) for (aCatch in aTry.catches) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index 7f328cde35b..65ab8ee8622 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -131,6 +131,9 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset) if (descriptor.isInlineConstructor) { + // Copier sets parent to be the current function but + // constructor's parent cannot be a function. + copiedCallee.parent = callee.parent val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall irBuilder.run { val constructorDescriptor = delegatingConstructorCall.descriptor.original 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 e4e92f69875..b5f261ae6f6 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 @@ -44,6 +44,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { } private fun createOuterThisField() { + irClass.declarations += context.specialDeclarationsFactory.getOuterThisField(irClass) outerThisFieldSymbol = context.specialDeclarationsFactory.getOuterThisField(irClass).symbol } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt index 9011af3ffb9..4b795202115 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -628,7 +628,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme descriptor.getExternalObjCMethodInfo()?.let { methodInfo -> val isInteropStubsFile = - currentFile.fileAnnotations.any { it.fqName == FqName("kotlinx.cinterop.InteropStubs") } + currentFile.annotations.hasAnnotation(FqName("kotlinx.cinterop.InteropStubs")) // Special case: bridge from Objective-C method implementation template to Kotlin method; // handled in CodeGeneratorVisitor.callVirtual. 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 deleted file mode 100644 index 9992cc011df..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt +++ /dev/null @@ -1,54 +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.serialization - -import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.util.addChild -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid - -internal class BackingFieldVisitor(val context: Context) : IrElementVisitorVoid { - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - 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() } } - list?.add(declaration.backingField!!.descriptor) - } - if (declaration.backingField == null || declaration.isDelegated) return - assert(declaration.backingField!!.descriptor == declaration.descriptor) { - "backing field descriptor mismatch: ${declaration.backingField!!.descriptor} != ${declaration.descriptor}" - } - - context.ir.propertiesWithBackingFields.add(declaration.descriptor) - } - - override fun visitClass(declaration: IrClass) { - if (declaration.isInner) - declaration.declarations += 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) - } -} - -internal fun markBackingFields(context: Context) { - context.irModule!!.accept(BackingFieldVisitor(context), null) -} - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt index 193cbdc3cae..780f92a498d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrModuleSerializer.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.descriptors.findTopLevelDeclaration import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass @@ -39,6 +40,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrUnaryPrimitiveImpl import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl +import org.jetbrains.kotlin.ir.util.dump +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.konan.library.impl.CombinedIrFileWriter import org.jetbrains.kotlin.konan.library.impl.DeclarationId import org.jetbrains.kotlin.metadata.KonanIr @@ -1058,6 +1063,7 @@ internal class IrModuleSerializer( val proto = KonanIr.IrFile.newBuilder() .setFileEntry(serializeFileEntry(file.fileEntry)) .setFqName(serializeString(file.fqName.toString())) + .setAnnotations(serializeAnnotations(file.annotations)) file.declarations.forEach { if (it is IrTypeAlias || (it.descriptor.isExpectMember && !it.descriptor.isSerializableExpectClass)) { @@ -1070,6 +1076,26 @@ internal class IrModuleSerializer( writer.addDeclaration(DeclarationId(uniqId.index, uniqId.isLocal), byteArray) proto.addDeclarationId(protoUniqId(uniqId)) } + + file.acceptVoid(object: IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + if (declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCppRuntime) + || declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) + proto.addExplicitlyExportedToCompiler(serializeIrSymbol(declaration.symbol)) + super.visitDeclaration(declaration) + } + + override fun visitClass(declaration: IrClass) { + if (declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportTypeInfoAnnotation)) + proto.addExplicitlyExportedToCompiler(serializeIrSymbol(declaration.symbol)) + super.visitDeclaration(declaration) + } + }) + return proto.build() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto index dfd2cea0bfa..ccdda541e40 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto @@ -89,6 +89,8 @@ message IrFile { repeated UniqId declaration_id = 1; required FileEntry file_entry = 2; required String fq_name = 3; + required Annotations annotations = 4; + repeated IrSymbol explicitly_exported_to_compiler = 5; // Symbols referenced by C runtime. TODO: Make an extension? } message IrModule { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt index b1169096e5d..3358550b714 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleDeserializer.kt @@ -309,7 +309,7 @@ class KonanIrModuleDeserializer( } } - fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrFile { + fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deseralizationStrategy: DeserializationStrategy): IrFile { val fileEntry = NaiveSourceBasedFileEntryImpl( deserializeString(fileProto.fileEntry.name), fileProto.fileEntry.lineStartOffsetsList.toIntArray() @@ -327,15 +327,22 @@ class KonanIrModuleDeserializer( val uniqIdKey = it.uniqIdKey(moduleDescriptor) reversedFileIndex.put(uniqIdKey, file) - if (deserializeAllDeclarations) { + if (deseralizationStrategy == DeserializationStrategy.ALL) { file.declarations.add(deserializeTopLevelDeclaration(uniqIdKey)) } } + val annotations = deserializeAnnotations(fileProto.annotations) + file.annotations.addAll(annotations) + + + if (deseralizationStrategy == DeserializationStrategy.EXPLICITLY_EXPORTED) + fileProto.explicitlyExportedToCompilerList.forEach { deserializeIrSymbol(it) } + return file } - fun deserializeIrModule(proto: KonanIr.IrModule, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrModuleFragment { + fun deserializeIrModuleHeader(proto: KonanIr.IrModule, moduleDescriptor: ModuleDescriptor, deserializationStrategy: DeserializationStrategy): IrModuleFragment { deserializedModuleDescriptor = moduleDescriptor deserializedModuleProtoSymbolTables.put(moduleDescriptor, proto.symbolTable) @@ -343,7 +350,7 @@ class KonanIrModuleDeserializer( deserializedModuleProtoTypeTables.put(moduleDescriptor, proto.typeTable) val files = proto.fileList.map { - deserializeIrFile(it, moduleDescriptor, deserializeAllDeclarations) + deserializeIrFile(it, moduleDescriptor, deserializationStrategy) } val module = IrModuleFragmentImpl(moduleDescriptor, builtIns, files) @@ -351,8 +358,14 @@ class KonanIrModuleDeserializer( return module } - fun deserializeIrModule(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializeAllDeclarations: Boolean = false): IrModuleFragment { + fun deserializeIrModuleHeader(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializationStrategy: DeserializationStrategy = DeserializationStrategy.ONLY_REFERENCED): IrModuleFragment { val proto = KonanIr.IrModule.parseFrom(byteArray.codedInputStream, KonanSerializerProtocol.extensionRegistry) - return deserializeIrModule(proto, moduleDescriptor, deserializeAllDeclarations) + return deserializeIrModuleHeader(proto, moduleDescriptor, deserializationStrategy) } } + +enum class DeserializationStrategy { + ONLY_REFERENCED, + ALL, + EXPLICITLY_EXPORTED +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt index 54f8c85fc51..34ec0cb4491 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt @@ -53,8 +53,6 @@ internal class KonanSerializerExtension(val context: Context, override val metad override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) { uniqId(descriptor) ?.let { proto.setExtension(KonanProtoBuf.enumEntryUniqId, it) } // Serialization doesn't preserve enum entry order, so we need to serialize ordinal. - val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(descriptor) - proto.setExtension(KonanProtoBuf.enumEntryOrdinal, ordinal) super.serializeEnumEntry(descriptor, proto) } diff --git a/build.gradle b/build.gradle index e84122915e1..854c1221ad6 100644 --- a/build.gradle +++ b/build.gradle @@ -340,7 +340,6 @@ targetList.each { target -> task("${target}CrossDistRuntime", type: Copy) { dependsOn ":runtime:${target}Runtime" dependsOn ":backend.native:${target}Stdlib" - dependsOn ":backend.native:${target}Start" destinationDir distDir @@ -357,10 +356,6 @@ targetList.each { target -> include('**') into(stdlib) } - from(project(':runtime').file("build/${target}Start.bc")) { - rename("${target}Start.bc", 'start.bc') - into("konan/targets/$target/native") - } if (target == 'wasm32') { into("$stdlib/targets/wasm32/included") { from(project(':runtime').file('src/main/js')) diff --git a/runtime/src/launcher/kotlin/konan/start.kt b/runtime/src/launcher/kotlin/konan/start.kt index e7dc25f19c8..39eccfe1e04 100644 --- a/runtime/src/launcher/kotlin/konan/start.kt +++ b/runtime/src/launcher/kotlin/konan/start.kt @@ -4,16 +4,18 @@ */ import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType // This function is produced by the code generator given // the '-entry foo.bar.main' flag. // It calls the requested entry point. // The default is main(Array):Unit in the root package. -@SymbolName("EntryPointSelector") -external fun EntryPointSelector(args: Array) +@TypedIntrinsic(IntrinsicType.SELECT_ENTRY_POINT) +private external fun EntryPointSelector(args: Array) @SymbolName("OnUnhandledException") -external private fun OnUnhandledException(throwable: Throwable) +private external fun OnUnhandledException(throwable: Throwable) @ExportForCppRuntime private fun Konan_start(args: Array): Int { diff --git a/runtime/src/main/cpp/Exceptions.cpp b/runtime/src/main/cpp/Exceptions.cpp index 1b852218eb1..6b51173ac1a 100644 --- a/runtime/src/main/cpp/Exceptions.cpp +++ b/runtime/src/main/cpp/Exceptions.cpp @@ -59,7 +59,7 @@ class AutoFree { } }; -// RuntimeUtiks.kt +// RuntimeUtils.kt extern "C" void ReportUnhandledException(KRef throwable); extern "C" void ExceptionReporterLaunchpad(KRef reporter, KRef throwable); diff --git a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt index 95cf76be237..5f20cd23b95 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt @@ -52,6 +52,7 @@ class IntrinsicType { const val IDENTITY = "IDENTITY" const val IMMUTABLE_BLOB = "IMMUTABLE_BLOB" const val INIT_INSTANCE = "INIT_INSTANCE" + const val SELECT_ENTRY_POINT = "SELECT_ENTRY_POINT" const val GET_CONTINUATION = "GET_CONTINUATION" const val RETURN_IF_SUSPEND = "RETURN_IF_SUSPEND" diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt index 8e1653bb7c2..71c852543d0 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt @@ -81,7 +81,7 @@ class Distribution( fun runtime(target: KonanTarget) = runtimeFileOverride ?: "$stdlib/targets/${target.visibleName}/native/runtime.bc" - val launcherFiles = listOf("start.bc", "launcher.bc") + val launcherFiles = listOf("launcher.bc") val dependenciesDir = DependencyProcessor.defaultDependenciesRoot.absolutePath