Rewrote all usages of annotations from descriptors to IR

This commit is contained in:
Igor Chevdar
2019-06-24 19:34:55 +03:00
parent 1e8eb1d4a8
commit 440c03035d
22 changed files with 176 additions and 324 deletions
@@ -7,10 +7,11 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
internal fun IrClass.isNonGeneratedAnnotation(): Boolean = internal fun IrClass.isNonGeneratedAnnotation(): Boolean =
this.kind == ClassKind.ANNOTATION_CLASS && this.kind == ClassKind.ANNOTATION_CLASS &&
!this.descriptor.annotations.hasAnnotation(serialInfoAnnotationFqName) !this.annotations.hasAnnotation(serialInfoAnnotationFqName)
private val serialInfoAnnotationFqName = FqName("kotlinx.serialization.SerialInfo") private val serialInfoAnnotationFqName = FqName("kotlinx.serialization.SerialInfo")
@@ -13,12 +13,16 @@ internal const val NATIVE_PTR_NAME = "NativePtr"
internal const val NON_NULL_NATIVE_PTR_NAME = "NonNullNativePtr" internal const val NON_NULL_NATIVE_PTR_NAME = "NonNullNativePtr"
object KonanFqNames { object KonanFqNames {
val packageName = FqName("kotlin.native") val packageName = FqName("kotlin.native")
val internalPackageName = FqName("kotlin.native.internal") val internalPackageName = FqName("kotlin.native.internal")
val nativePtr = internalPackageName.child(Name.identifier(NATIVE_PTR_NAME)).toUnsafe() val nativePtr = internalPackageName.child(Name.identifier(NATIVE_PTR_NAME)).toUnsafe()
val nonNullNativePtr = internalPackageName.child(Name.identifier(NON_NULL_NATIVE_PTR_NAME)).toUnsafe() val nonNullNativePtr = internalPackageName.child(Name.identifier(NON_NULL_NATIVE_PTR_NAME)).toUnsafe()
val throws = FqName("kotlin.native.Throws") val throws = FqName("kotlin.native.Throws")
val threadLocal = FqName("kotlin.native.concurrent.ThreadLocal")
val sharedImmutable = FqName("kotlin.native.concurrent.SharedImmutable")
val frozen = FqName("kotlin.native.internal.Frozen")
val typedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic")
val objCMethod = FqName("kotlinx.cinterop.ObjCMethod")
} }
/** /**
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.constructedClass import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isReal
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition
@@ -61,8 +58,7 @@ fun ClassDescriptor.isExternalObjCClass(): Boolean = this.isObjCClass() &&
} }
fun IrClass.isExternalObjCClass(): Boolean = this.isObjCClass() && fun IrClass.isExternalObjCClass(): Boolean = this.isObjCClass() &&
(this as IrDeclaration).parentDeclarationsWithSelf.filterIsInstance<IrClass>().any { (this as IrDeclaration).parentDeclarationsWithSelf.filterIsInstance<IrClass>().any {
it.annotations.hasAnnotation(externalObjCClassFqName) || it.annotations.hasAnnotation(externalObjCClassFqName)
it.descriptor.annotations.hasAnnotation(externalObjCClassFqName)
} }
fun ClassDescriptor.isObjCForwardDeclaration(): Boolean = fun ClassDescriptor.isObjCForwardDeclaration(): Boolean =
@@ -140,9 +136,9 @@ fun FunctionDescriptor.getObjCMethodInfo(): ObjCMethodInfo? = this.getObjCMethod
fun IrFunction.isObjCBridgeBased(): Boolean { fun IrFunction.isObjCBridgeBased(): Boolean {
assert(this.isReal) assert(this.isReal)
return this.descriptor.annotations.hasAnnotation(objCMethodFqName) || return this.annotations.hasAnnotation(objCMethodFqName) ||
this.descriptor.annotations.hasAnnotation(objCFactoryFqName) || this.annotations.hasAnnotation(objCFactoryFqName) ||
this.descriptor.annotations.hasAnnotation(objCConstructorFqName) this.annotations.hasAnnotation(objCConstructorFqName)
} }
/** /**
@@ -222,11 +218,11 @@ fun ConstructorDescriptor.objCConstructorIsDesignated(): Boolean {
} }
val IrConstructor.isObjCConstructor get() = this.descriptor.annotations.hasAnnotation(objCConstructorFqName) val IrConstructor.isObjCConstructor get() = this.annotations.hasAnnotation(objCConstructorFqName)
// TODO-DCE-OBJC-INIT: Selector should be preserved by DCE. // TODO-DCE-OBJC-INIT: Selector should be preserved by DCE.
fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? { fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? {
return this.descriptor.annotations.findAnnotation(objCConstructorFqName)?.let { return this.annotations.findAnnotation(objCConstructorFqName)?.let {
val initSelector = it.getStringValue("initSelector") val initSelector = it.getStringValue("initSelector")
this.constructedClass.declarations.asSequence() this.constructedClass.declarations.asSequence()
.filterIsInstance<IrSimpleFunction>() .filterIsInstance<IrSimpleFunction>()
@@ -234,9 +230,9 @@ fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? {
} }
} }
val IrFunction.hasObjCFactoryAnnotation get() = this.descriptor.annotations.hasAnnotation(objCFactoryFqName) val IrFunction.hasObjCFactoryAnnotation get() = this.annotations.hasAnnotation(objCFactoryFqName)
val IrFunction.hasObjCMethodAnnotation get() = this.descriptor.annotations.hasAnnotation(objCMethodFqName) val IrFunction.hasObjCMethodAnnotation get() = this.annotations.hasAnnotation(objCMethodFqName)
fun FunctionDescriptor.getObjCFactoryInitMethodInfo(): ObjCMethodInfo? { fun FunctionDescriptor.getObjCFactoryInitMethodInfo(): ObjCMethodInfo? {
val factoryAnnotation = this.annotations.findAnnotation(objCFactoryFqName) ?: return null val factoryAnnotation = this.annotations.findAnnotation(objCFactoryFqName) ?: return null
@@ -581,11 +581,9 @@ private fun IrType.isCEnumType(): Boolean {
.any { (it.classifierOrNull?.owner as? IrClass)?.fqNameForIrSerialization == FqName("kotlinx.cinterop.CEnum") } .any { (it.classifierOrNull?.owner as? IrClass)?.fqNameForIrSerialization == FqName("kotlinx.cinterop.CEnum") }
} }
// TODO: get rid of consulting descriptors for annotations.
// Make sure external stubs always get proper annotaions. // Make sure external stubs always get proper annotaions.
private fun IrDeclaration.hasCCallAnnotation(name: String): Boolean = private fun IrDeclaration.hasCCallAnnotation(name: String): Boolean =
this.annotations.hasAnnotation(cCall.child(Name.identifier(name))) || this.annotations.hasAnnotation(cCall.child(Name.identifier(name)))
this.descriptor.annotations.hasAnnotation(cCall.child(Name.identifier(name)))
private fun IrValueParameter.isWCStringParameter() = hasCCallAnnotation("WCString") private fun IrValueParameter.isWCStringParameter() = hasCCallAnnotation("WCString")
@@ -5,17 +5,19 @@
package org.jetbrains.kotlin.backend.konan.descriptors package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.isInlinedNative import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.backend.konan.llvm.longName
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.isReal
import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.ir.util.overrides
import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.SimpleType
/** /**
@@ -75,12 +77,8 @@ internal fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false
return realSupers.first { allowAbstract || it.modality != Modality.ABSTRACT } return realSupers.first { allowAbstract || it.modality != Modality.ABSTRACT }
} }
// TODO: don't forget to remove descriptor access here.
internal val IrFunction.isTypedIntrinsic: Boolean internal val IrFunction.isTypedIntrinsic: Boolean
get() = this.descriptor.isTypedIntrinsic get() = annotations.hasAnnotation(KonanFqNames.typedIntrinsic)
internal val IrDeclaration.isFrozen: Boolean
get() = this.descriptor.isFrozen
internal val arrayTypes = setOf( internal val arrayTypes = setOf(
"kotlin.Array", "kotlin.Array",
@@ -242,4 +240,28 @@ fun IrDeclaration.findTopLevelDeclaration(): IrDeclaration = when {
(this as IrField).correspondingProperty!!.findTopLevelDeclaration() (this as IrField).correspondingProperty!!.findTopLevelDeclaration()
else -> else ->
(this.parent as IrDeclaration).findTopLevelDeclaration() (this.parent as IrDeclaration).findTopLevelDeclaration()
} }
internal val IrClass.isFrozen: Boolean
get() = annotations.hasAnnotation(KonanFqNames.frozen) ||
// RTTI is used for non-reference type box or Objective-C object wrapper:
!this.defaultType.binaryTypeIsReference() || this.isObjCClass()
fun IrConstructorCall.getAnnotationValue() = (getValueArgument(0) as? IrConst<String>)?.value
fun IrConstructorCall.getStringValue(name: String): String {
val parameter = symbol.owner.valueParameters.single { it.name.asString() == name }
return (getValueArgument(parameter.index) as IrConst<String>).value
}
fun IrFunction.externalSymbolOrThrow(): String? {
annotations.findAnnotation(RuntimeNames.symbolNameAnnotation)?.let { return it.getAnnotationValue() }
if (annotations.hasAnnotation(KonanFqNames.objCMethod)) return null
if (annotations.hasAnnotation(KonanFqNames.typedIntrinsic)) return null
if (annotations.hasAnnotation(RuntimeNames.cCall)) return null
throw Error("external function ${this.longName} must have @TypedIntrinsic, @SymbolName or @ObjCMethod annotation")
}
@@ -7,22 +7,14 @@ package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.RuntimeNames
import org.jetbrains.kotlin.backend.konan.binaryTypeIsReference
import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.konanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.konanModuleOrigin
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -30,11 +22,8 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
/** /**
* Implementation of given method. * Implementation of given method.
@@ -172,31 +161,6 @@ internal val DeclarationDescriptor.isExpectMember: Boolean
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this) get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this)
internal fun KotlinType?.createExtensionReceiver(owner: CallableDescriptor): ReceiverParameterDescriptor? =
DescriptorFactory.createExtensionReceiverParameterForCallable(
owner,
this,
Annotations.EMPTY
)
internal fun FunctionDescriptorImpl.initialize(
extensionReceiverType: KotlinType?,
dispatchReceiverParameter: ReceiverParameterDescriptor?,
typeParameters: List<TypeParameterDescriptor>,
unsubstitutedValueParameters: List<ValueParameterDescriptor>,
unsubstitutedReturnType: KotlinType?,
modality: Modality?,
visibility: Visibility
): FunctionDescriptorImpl = this.initialize(
extensionReceiverType.createExtensionReceiver(this),
dispatchReceiverParameter,
typeParameters,
unsubstitutedValueParameters,
unsubstitutedReturnType,
modality,
visibility
)
private fun sourceByIndex(descriptor: CallableMemberDescriptor, index: Int): SourceFile { private fun sourceByIndex(descriptor: CallableMemberDescriptor, index: Int): SourceFile {
val fragment = descriptor.findPackage() as KonanPackageFragment val fragment = descriptor.findPackage() as KonanPackageFragment
return fragment.sourceFileMap.sourceFile(index) return fragment.sourceFileMap.sourceFile(index)
@@ -216,43 +180,4 @@ fun CallableMemberDescriptor.findSourceFile(): SourceFile {
} }
} }
internal val DeclarationDescriptor.isFrozen: Boolean
get() = this.annotations.hasAnnotation(RuntimeNames.frozenAnnotation) ||
(this is org.jetbrains.kotlin.descriptors.ClassDescriptor
// RTTI is used for non-reference type box or Objective-C object wrapper:
&& (!this.defaultType.binaryTypeIsReference() || this.isObjCClass()))
internal val FunctionDescriptor.isTypedIntrinsic: Boolean
get() = this.annotations.hasAnnotation(RuntimeNames.typedIntrinsicAnnotation)
// 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(RuntimeNames.symbolNameAnnotation)?.let {
return getAnnotationValue(it)!!
}
if (this.annotations.hasAnnotation(RuntimeNames.objCMethodAnnotation)) return null
if (this.annotations.hasAnnotation(RuntimeNames.typedIntrinsicAnnotation)) return null
if (this.annotations.hasAnnotation(RuntimeNames.cCall)) return null
throw Error("external function ${this} must have @TypedIntrinsic, @SymbolName or @ObjCMethod annotation")
}
fun createAnnotation(
descriptor: ClassDescriptor,
vararg values: Pair<String, String>
): AnnotationDescriptor = AnnotationDescriptorImpl(
descriptor.defaultType,
values.map { (name, value) -> Name.identifier(name) to StringValue(value) }.toMap(),
SourceElement.NO_SOURCE
)
val ModuleDescriptor.konanLibrary get() = (this.konanModuleOrigin as? DeserializedKonanModuleOrigin)?.library val ModuleDescriptor.konanLibrary get() = (this.konanModuleOrigin as? DeserializedKonanModuleOrigin)?.library
@@ -451,13 +451,13 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
) )
val listOfInternal = internalFunction("listOfInternal") val listOfInternal = internalFunction("listOfInternal")
val threadLocal = val threadLocal = symbolTable.referenceClass(
context.builtIns.builtInsModule.findClassAcrossModuleDependencies( context.builtIns.builtInsModule.findClassAcrossModuleDependencies(
ClassId.topLevel(FqName("kotlin.native.concurrent.ThreadLocal")))!! ClassId.topLevel(KonanFqNames.threadLocal))!!)
val sharedImmutable = val sharedImmutable = symbolTable.referenceClass(
context.builtIns.builtInsModule.findClassAcrossModuleDependencies( context.builtIns.builtInsModule.findClassAcrossModuleDependencies(
ClassId.topLevel(FqName("kotlin.native.concurrent.SharedImmutable")))!! ClassId.topLevel(KonanFqNames.sharedImmutable))!!)
private fun topLevelClass(fqName: String): IrClassSymbol = topLevelClass(FqName(fqName)) private fun topLevelClass(fqName: String): IrClassSymbol = topLevelClass(FqName(fqName))
private fun topLevelClass(fqName: FqName): IrClassSymbol = classById(ClassId.topLevel(fqName)) private fun topLevelClass(fqName: FqName): IrClassSymbol = classById(ClassId.topLevel(fqName))
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
@@ -69,14 +68,7 @@ val IrClass.isFinalClass: Boolean
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing() fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
fun <T> IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? { fun <T> IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? {
val annotation = this.annotations.findAnnotation(fqName) val annotation = this.annotations.findAnnotation(fqName) ?: return null
if (annotation == null) {
// As a last resort try searching the descriptor.
// This is needed for a period while we don't have IR for platform libraries.
return this.descriptor.annotations
.findAnnotation(fqName)
?.getArgumentValueOrNull<T>(argumentName)
}
for (index in 0 until annotation.valueArgumentsCount) { for (index in 0 until annotation.valueArgumentsCount) {
val parameter = annotation.symbol.owner.valueParameters[index] val parameter = annotation.symbol.owner.valueParameters[index]
if (parameter.name == Name.identifier(argumentName)) { if (parameter.name == Name.identifier(argumentName)) {
@@ -18,11 +18,9 @@ import org.jetbrains.kotlin.backend.konan.ir.isUnit
import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler.isExported import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler.isExported
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.ir.util.isVararg
import org.jetbrains.kotlin.backend.konan.isInlinedNative import org.jetbrains.kotlin.backend.konan.isInlinedNative
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.library.uniqueName import org.jetbrains.kotlin.library.uniqueName
@@ -45,20 +43,19 @@ object KonanMangler : KotlinManglerImpl() {
*/ */
override fun IrDeclaration.isPlatformSpecificExported(): Boolean { override fun IrDeclaration.isPlatformSpecificExported(): Boolean {
// TODO: revise // TODO: revise
val descriptorAnnotations = this.descriptor.annotations if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
if (descriptorAnnotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
// Treat any `@SymbolName` declaration as exported. // Treat any `@SymbolName` declaration as exported.
return true return true
} }
if (descriptorAnnotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) {
// Treat any `@ExportForCppRuntime` declaration as exported. // Treat any `@ExportForCppRuntime` declaration as exported.
return true return true
} }
if (descriptorAnnotations.hasAnnotation(RuntimeNames.cnameAnnotation)) { if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
// Treat `@CName` declaration as exported. // Treat `@CName` declaration as exported.
return true return true
} }
if (descriptorAnnotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) { if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
return true return true
} }
@@ -107,13 +104,13 @@ object KonanMangler : KotlinManglerImpl() {
} }
if (isExternal) { if (isExternal) {
this.descriptor.externalSymbolOrThrow()?.let { this.externalSymbolOrThrow()?.let {
return it return it
} }
} }
this.descriptor.annotations.findAnnotation(RuntimeNames.exportForCppRuntime)?.let { this.annotations.findAnnotation(RuntimeNames.exportForCppRuntime)?.let {
val name = getAnnotationValue(it) ?: this.name.asString() val name = it.getAnnotationValue() ?: this.name.asString()
return name // no wrapping currently required return name // no wrapping currently required
} }
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.cValuesOf import kotlinx.cinterop.cValuesOf
import llvm.* import llvm.*
import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.RuntimeNames
import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValue
import org.jetbrains.kotlin.backend.konan.descriptors.isTypedIntrinsic import org.jetbrains.kotlin.backend.konan.descriptors.isTypedIntrinsic
import org.jetbrains.kotlin.backend.konan.llvm.objc.genObjCSelector import org.jetbrains.kotlin.backend.konan.llvm.objc.genObjCSelector
import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.backend.konan.reportCompilationError
@@ -12,8 +13,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.findAnnotation
import org.jetbrains.kotlin.ir.util.isSuspend import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.name.Name
internal enum class IntrinsicType { internal enum class IntrinsicType {
PLUS, PLUS,
@@ -113,8 +114,8 @@ internal fun tryGetIntrinsicType(callSite: IrFunctionAccessExpression): Intrinsi
private fun getIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicType { private fun getIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicType {
val function = callSite.symbol.owner val function = callSite.symbol.owner
val annotation = function.descriptor.annotations.findAnnotation(RuntimeNames.typedIntrinsicAnnotation)!! val annotation = function.annotations.findAnnotation(RuntimeNames.typedIntrinsicAnnotation)!!
val value = annotation.allValueArguments.getValue(Name.identifier("kind")).value as String val value = annotation.getAnnotationValue()!!
return IntrinsicType.valueOf(value) return IntrinsicType.valueOf(value)
} }
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.ir.NaiveSourceBasedFileEntryImpl import org.jetbrains.kotlin.backend.konan.ir.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.backend.konan.ir.containsNull import org.jetbrains.kotlin.backend.konan.ir.containsNull
import org.jetbrains.kotlin.backend.konan.llvm.coverage.* import org.jetbrains.kotlin.backend.konan.llvm.coverage.*
import org.jetbrains.kotlin.backend.konan.llvm.objcexport.is64Bit
import org.jetbrains.kotlin.backend.konan.optimizations.* import org.jetbrains.kotlin.backend.konan.optimizations.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.builtins.UnsignedType
@@ -28,29 +27,14 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
private val threadLocalAnnotationFqName = FqName("kotlin.native.concurrent.ThreadLocal")
private val sharedAnnotationFqName = FqName("kotlin.native.concurrent.SharedImmutable")
private val frozenAnnotationFqName = FqName("kotlin.native.internal.Frozen")
val IrField.propertyDescriptor: PropertyDescriptor
get() {
val descriptor = this.descriptor
return if (descriptor is IrPropertyDelegateDescriptor)
descriptor.correspondingProperty
else
descriptor
}
internal enum class FieldStorage { internal enum class FieldStorage {
MAIN_THREAD, MAIN_THREAD,
SHARED, SHARED,
@@ -59,17 +43,18 @@ internal enum class FieldStorage {
// TODO: maybe unannotated singleton objects shall be accessed from main thread only as well? // TODO: maybe unannotated singleton objects shall be accessed from main thread only as well?
val IrClass.objectIsShared get() = val IrClass.objectIsShared get() =
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) !annotations.hasAnnotation(KonanFqNames.threadLocal)
internal val IrField.storageClass: FieldStorage get() { internal val IrField.storageClass: FieldStorage get() {
val descriptor = propertyDescriptor // TODO: Is this correct?
val annotations = correspondingPropertySymbol?.owner?.annotations ?: annotations
return when { return when {
descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) -> FieldStorage.THREAD_LOCAL annotations.hasAnnotation(KonanFqNames.threadLocal) -> FieldStorage.THREAD_LOCAL
!isFinal -> FieldStorage.MAIN_THREAD !isFinal -> FieldStorage.MAIN_THREAD
descriptor.annotations.hasAnnotation(sharedAnnotationFqName) -> FieldStorage.SHARED annotations.hasAnnotation(KonanFqNames.sharedImmutable) -> FieldStorage.SHARED
// TODO: simplify, once IR types are fully there. // TODO: simplify, once IR types are fully there.
type is IrSimpleType && (type as IrSimpleType). (type.classifierOrNull?.owner as? IrAnnotationContainer)
classifier.descriptor.annotations.hasAnnotation(frozenAnnotationFqName) -> FieldStorage.SHARED ?.annotations?.hasAnnotation(KonanFqNames.frozen) == true -> FieldStorage.SHARED
else -> FieldStorage.MAIN_THREAD else -> FieldStorage.MAIN_THREAD
} }
} }
@@ -682,7 +667,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
} }
if (declaration.descriptor.retainAnnotation(context.config.target)) { if (declaration.retainAnnotation(context.config.target)) {
context.llvm.usedFunctions.add(codegen.llvmFunction(declaration)) context.llvm.usedFunctions.add(codegen.llvmFunction(declaration))
} }
@@ -1452,11 +1437,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
// TODO: rewrite in IR! private fun needMutationCheck(irClass: IrClass): Boolean {
private fun needMutationCheck(descriptor: org.jetbrains.kotlin.descriptors.DeclarationDescriptor): Boolean {
// For now we omit mutation checks on immutable types, as this allows initialization in constructor // For now we omit mutation checks on immutable types, as this allows initialization in constructor
// and it is assumed that API doesn't allow to change them. // and it is assumed that API doesn't allow to change them.
return !descriptor.isFrozen return !irClass.isFrozen
} }
private fun evaluateSetField(value: IrSetField): LLVMValueRef { private fun evaluateSetField(value: IrSetField): LLVMValueRef {
@@ -1467,7 +1451,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
assert(thisPtr.type == codegen.kObjHeaderPtr) { assert(thisPtr.type == codegen.kObjHeaderPtr) {
LLVMPrintTypeToString(thisPtr.type)?.toKString().toString() LLVMPrintTypeToString(thisPtr.type)?.toKString().toString()
} }
if (needMutationCheck(value.descriptor.containingDeclaration)) { if (needMutationCheck(value.symbol.owner.parentAsClass)) {
functionGenerationContext.call(context.llvm.mutationCheck, functionGenerationContext.call(context.llvm.mutationCheck,
listOf(functionGenerationContext.bitcast(codegen.kObjHeaderPtr, thisPtr)), listOf(functionGenerationContext.bitcast(codegen.kObjHeaderPtr, thisPtr)),
Lifetime.IRRELEVANT, ExceptionHandler.Caller) Lifetime.IRRELEVANT, ExceptionHandler.Caller)
@@ -2086,7 +2070,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
assert(irClass.isInterface) assert(irClass.isInterface)
assert(irClass.isExternalObjCClass()) assert(irClass.isExternalObjCClass())
val annotation = irClass.descriptor.annotations.findAnnotation(externalObjCClassFqName)!! val annotation = irClass.annotations.findAnnotation(externalObjCClassFqName)!!
val protocolGetterName = annotation.getStringValue("protocolGetter") val protocolGetterName = annotation.getStringValue("protocolGetter")
val protocolGetter = context.llvm.externalFunction( val protocolGetter = context.llvm.externalFunction(
protocolGetterName, protocolGetterName,
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.backend.konan.llvm
import llvm.LLVMStoreSizeOfType import llvm.LLVMStoreSizeOfType
import llvm.LLVMValueRef import llvm.LLVMValueRef
import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.getStringValue import org.jetbrains.kotlin.backend.konan.descriptors.getStringValue
import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.findAnnotation
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -118,7 +118,7 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
.filterIsInstance<IrSimpleFunction>() .filterIsInstance<IrSimpleFunction>()
.mapNotNull { .mapNotNull {
val annotation = val annotation =
it.descriptor.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?: it.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?:
return@mapNotNull null return@mapNotNull null
ObjCMethodDesc( ObjCMethodDesc(
@@ -14,8 +14,6 @@ import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.konan.KonanAbiVersion
import org.jetbrains.kotlin.ir.util.fqNameSafe
import org.jetbrains.kotlin.ir.util.isAnnotationClass import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.library.KotlinAbiVersion
@@ -128,9 +126,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
private val EXPORT_TYPE_INFO_FQ_NAME = FqName.fromSegments(listOf("kotlin", "native", "internal", "ExportTypeInfo")) private val EXPORT_TYPE_INFO_FQ_NAME = FqName.fromSegments(listOf("kotlin", "native", "internal", "ExportTypeInfo"))
private fun exportTypeInfoIfRequired(irClass: IrClass, typeInfoGlobal: LLVMValueRef?) { private fun exportTypeInfoIfRequired(irClass: IrClass, typeInfoGlobal: LLVMValueRef?) {
val annotation = irClass.descriptor.annotations.findAnnotation(EXPORT_TYPE_INFO_FQ_NAME) val annotation = irClass.annotations.findAnnotation(EXPORT_TYPE_INFO_FQ_NAME)
if (annotation != null) { if (annotation != null) {
val name = getAnnotationValue(annotation)!! val name = annotation.getAnnotationValue()!!
// TODO: use LLVMAddAlias. // TODO: use LLVMAddAlias.
val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true) val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true)
LLVMSetInitializer(global, typeInfoGlobal) LLVMSetInitializer(global, typeInfoGlobal)
@@ -5,18 +5,18 @@
package org.jetbrains.kotlin.backend.konan.llvm package org.jetbrains.kotlin.backend.konan.llvm
import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValue
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.util.findAnnotation
import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
private val retainAnnotationName = FqName("kotlin.native.Retain") private val retainAnnotationName = FqName("kotlin.native.Retain")
private val retainForTargetAnnotationName = FqName("kotlin.native.RetainForTarget") private val retainForTargetAnnotationName = FqName("kotlin.native.RetainForTarget")
internal fun IrFunction.retainAnnotation(target: KonanTarget): Boolean {
internal fun FunctionDescriptor.retainAnnotation(target: KonanTarget): Boolean {
if (this.annotations.findAnnotation(retainAnnotationName) != null) return true if (this.annotations.findAnnotation(retainAnnotationName) != null) return true
val forTarget = this.annotations.findAnnotation(retainForTargetAnnotationName) val forTarget = this.annotations.findAnnotation(retainForTargetAnnotationName)
if (forTarget != null && forTarget.getStringValueOrNull("target") == target.name) return true if (forTarget != null && forTarget.getAnnotationValue() == target.name) return true
return false return false
} }
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.ir.fqNameForIrSerialization
import org.jetbrains.kotlin.backend.konan.ir.isFunctionOrKFunctionType import org.jetbrains.kotlin.backend.konan.ir.isFunctionOrKFunctionType
import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.functionName
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -95,11 +94,10 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
if (cur !is IrCall) if (cur !is IrCall)
break break
val argument = if (i < stack.size - 1) stack[i + 1] else expression val argument = if (i < stack.size - 1) stack[i + 1] else expression
val descriptor = cur.descriptor val parameter = cur.symbol.owner.valueParameters.singleOrNull {
val argumentDescriptor = descriptor.valueParameters.singleOrNull {
cur.getValueArgument(it.index) == argument cur.getValueArgument(it.index) == argument
} }
if (argumentDescriptor?.annotations?.findAnnotation(VOLATILE_LAMBDA_FQ_NAME) != null) { if (parameter?.annotations?.findAnnotation(VOLATILE_LAMBDA_FQ_NAME) != null) {
return expression return expression
} }
break break
@@ -10,12 +10,13 @@ import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.contracts.parsing.ContractsDslNames import org.jetbrains.kotlin.contracts.parsing.ContractsDslNames
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
internal class ContractsDslRemover(val context: Context) : DeclarationContainerLoweringPass { internal class ContractsDslRemover(val context: Context) : DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { irDeclarationContainer.declarations.transformFlat {
if (it is IrClass && it.descriptor.annotations.hasAnnotation(ContractsDslNames.CONTRACTS_DSL_ANNOTATION_FQN)) if (it is IrClass && it.annotations.hasAnnotation(ContractsDslNames.CONTRACTS_DSL_ANNOTATION_FQN))
null null
else else
listOf(it) listOf(it)
@@ -12,6 +12,10 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections
import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -87,10 +91,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType) val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType)
val kPropertiesField = WrappedFieldDescriptor( val kPropertiesField = WrappedFieldDescriptor().let {
Annotations.create(listOf(AnnotationDescriptorImpl(context.ir.symbols.sharedImmutable.defaultType,
emptyMap(), SourceElement.NO_SOURCE)))
).let {
IrFieldImpl( IrFieldImpl(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
@@ -104,6 +105,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
).apply { ).apply {
it.bind(this) it.bind(this)
parent = irFile parent = irFile
annotations += buildSimpleAnnotation(context.irBuiltIns, startOffset, endOffset, context.ir.symbols.sharedImmutable.owner)
} }
} }
@@ -5,13 +5,13 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.cgen.* import org.jetbrains.kotlin.backend.konan.cgen.*
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
@@ -26,12 +26,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
@@ -43,15 +38,15 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.OverridingUtil 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.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
internal abstract class BaseInteropIrTransformer(private val context: Context) : IrBuildingTransformer(context) { internal abstract class BaseInteropIrTransformer(private val context: Context) : IrBuildingTransformer(context) {
@@ -159,20 +154,20 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
irClass.declarations.toList().mapNotNull { irClass.declarations.toList().mapNotNull {
when { when {
it is IrSimpleFunction && it.descriptor.annotations.hasAnnotation(interop.objCAction) -> it is IrSimpleFunction && it.annotations.hasAnnotation(interop.objCAction.fqNameSafe) ->
generateActionImp(it) generateActionImp(it)
it is IrProperty && it.descriptor.annotations.hasAnnotation(interop.objCOutlet) -> it is IrProperty && it.annotations.hasAnnotation(interop.objCOutlet.fqNameSafe) ->
generateOutletSetterImp(it) generateOutletSetterImp(it)
it is IrConstructor && it.descriptor.annotations.hasAnnotation(interop.objCOverrideInit) -> it is IrConstructor && it.annotations.hasAnnotation(interop.objCOverrideInit.fqNameSafe) ->
generateOverrideInit(irClass, it) generateOverrideInit(irClass, it)
else -> null else -> null
} }
}.let { irClass.addChildren(it) } }.let { irClass.addChildren(it) }
if (irClass.descriptor.annotations.hasAnnotation(interop.exportObjCClass.fqNameSafe)) { if (irClass.annotations.hasAnnotation(interop.exportObjCClass.fqNameSafe)) {
val irBuilder = context.createIrBuilder(currentFile.symbol).at(irClass) val irBuilder = context.createIrBuilder(currentFile.symbol).at(irClass)
topLevelInitializers.add(irBuilder.getObjCClass(irClass.symbol)) topLevelInitializers.add(irBuilder.getObjCClass(irClass.symbol))
} }
@@ -224,51 +219,26 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
// Generate `override fun init...(...) = this.initBy(...)`: // Generate `override fun init...(...) = this.initBy(...)`:
val resultDescriptor = SimpleFunctionDescriptorImpl.create( val resultDescriptor = WrappedSimpleFunctionDescriptor()
irClass.descriptor,
Annotations.EMPTY,
initMethod.name,
CallableMemberDescriptor.Kind.DECLARATION,
SourceElement.NO_SOURCE
)
val valueParameters = constructor.valueParameters.map {
val descriptor = ValueParameterDescriptorImpl(
resultDescriptor,
null,
it.index,
Annotations.EMPTY,
it.name,
it.descriptor.type,
false,
false,
false,
it.varargElementType?.toKotlinType(),
SourceElement.NO_SOURCE
)
it.copy(descriptor)
}
resultDescriptor.initialize(
null,
irClass.descriptor.thisAsReceiverParameter,
emptyList<TypeParameterDescriptor>(),
valueParameters.map { it.descriptor as ValueParameterDescriptor },
irClass.descriptor.defaultType,
Modality.OPEN,
Visibilities.PUBLIC
)
return IrFunctionImpl( return IrFunctionImpl(
constructor.startOffset, constructor.endOffset, OVERRIDING_INITIALIZER_BY_CONSTRUCTOR, constructor.startOffset, constructor.endOffset,
resultDescriptor, OVERRIDING_INITIALIZER_BY_CONSTRUCTOR,
irClass.defaultType IrSimpleFunctionSymbolImpl(resultDescriptor),
initMethod.name,
Visibilities.PUBLIC,
Modality.OPEN,
irClass.defaultType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false
).also { result -> ).also { result ->
resultDescriptor.bind(result)
result.parent = irClass result.parent = irClass
result.createDispatchReceiverParameter() result.createDispatchReceiverParameter()
result.valueParameters += valueParameters constructor.valueParameters.mapTo(result.valueParameters) { it.copyTo(result) }
result.overriddenSymbols.add(initMethod.symbol) result.overriddenSymbols.add(initMethod.symbol)
result.descriptor.overriddenDescriptors = listOf(initMethod.descriptor)
result.body = context.createIrBuilder(result.symbol).irBlockBody(result) { result.body = context.createIrBuilder(result.symbol).irBlockBody(result) {
+irReturn( +irReturn(
@@ -390,54 +360,40 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
} }
} }
val newDescriptor = SimpleFunctionDescriptorImpl.create( val newFunction = WrappedSimpleFunctionDescriptor().let {
function.descriptor.containingDeclaration, IrFunctionImpl(
Annotations.EMPTY, function.startOffset, function.endOffset,
("imp:" + selector).synthesizedName, IrDeclarationOrigin.DEFINED,
CallableMemberDescriptor.Kind.SYNTHESIZED, IrSimpleFunctionSymbolImpl(it),
SourceElement.NO_SOURCE ("imp:$selector").synthesizedName,
) Visibilities.PRIVATE,
Modality.FINAL,
val valueParameters = parameterTypes.mapIndexed { index, it -> returnType,
ValueParameterDescriptorImpl( isInline = false,
newDescriptor, isExternal = false,
null, isTailrec = false,
index, isSuspend = false
Annotations.EMPTY, ).apply {
Name.identifier("p$index"), it.bind(this)
it.toKotlinType(), }
false,
false,
false,
null,
SourceElement.NO_SOURCE
)
} }
newDescriptor.initialize( parameterTypes.mapIndexedTo(newFunction.valueParameters) { index, type ->
null, null, WrappedValueParameterDescriptor().let {
emptyList(),
valueParameters,
function.descriptor.returnType,
Modality.FINAL,
Visibilities.PRIVATE
)
val newFunction = IrFunctionImpl(
function.startOffset, function.endOffset,
IrDeclarationOrigin.DEFINED,
newDescriptor,
function.returnType
).apply {
parameterTypes.mapIndexedTo(this.valueParameters) { index, it ->
IrValueParameterImpl( IrValueParameterImpl(
startOffset, function.startOffset, function.endOffset,
endOffset,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
descriptor.valueParameters[index], IrValueParameterSymbolImpl(it),
it, Name.identifier("p$index"),
null index,
) type,
varargElementType = null,
isCrossinline = false,
isNoinline = false
).apply {
it.bind(this)
parent = newFunction
}
} }
} }
@@ -480,18 +436,6 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
} }
} }
private fun createObjCMethodImpAnnotations(selector: String, encoding: String): Annotations {
val annotation = AnnotationDescriptorImpl(
context.interopBuiltIns.objCMethodImp.defaultType,
mapOf("selector" to selector, "encoding" to encoding)
.mapKeys { Name.identifier(it.key) }
.mapValues { StringValue(it.value) },
SourceElement.NO_SOURCE
)
return Annotations.create(listOf(annotation))
}
private fun checkKotlinObjCClass(irClass: IrClass) { private fun checkKotlinObjCClass(irClass: IrClass) {
val kind = irClass.descriptor.kind val kind = irClass.descriptor.kind
if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT) { if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT) {
@@ -561,7 +505,6 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
builder.at(expression) builder.at(expression)
val constructedClass = outerClasses.peek()!! val constructedClass = outerClasses.peek()!!
val constructedClassDescriptor = constructedClass.descriptor
if (!constructedClass.isObjCClass()) { if (!constructedClass.isObjCClass()) {
return expression return expression
@@ -578,12 +521,13 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
} }
} }
val delegatingCallConstructingClass = expression.symbol.owner.constructedClass
if (!constructedClass.isExternalObjCClass() && if (!constructedClass.isExternalObjCClass() &&
(expression.symbol.owner.constructedClass).isExternalObjCClass()) { delegatingCallConstructingClass.isExternalObjCClass()) {
// Calling super constructor from Kotlin Objective-C class. // Calling super constructor from Kotlin Objective-C class.
assert(constructedClassDescriptor.getSuperClassNotAny() == expression.descriptor.constructedClass) assert(constructedClass.getSuperClassNotAny() == delegatingCallConstructingClass)
val initMethod = expression.symbol.owner.getObjCInitMethod()!! val initMethod = expression.symbol.owner.getObjCInitMethod()!!
@@ -602,14 +546,14 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
val initCall = builder.genLoweredObjCMethodCall( val initCall = builder.genLoweredObjCMethodCall(
initMethodInfo, initMethodInfo,
superQualifier = expression.symbol.owner.constructedClass.symbol, superQualifier = delegatingCallConstructingClass.symbol,
receiver = builder.getRawPtr(builder.irGet(constructedClass.thisReceiver!!)), receiver = builder.getRawPtr(builder.irGet(constructedClass.thisReceiver!!)),
arguments = initMethod.valueParameters.map { expression.getValueArgument(it.index) }, arguments = initMethod.valueParameters.map { expression.getValueArgument(it.index) },
call = expression, call = expression,
method = initMethod method = initMethod
) )
val superConstructor = expression.symbol.owner.constructedClass val superConstructor = delegatingCallConstructingClass
.constructors.single { it.valueParameters.size == 0 }.symbol .constructors.single { it.valueParameters.size == 0 }.symbol
return builder.irBlock(expression) { return builder.irBlock(expression) {
@@ -897,7 +841,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
} }
} }
if (function.descriptor.annotations.hasAnnotation(RuntimeNames.cCall)) { if (function.annotations.hasAnnotation(RuntimeNames.cCall)) {
context.llvmImports.add(function.descriptor.llvmSymbolOrigin) context.llvmImports.add(function.descriptor.llvmSymbolOrigin)
return generateWithStubs { generateCCall(expression, builder, isInvoke = false) } return generateWithStubs { generateCCall(expression, builder, isInvoke = false) }
} }
@@ -1186,5 +1130,3 @@ private fun IrBuilder.irFloat(value: Float) =
private fun IrBuilder.irDouble(value: Double) = private fun IrBuilder.irDouble(value: Double) =
IrConstImpl.double(startOffset, endOffset, context.irBuiltIns.doubleType, value) IrConstImpl.double(startOffset, endOffset, context.irBuiltIns.doubleType, value)
private fun Annotations.hasAnnotation(descriptor: ClassDescriptor) = this.hasAnnotation(descriptor.fqNameSafe)
@@ -463,7 +463,7 @@ internal class TestProcessor (val context: Context) {
} }
} }
private val IrClass.ignored: Boolean get() = descriptor.annotations.hasAnnotation(IGNORE_FQ_NAME) private val IrClass.ignored: Boolean get() = annotations.hasAnnotation(IGNORE_FQ_NAME)
/** /**
* Builds a test suite class representing a test class (any class in the original IrFile with method(s) * Builds a test suite class representing a test class (any class in the original IrFile with method(s)
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrGetField
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isNothing
@@ -602,15 +599,15 @@ internal object DataFlowIR {
} }
val symbol = when { val symbol = when {
it.isExternal || (it.symbol in context.irBuiltIns.irBuiltInsSymbols) -> { it.isExternal || (it.symbol in context.irBuiltIns.irBuiltInsSymbols) -> {
val escapesAnnotation = it.descriptor.annotations.findAnnotation(FQ_NAME_ESCAPES) val escapesAnnotation = it.annotations.findAnnotation(FQ_NAME_ESCAPES)
val pointsToAnnotation = it.descriptor.annotations.findAnnotation(FQ_NAME_POINTS_TO) val pointsToAnnotation = it.annotations.findAnnotation(FQ_NAME_POINTS_TO)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val escapesBitMask = (escapesAnnotation?.allValueArguments?.get(escapesWhoDescriptor.name) as? ConstantValue<Int>)?.value val escapesBitMask = (escapesAnnotation?.getValueArgument(0) as? IrConst<Int>)?.value
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val pointsToBitMask = (pointsToAnnotation?.allValueArguments?.get(pointsToOnWhomDescriptor.name) as? ConstantValue<List<IntValue>>)?.value val pointsToBitMask = (pointsToAnnotation?.getValueArgument(0) as? IrVararg)?.elements?.map { (it as IrConst<Int>).value }
FunctionSymbol.External(name.localHash.value, attributes, it, takeName { name }).apply { FunctionSymbol.External(name.localHash.value, attributes, it, takeName { name }).apply {
escapes = escapesBitMask escapes = escapesBitMask
pointsTo = pointsToBitMask?.let { it.map { it.value }.toIntArray() } pointsTo = pointsToBitMask?.let { it.toIntArray() }
} }
} }
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.util.hasAnnotation
class KonanIrModuleSerializer( class KonanIrModuleSerializer(
logger: LoggingContext, logger: LoggingContext,
@@ -15,9 +16,9 @@ class KonanIrModuleSerializer(
) : IrModuleSerializer(logger, declarationTable, KonanMangler, bodiesOnlyForInlines) { ) : IrModuleSerializer(logger, declarationTable, KonanMangler, bodiesOnlyForInlines) {
override fun backendSpecificExplicitRoot(declaration: IrFunction) = override fun backendSpecificExplicitRoot(declaration: IrFunction) =
declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCppRuntime) declaration.annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)
override fun backendSpecificExplicitRoot(declaration: IrClass) = override fun backendSpecificExplicitRoot(declaration: IrClass) =
declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportTypeInfoAnnotation) declaration.annotations.hasAnnotation(RuntimeNames.exportTypeInfoAnnotation)
} }
@@ -7,22 +7,20 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.substitute import org.jetbrains.kotlin.backend.common.descriptors.substitute
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
import org.jetbrains.kotlin.backend.konan.KonanBackendContext import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.backend.konan.KonanCompilationException import org.jetbrains.kotlin.backend.konan.KonanCompilationException
import org.jetbrains.kotlin.backend.konan.KonanFqNames
import org.jetbrains.kotlin.backend.konan.RuntimeNames
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.allParameters import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
import org.jetbrains.kotlin.backend.konan.ir.containsNull import org.jetbrains.kotlin.backend.konan.ir.containsNull
import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
@@ -36,8 +34,6 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -65,13 +61,7 @@ internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrC
private var topLevelInitializersCounter = 0 private var topLevelInitializersCounter = 0
internal fun IrFile.addTopLevelInitializer(expression: IrExpression, context: KonanBackendContext, threadLocal: Boolean) { internal fun IrFile.addTopLevelInitializer(expression: IrExpression, context: KonanBackendContext, threadLocal: Boolean) {
val descriptor = WrappedFieldDescriptor( val descriptor = WrappedFieldDescriptor()
if (threadLocal)
Annotations.create(listOf(AnnotationDescriptorImpl(context.ir.symbols.threadLocal.defaultType,
emptyMap(), SourceElement.NO_SOURCE)))
else
Annotations.EMPTY
)
val irField = IrFieldImpl( val irField = IrFieldImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
@@ -85,7 +75,10 @@ internal fun IrFile.addTopLevelInitializer(expression: IrExpression, context: Ko
).apply { ).apply {
descriptor.bind(this) descriptor.bind(this)
initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, expression) if (threadLocal)
annotations += buildSimpleAnnotation(context.irBuiltIns, startOffset, endOffset, context.ir.symbols.threadLocal.owner)
initializer = IrExpressionBodyImpl(startOffset, endOffset, expression)
} }
addChild(irField) addChild(irField)
} }