Refactor annotation checks, fix regression. (#2285)

This commit is contained in:
Nikolay Igotti
2018-10-31 13:49:25 +03:00
committed by GitHub
parent 0a43fa21d3
commit 6249f4bdfe
5 changed files with 69 additions and 61 deletions
@@ -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<SimpleType, IrSimpleFunction>): 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
@@ -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")
}
@@ -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
@@ -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)
@@ -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.