From 7567c96bc95e7e59043f755de0ba95fa997bae29 Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Thu, 25 Jan 2018 12:55:06 +0300 Subject: [PATCH] Add basic support for multi-platform projects to the compiler (#1254) Add compiler pass removing `expect` declarations Thus support multi-platform projects in the compiler. Also * Add some trivial checks to ensure that `expect` declarations are not generated to bitcode. * Add minor improvement to exported symbol name clash detection. * Don't create LLVM declarations for Obj-C-interop fake functions. --- .../kotlin/backend/konan/KonanLower.kt | 4 +++ .../kotlin/backend/konan/KonanPhases.kt | 1 + .../konan/descriptors/DescriptorUtils.kt | 3 ++ .../backend/konan/llvm/BinaryInterface.kt | 3 ++ .../kotlin/backend/konan/llvm/Imports.kt | 7 ++--- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 5 +++ .../backend/konan/llvm/LlvmDeclarations.kt | 20 +++++++++--- .../konan/lower/ExpectDeclarationsRemoving.kt | 17 ++++++++++ backend.native/tests/build.gradle | 5 +++ backend.native/tests/codegen/mpp/mpp1.kt | 31 +++++++++++++++++++ 10 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt create mode 100644 backend.native/tests/codegen/mpp/mpp1.kt 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 77b5acffdd9..83f17114771 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 @@ -41,6 +41,10 @@ internal class KonanLower(val context: Context) { fun lowerModule(irModule: IrModuleFragment) { val phaser = PhaseManager(context) + phaser.phase(KonanPhase.REMOVE_EXPECT_DECLARATIONS) { + irModule.files.forEach(ExpectDeclarationsRemoving(context)::lower) + } + phaser.phase(KonanPhase.TEST_PROCESSOR) { TestProcessor(context).process(irModule) } 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 d61475c65b1..a604f9e47af 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 @@ -29,6 +29,7 @@ enum class KonanPhase(val description: String, /* */ SERIALIZER("Serialize descriptor tree and inline IR bodies"), /* */ 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_CONSTRUCTORS("Inline constructors transformation", LOWER_BEFORE_INLINE), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 5a46d6ba4cc..ea04460c123 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -344,3 +344,6 @@ val ClassDescriptor.enumEntries: List .filterIsInstance() .filter { it.kind == ClassKind.ENUM_ENTRY } } + +internal val DeclarationDescriptor.isExpectMember: Boolean + get() = this is MemberDescriptor && this.isExpect 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 e4e5a5867b8..7f53f40357c 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 @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef import org.jetbrains.kotlin.backend.common.descriptors.allParameters import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract +import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember import org.jetbrains.kotlin.backend.konan.descriptors.isUnit import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo import org.jetbrains.kotlin.backend.konan.isExternalObjCClass @@ -47,6 +48,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty * and so should be computable from the descriptor itself without checking a backend state. */ internal tailrec fun DeclarationDescriptor.isExported(): Boolean { + assert(!this.isExpectMember) { this } + if (this.annotations.findAnnotation(symbolNameAnnotation) != null) { // Treat any `@SymbolName` declaration as exported. return true diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt index 0a7a77ebb4c..564e3f431ac 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt @@ -17,10 +17,7 @@ package org.jetbrains.kotlin.backend.konan.llvm import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin -import org.jetbrains.kotlin.backend.konan.descriptors.SyntheticModules -import org.jetbrains.kotlin.backend.konan.descriptors.origin -import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule +import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -30,6 +27,8 @@ internal interface LlvmImports { internal val DeclarationDescriptor.llvmSymbolOrigin: LlvmSymbolOrigin get() { + assert(!this.isExpectMember) { this } + val module = this.module val moduleOrigin = module.origin when (moduleOrigin) { 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 61c85439f54..9871980b061 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 @@ -444,6 +444,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map