diff --git a/core/compiler.common.native/src/org/jetbrains/kotlin/name/NativeRuntimeNames.kt b/core/compiler.common.native/src/org/jetbrains/kotlin/name/NativeRuntimeNames.kt index 18b9c24eafd..dd9e0e6e7ac 100644 --- a/core/compiler.common.native/src/org/jetbrains/kotlin/name/NativeRuntimeNames.kt +++ b/core/compiler.common.native/src/org/jetbrains/kotlin/name/NativeRuntimeNames.kt @@ -11,6 +11,7 @@ object NativeRuntimeNames { object Annotations { val symbolNameClassId = ClassId(kotlinNativePackage, Name.identifier("SymbolName")) val cNameClassId = ClassId(kotlinNativePackage, Name.identifier("CName")) + val exportedBridgeClassId = ClassId(kotlinNativeInternalPackage, Name.identifier("ExportedBridge")) val exportForCppRuntimeClassId = ClassId(kotlinNativeInternalPackage, Name.identifier("ExportForCppRuntime")) val exportForCompilerClassId = ClassId(kotlinNativeInternalPackage, Name.identifier("ExportForCompiler")) val gcUnsafeCallClassId = ClassId(kotlinNativeInternalPackage, Name.identifier("GCUnsafeCall")) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt index 4f1906f146a..5dccc484449 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt @@ -8,6 +8,7 @@ object RuntimeNames { val cnameAnnotation = NativeRuntimeNames.Annotations.cNameClassId.asSingleFqName() val frozenAnnotation = FqName("kotlin.native.internal.Frozen") val exportForCppRuntime = NativeRuntimeNames.Annotations.exportForCppRuntimeClassId.asSingleFqName() + val exportedBridge = NativeRuntimeNames.Annotations.exportedBridgeClassId.asSingleFqName() val exportForCompilerAnnotation = NativeRuntimeNames.Annotations.exportForCompilerClassId.asSingleFqName() val exportTypeInfoAnnotation = FqName("kotlin.native.internal.ExportTypeInfo") val cCall = FqName("kotlinx.cinterop.internal.CCall") diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 95ec5ff4c9b..37c790824ad 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -6,19 +6,21 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef -import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow -import org.jetbrains.kotlin.ir.util.getAnnotationStringValue import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.ir.isUnit +import org.jetbrains.kotlin.backend.konan.serialization.AbstractKonanIrMangler +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.objcinterop.isExternalObjCClass import org.jetbrains.kotlin.ir.objcinterop.isKotlinObjCClass -import org.jetbrains.kotlin.backend.konan.serialization.AbstractKonanIrMangler -import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.util.findAnnotation import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.util.getAnnotationStringValue import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.library.uniqueName @@ -62,6 +64,10 @@ object KonanBinaryInterface { private fun withPrefix(prefix: String, mangle: String) = "$prefix:$mangle" + private fun IrFunction.findManglingAnnotation() = + this.annotations.findAnnotation(RuntimeNames.exportForCppRuntime) + ?: this.annotations.findAnnotation(RuntimeNames.exportedBridge) + private fun IrFunction.funSymbolNameImpl(containerName: String?): String { if (isExternal) { this.externalSymbolOrThrow()?.let { @@ -69,7 +75,7 @@ object KonanBinaryInterface { } } - this.annotations.findAnnotation(RuntimeNames.exportForCppRuntime)?.let { + this.findManglingAnnotation()?.let { val name = it.getAnnotationStringValue() ?: this.name.asString() return name // no wrapping currently required } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index acf0b4abc18..5a18cde2dec 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -114,6 +114,8 @@ internal inline fun generateFunction( val llvmFunction = codegen.llvmFunction(function) val isCToKotlinBridge = function.origin == CBridgeOrigin.C_TO_KOTLIN_BRIDGE + // TODO: Alternative approach: lowering that changes origin of such functions to C_TO_KOTLIN_BRIDGE? + || function.hasAnnotation(RuntimeNames.exportedBridge) val functionGenerationContext = DefaultFunctionGenerationContext( llvmFunction, diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt index 8b1c45b96fa..0547d6778d3 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.backend.konan.llvm +import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.ir.util.getAnnotationStringValue import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.util.findAnnotation @@ -18,5 +19,6 @@ internal fun IrFunction.retainAnnotation(target: KonanTarget): Boolean { if (this.annotations.findAnnotation(retainAnnotationName) != null) return true val forTarget = this.annotations.findAnnotation(retainForTargetAnnotationName) if (forTarget != null && forTarget.getAnnotationStringValue() == target.name) return true + if (this.annotations.findAnnotation(RuntimeNames.exportedBridge) != null) return true return false } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index ae15c1496bd..4b183dbbee8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -603,6 +603,7 @@ internal object DataFlowIR { if (returnsNothing) attributes = attributes or FunctionAttributes.RETURNS_NOTHING if (it.hasAnnotation(RuntimeNames.exportForCppRuntime) + || it.hasAnnotation(RuntimeNames.exportedBridge) || it.getExternalObjCMethodInfo() != null // TODO-DCE-OBJC-INIT || it.hasAnnotation(RuntimeNames.objCMethodImp)) { attributes = attributes or FunctionAttributes.EXPLICITLY_EXPORTED diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt index 3d2c0be0a30..fe28f2404c5 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt @@ -5,6 +5,8 @@ package kotlin.native.internal +import kotlin.experimental.ExperimentalNativeApi + /** * Makes this function to be possible to call by given name from C++ part of runtime using C ABI. * The parameters are mapped in an implementation-dependent manner. @@ -180,3 +182,13 @@ internal annotation class InternalForKotlinNativeTests @InternalForKotlinNativeTests @Target(AnnotationTarget.FILE) public annotation class ReflectionPackageName(val name: String) + +/** + * Indicates that the marked function is an exported bridge between Kotlin and the platform. + * This annotation prevents the function from being removed by DCE + * and specifies a stable [bridgeName] for the function symbol. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(value = AnnotationRetention.BINARY) +@ExperimentalNativeApi +public annotation class ExportedBridge(val bridgeName: String) \ No newline at end of file