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 171f7f22528..5b830e13712 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 @@ -17,11 +17,7 @@ import org.jetbrains.kotlin.backend.konan.isInlined import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.types.isUnit -import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor -import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment import org.jetbrains.kotlin.types.SimpleType /** @@ -81,17 +77,9 @@ internal fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction { return realSupers.first { it.modality != Modality.ABSTRACT } } -private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic") -private val frozenAnnotation = FqName("kotlin.native.internal.Frozen") - // TODO: don't forget to remove descriptor access here. internal val FunctionDescriptor.isIntrinsic: Boolean - get() = this.descriptor.annotations.hasAnnotation(intrinsicAnnotation) - -internal val org.jetbrains.kotlin.descriptors.DeclarationDescriptor.isFrozen: Boolean - get() = this.annotations.hasAnnotation(frozenAnnotation) || - // RTTI is used for non-reference type box: - this is org.jetbrains.kotlin.descriptors.ClassDescriptor && !this.defaultType.binaryTypeIsReference() + get() = this.descriptor.isIntrinsic internal val DeclarationDescriptor.isFrozen: Boolean get() = this.descriptor.isFrozen @@ -239,23 +227,4 @@ tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescrip } fun FunctionDescriptor.isComparisonDescriptor(map: Map): Boolean = - this in map.values - -private fun sourceByIndex(descriptor: CallableMemberDescriptor, index: Int): SourceFile { - val fragment = descriptor.findPackage() as KonanPackageFragment - return fragment.sourceFileMap.sourceFile(index) -} - -fun CallableMemberDescriptor.findSourceFile(): SourceFile { - val source = this.source.containingFile - if (source != SourceFile.NO_SOURCE_FILE) - return source - return when { - this is DeserializedSimpleFunctionDescriptor && proto.hasExtension(KonanProtoBuf.functionFile) -> sourceByIndex( - this, proto.getExtension(KonanProtoBuf.functionFile)) - this is DeserializedPropertyDescriptor && proto.hasExtension(KonanProtoBuf.propertyFile) -> - sourceByIndex( - this, proto.getExtension(KonanProtoBuf.propertyFile)) - else -> TODO() - } -} + this in map.values \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt index 5e1dda024c4..af9ba7cb74d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.binaryTypeIsReference import org.jetbrains.kotlin.backend.konan.serialization.isExported import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.getFunctionalClassKind @@ -15,15 +16,21 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty /** @@ -207,3 +214,54 @@ internal fun FunctionDescriptorImpl.initialize( modality, visibility ) + +private fun sourceByIndex(descriptor: CallableMemberDescriptor, index: Int): SourceFile { + val fragment = descriptor.findPackage() as KonanPackageFragment + return fragment.sourceFileMap.sourceFile(index) +} + +fun CallableMemberDescriptor.findSourceFile(): SourceFile { + val source = this.source.containingFile + if (source != SourceFile.NO_SOURCE_FILE) + return source + return when { + this is DeserializedSimpleFunctionDescriptor && proto.hasExtension(KonanProtoBuf.functionFile) -> sourceByIndex( + this, proto.getExtension(KonanProtoBuf.functionFile)) + this is DeserializedPropertyDescriptor && proto.hasExtension(KonanProtoBuf.propertyFile) -> + sourceByIndex( + this, proto.getExtension(KonanProtoBuf.propertyFile)) + else -> TODO() + } +} + +private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic") +private val symbolNameAnnotation = FqName("kotlin.native.SymbolName") +private val objCMethodAnnotation = FqName("kotlinx.cinterop.ObjCMethod") +private val frozenAnnotation = FqName("kotlin.native.internal.Frozen") + +internal val DeclarationDescriptor.isFrozen: Boolean + get() = this.annotations.hasAnnotation(frozenAnnotation) || + // RTTI is used for non-reference type box: + this is org.jetbrains.kotlin.descriptors.ClassDescriptor && !this.defaultType.binaryTypeIsReference() + +internal val FunctionDescriptor.isIntrinsic: Boolean + get() = this.annotations.hasAnnotation(intrinsicAnnotation) + +// TODO: coalesce all our annotation value getters into fewer functions. +fun getAnnotationValue(annotation: AnnotationDescriptor): String? { + return annotation.allValueArguments.values.ifNotEmpty { + val stringValue = single() as? StringValue + stringValue?.value + } +} + +fun CallableMemberDescriptor.externalSymbolOrThrow(): String? { + this.annotations.findAnnotation(symbolNameAnnotation)?.let { + return getAnnotationValue(it)!! + } + if (this.annotations.hasAnnotation(intrinsicAnnotation)) return null + + if (this.annotations.hasAnnotation(objCMethodAnnotation)) return null + + throw Error("external function ${this} must have @SymbolName, @Intrinsic or @ObjCMethod annotation") +} 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 3d69739a9fb..539b9c8f1d0 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 @@ -6,7 +6,8 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef -import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValue import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isInlined @@ -23,8 +24,6 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.konan.library.uniqueName import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.constants.StringValue -import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty // This file describes the ABI for Kotlin descriptors of exported declarations. @@ -105,9 +104,6 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean { private val symbolNameAnnotation = FqName("kotlin.native.SymbolName") -private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic") -private val objCMethodAnnotation = FqName("kotlinx.cinterop.ObjCMethod") - private val cnameAnnotation = FqName("kotlin.native.CName") private val exportForCppRuntimeAnnotation = FqName("kotlin.native.internal.ExportForCppRuntime") @@ -211,17 +207,13 @@ internal val FunctionDescriptor.symbolName: String } if (isExternal) { - this.descriptor.annotations.findAnnotation(symbolNameAnnotation)?.let { - return getStringValue(it)!! - } - if (!this.descriptor.annotations.hasAnnotation(intrinsicAnnotation) && - !this.descriptor.annotations.hasAnnotation(objCMethodAnnotation)) { - throw Error("external function ${this.descriptor} must have @SymbolName, @Intrinsic or @ObjCMethod annotation") + this.descriptor.externalSymbolOrThrow()?.let { + return it } } this.descriptor.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let { - val name = getStringValue(it) ?: this.name.asString() + val name = getAnnotationValue(it) ?: this.name.asString() return name // no wrapping currently required } @@ -242,13 +234,6 @@ internal val IrField.symbolName: String } -internal fun getStringValue(annotation: AnnotationDescriptor): String? { - return annotation.allValueArguments.values.ifNotEmpty { - val stringValue = single() as? StringValue - stringValue?.value - } -} - // TODO: bring here dependencies of this method? internal fun RuntimeAware.getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef { val original = function.original diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index aa702f6d6c8..00eea3d7ca0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -91,7 +91,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMValueRef?) { val annot = classDesc.descriptor.annotations.findAnnotation(EXPORT_TYPE_INFO_FQ_NAME) if (annot != null) { - val name = getStringValue(annot)!! + val name = getAnnotationValue(annot)!! // TODO: use LLVMAddAlias. val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true) LLVMSetInitializer(global, typeInfoGlobal) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt index 7e3fd85a6fa..7900bc283a3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember import org.jetbrains.kotlin.backend.konan.getInlinedClass import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo @@ -156,8 +157,6 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean { private val symbolNameAnnotation = FqName("kotlin.native.SymbolName") -private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic") - private val exportForCppRuntimeAnnotation = FqName("kotlin.native.internal.ExportForCppRuntime") private val cnameAnnotation = FqName("kotlin.native.internal.CName") @@ -249,11 +248,8 @@ private val FunctionDescriptor.uniqueName: String } if (this.isExternal) { - this.annotations.findAnnotation(symbolNameAnnotation)?.let { - return getStringValue(it)!! - } - if (!annotations.hasAnnotation(intrinsicAnnotation)) { - throw Error("external function $this must have @SymbolName annotation") + externalSymbolOrThrow()?.let { + return it } } // TODO: check that only external function has @SymbolName.