[K/N] Modularise :kotlin-native:native.backend to extract objc header generation (1/2)

^KT-63905
This commit is contained in:
Sebastian Sellmair
2023-11-29 11:27:55 +01:00
committed by Space Team
parent 4294c7bab7
commit ae9f3d66c2
69 changed files with 0 additions and 0 deletions
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
sealed class BinaryType<out T> {
class Primitive(val type: PrimitiveBinaryType) : BinaryType<Nothing>()
class Reference<T>(val types: Sequence<T>, val nullable: Boolean) : BinaryType<T>()
}
fun BinaryType<*>.primitiveBinaryTypeOrNull(): PrimitiveBinaryType? = when (this) {
is BinaryType.Primitive -> this.type
is BinaryType.Reference -> null
}
enum class PrimitiveBinaryType {
BOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, POINTER, VECTOR128
}
@@ -0,0 +1,316 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.utils.atMostOne
import org.jetbrains.kotlin.descriptors.findPackage
import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.inlineClassRepresentation
import org.jetbrains.kotlin.ir.declarations.isSingleFieldValueClass
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
fun IrType.getInlinedClassNative(): IrClass? = IrTypeInlineClassesSupport.getInlinedClass(this)
fun IrType.isInlinedNative(): Boolean = IrTypeInlineClassesSupport.isInlined(this)
fun IrClass.isInlined(): Boolean = IrTypeInlineClassesSupport.isInlined(this)
fun IrClass.isNativePrimitiveType() = IrTypeInlineClassesSupport.isTopLevelClass(this) &&
KonanPrimitiveType.byFqNameParts[packageFqName]?.get(name) != null
fun KotlinType.getInlinedClass(): ClassDescriptor? = KotlinTypeInlineClassesSupport.getInlinedClass(this)
fun ClassDescriptor.isInlined(): Boolean = KotlinTypeInlineClassesSupport.isInlined(this)
fun KotlinType.binaryRepresentationIsNullable() = KotlinTypeInlineClassesSupport.representationIsNullable(this)
internal inline fun <R> KotlinType.unwrapToPrimitiveOrReference(
eachInlinedClass: (inlinedClass: ClassDescriptor, nullable: Boolean) -> Unit,
ifPrimitive: (primitiveType: KonanPrimitiveType, nullable: Boolean) -> R,
ifReference: (type: KotlinType) -> R
): R = KotlinTypeInlineClassesSupport.unwrapToPrimitiveOrReference(this, eachInlinedClass, ifPrimitive, ifReference)
internal inline fun <R> IrType.unwrapToPrimitiveOrReference(
eachInlinedClass: (inlinedClass: IrClass, nullable: Boolean) -> Unit,
ifPrimitive: (primitiveType: KonanPrimitiveType, nullable: Boolean) -> R,
ifReference: (type: IrType) -> R
): R = IrTypeInlineClassesSupport.unwrapToPrimitiveOrReference(this, eachInlinedClass, ifPrimitive, ifReference)
// TODO: consider renaming to `isReference`.
fun KotlinType.binaryTypeIsReference(): Boolean = this.computePrimitiveBinaryTypeOrNull() == null
fun IrType.binaryTypeIsReference(): Boolean = this.computePrimitiveBinaryTypeOrNull() == null
fun KotlinType.computePrimitiveBinaryTypeOrNull(): PrimitiveBinaryType? =
this.computeBinaryType().primitiveBinaryTypeOrNull()
fun KotlinType.computeBinaryType(): BinaryType<ClassDescriptor> = KotlinTypeInlineClassesSupport.computeBinaryType(this)
fun IrType.computePrimitiveBinaryTypeOrNull(): PrimitiveBinaryType? =
this.computeBinaryType().primitiveBinaryTypeOrNull()
fun IrType.computeBinaryType(): BinaryType<IrClass> = IrTypeInlineClassesSupport.computeBinaryType(this)
fun IrClass.inlinedClassIsNullable(): Boolean = this.defaultType.makeNullable().getInlinedClassNative() == this // TODO: optimize
fun IrClass.isUsedAsBoxClass(): Boolean = IrTypeInlineClassesSupport.isUsedAsBoxClass(this)
/**
* Most "underlying" user-visible non-reference type.
* It is visible as inlined to compiler for simplicity.
*/
enum class KonanPrimitiveType(val classId: ClassId, val binaryType: BinaryType.Primitive) {
BOOLEAN(PrimitiveType.BOOLEAN, PrimitiveBinaryType.BOOLEAN),
CHAR(PrimitiveType.CHAR, PrimitiveBinaryType.SHORT),
BYTE(PrimitiveType.BYTE, PrimitiveBinaryType.BYTE),
SHORT(PrimitiveType.SHORT, PrimitiveBinaryType.SHORT),
INT(PrimitiveType.INT, PrimitiveBinaryType.INT),
LONG(PrimitiveType.LONG, PrimitiveBinaryType.LONG),
FLOAT(PrimitiveType.FLOAT, PrimitiveBinaryType.FLOAT),
DOUBLE(PrimitiveType.DOUBLE, PrimitiveBinaryType.DOUBLE),
NON_NULL_NATIVE_PTR(ClassId.topLevel(KonanFqNames.nonNullNativePtr.toSafe()), PrimitiveBinaryType.POINTER),
VECTOR128(ClassId.topLevel(KonanFqNames.Vector128), PrimitiveBinaryType.VECTOR128)
;
constructor(primitiveType: PrimitiveType, primitiveBinaryType: PrimitiveBinaryType)
: this(ClassId.topLevel(primitiveType.typeFqName), primitiveBinaryType)
constructor(classId: ClassId, primitiveBinaryType: PrimitiveBinaryType)
: this(classId, BinaryType.Primitive(primitiveBinaryType))
val fqName: FqNameUnsafe get() = this.classId.asSingleFqName().toUnsafe()
companion object {
val byFqNameParts = KonanPrimitiveType.values().groupingBy {
assert(!it.classId.isNestedClass)
it.classId.packageFqName
}.fold({ _, _ -> mutableMapOf<Name, KonanPrimitiveType>() },
{ _, accumulator, element ->
accumulator.also { it[element.classId.shortClassName] = element }
})
}
}
internal abstract class InlineClassesSupport<Class : Any, Type : Any> {
protected abstract fun isNullable(type: Type): Boolean
protected abstract fun makeNullable(type: Type): Type
protected abstract fun erase(type: Type): Class
protected abstract fun computeFullErasure(type: Type): Sequence<Class>
protected abstract fun hasInlineModifier(clazz: Class): Boolean
protected abstract fun getNativePointedSuperclass(clazz: Class): Class?
protected abstract fun getInlinedClassUnderlyingType(clazz: Class): Type
protected abstract fun getPackageFqName(clazz: Class): FqName?
protected abstract fun getName(clazz: Class): Name?
abstract fun isTopLevelClass(clazz: Class): Boolean
@JvmName("classIsInlined")
fun isInlined(clazz: Class): Boolean = getInlinedClass(clazz) != null
fun isInlined(type: Type): Boolean = getInlinedClass(type) != null
fun isUsedAsBoxClass(clazz: Class) = getInlinedClass(clazz) == clazz // To handle NativePointed subclasses.
fun getInlinedClass(type: Type): Class? =
getInlinedClass(erase(type), isNullable(type))
protected fun getKonanPrimitiveType(clazz: Class): KonanPrimitiveType? =
if (isTopLevelClass(clazz))
KonanPrimitiveType.byFqNameParts[getPackageFqName(clazz)]?.get(getName(clazz))
else null
protected fun isImplicitInlineClass(clazz: Class): Boolean =
isTopLevelClass(clazz) && (getKonanPrimitiveType(clazz) != null ||
getName(clazz) == KonanFqNames.nativePtr.shortName() && getPackageFqName(clazz) == KonanFqNames.internalPackageName ||
getName(clazz) == InteropFqNames.cPointer.shortName() && getPackageFqName(clazz) == InteropFqNames.cPointer.parent().toSafe())
private fun getInlinedClass(erased: Class, isNullable: Boolean): Class? {
val inlinedClass = getInlinedClass(erased) ?: return null
return if (!isNullable || representationIsNonNullReferenceOrPointer(inlinedClass)) {
inlinedClass
} else {
null
}
}
tailrec fun representationIsNonNullReferenceOrPointer(clazz: Class): Boolean {
val konanPrimitiveType = getKonanPrimitiveType(clazz)
if (konanPrimitiveType != null) {
return konanPrimitiveType == KonanPrimitiveType.NON_NULL_NATIVE_PTR
}
val inlinedClass = getInlinedClass(clazz) ?: return true
val underlyingType = getInlinedClassUnderlyingType(inlinedClass)
return if (isNullable(underlyingType)) {
false
} else {
representationIsNonNullReferenceOrPointer(erase(underlyingType))
}
}
@JvmName("classGetInlinedClass")
private fun getInlinedClass(clazz: Class): Class? =
if (hasInlineModifier(clazz) || isImplicitInlineClass(clazz)) {
clazz
} else {
getNativePointedSuperclass(clazz)
}
inline fun <R> unwrapToPrimitiveOrReference(
type: Type,
eachInlinedClass: (inlinedClass: Class, nullable: Boolean) -> Unit,
ifPrimitive: (primitiveType: KonanPrimitiveType, nullable: Boolean) -> R,
ifReference: (type: Type) -> R
): R {
var currentType: Type = type
while (true) {
val inlinedClass = getInlinedClass(currentType)
if (inlinedClass == null) {
return ifReference(currentType)
}
val nullable = isNullable(currentType)
getKonanPrimitiveType(inlinedClass)?.let { primitiveType ->
return ifPrimitive(primitiveType, nullable)
}
eachInlinedClass(inlinedClass, nullable)
val underlyingType = getInlinedClassUnderlyingType(inlinedClass)
currentType = if (nullable) makeNullable(underlyingType) else underlyingType
}
}
fun representationIsNullable(type: Type): Boolean {
unwrapToPrimitiveOrReference(
type,
eachInlinedClass = { _, nullable -> if (nullable) return true },
ifPrimitive = { _, nullable -> return nullable },
ifReference = { return isNullable(it) }
)
}
// TODO: optimize.
fun computeBinaryType(type: Type): BinaryType<Class> {
val erased = erase(type)
val inlinedClass = getInlinedClass(erased, isNullable(type)) ?: return createReferenceBinaryType(type)
getKonanPrimitiveType(inlinedClass)?.let {
return it.binaryType
}
val underlyingBinaryType = computeBinaryType(getInlinedClassUnderlyingType(inlinedClass))
return if (isNullable(type) && underlyingBinaryType is BinaryType.Reference) {
BinaryType.Reference(underlyingBinaryType.types, true)
} else {
underlyingBinaryType
}
}
private fun createReferenceBinaryType(type: Type): BinaryType.Reference<Class> =
BinaryType.Reference(computeFullErasure(type), true)
}
internal object KotlinTypeInlineClassesSupport : InlineClassesSupport<ClassDescriptor, KotlinType>() {
override fun isNullable(type: KotlinType): Boolean = type.isNullable()
override fun makeNullable(type: KotlinType): KotlinType = type.makeNullable()
override tailrec fun erase(type: KotlinType): ClassDescriptor {
val descriptor = type.constructor.declarationDescriptor
return if (descriptor is ClassDescriptor) {
descriptor
} else {
erase(type.constructor.supertypes.first())
}
}
override fun computeFullErasure(type: KotlinType): Sequence<ClassDescriptor> {
val classifier = type.constructor.declarationDescriptor
return if (classifier is ClassDescriptor) sequenceOf(classifier)
else type.constructor.supertypes.asSequence().flatMap { computeFullErasure(it) }
}
override fun hasInlineModifier(clazz: ClassDescriptor): Boolean = clazz.isInlineClass()
override fun getNativePointedSuperclass(clazz: ClassDescriptor): ClassDescriptor? = clazz.getAllSuperClassifiers()
.firstOrNull { it.fqNameUnsafe == InteropFqNames.nativePointed } as ClassDescriptor?
override fun getInlinedClassUnderlyingType(clazz: ClassDescriptor): KotlinType =
clazz.unsubstitutedPrimaryConstructor!!.valueParameters.single().type
override fun getPackageFqName(clazz: ClassDescriptor) =
clazz.findPackage().fqName
override fun getName(clazz: ClassDescriptor) =
clazz.name
override fun isTopLevelClass(clazz: ClassDescriptor): Boolean = clazz.containingDeclaration is PackageFragmentDescriptor
}
internal object IrTypeInlineClassesSupport : InlineClassesSupport<IrClass, IrType>() {
override fun isNullable(type: IrType): Boolean = type.isNullable()
override fun makeNullable(type: IrType): IrType = type.makeNullable()
override tailrec fun erase(type: IrType): IrClass {
val classifier = type.classifierOrFail
return when (classifier) {
is IrClassSymbol -> classifier.owner
is IrTypeParameterSymbol -> erase(classifier.owner.superTypes.first())
else -> error(classifier)
}
}
override fun computeFullErasure(type: IrType): Sequence<IrClass> = when (val classifier = type.classifierOrFail) {
is IrClassSymbol -> sequenceOf(classifier.owner)
is IrTypeParameterSymbol -> classifier.owner.superTypes.asSequence().flatMap { computeFullErasure(it) }
is IrScriptSymbol -> classifier.unexpectedSymbolKind<IrClassifierSymbol>()
}
override fun hasInlineModifier(clazz: IrClass): Boolean = clazz.isSingleFieldValueClass
override fun getNativePointedSuperclass(clazz: IrClass): IrClass? {
var superClass: IrClass? = clazz
while (superClass != null && InteropFqNames.nativePointed.toSafe() != superClass.fqNameWhenAvailable)
superClass = superClass.getSuperClassNotAny()
return superClass
}
override fun getInlinedClassUnderlyingType(clazz: IrClass): IrType =
clazz.constructors.firstOrNull { it.isPrimary }?.valueParameters?.single()?.type
?: clazz.declarations.filterIsInstance<IrProperty>().atMostOne { it.backingField?.takeUnless { it.isStatic } != null }?.backingField?.type
?: clazz.inlineClassRepresentation!!.underlyingType
override fun getPackageFqName(clazz: IrClass) =
clazz.packageFqName
override fun getName(clazz: IrClass): Name? =
clazz.name
override fun isTopLevelClass(clazz: IrClass): Boolean = clazz.isTopLevel
}
@@ -0,0 +1,155 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
object InteropFqNames {
const val cPointerName = "CPointer"
const val nativePointedName = "NativePointed"
const val objCObjectBaseName = "ObjCObjectBase"
const val objCOverrideInitName = "OverrideInit"
const val objCActionName = "ObjCAction"
const val objCOutletName = "ObjCOutlet"
const val objCMethodImpName = "ObjCMethodImp"
const val exportObjCClassName = "ExportObjCClass"
const val nativeHeapName = "nativeHeap"
const val cValueName = "CValue"
const val cValuesName = "CValues"
const val cValuesRefName = "CValuesRef"
const val cEnumName = "CEnum"
const val cStructVarName = "CStructVar"
const val cEnumVarName = "CEnumVar"
const val cPrimitiveVarName = "CPrimitiveVar"
const val cPointedName = "CPointed"
const val interopStubsName = "InteropStubs"
const val managedTypeName = "ManagedType"
const val memScopeName = "MemScope"
const val foreignObjCObjectName = "ForeignObjCObject"
const val cOpaqueName = "COpaque"
const val objCObjectName = "ObjCObject"
const val objCObjectBaseMetaName = "ObjCObjectBaseMeta"
const val objCClassName = "ObjCClass"
const val objCClassOfName = "ObjCClassOf"
const val objCProtocolName = "ObjCProtocol"
const val nativeMemUtilsName = "nativeMemUtils"
const val cPlusPlusClassName = "CPlusPlusClass"
const val skiaRefCntName = "SkiaRefCnt"
const val TypeName = "Type"
const val cstrPropertyName = "cstr"
const val wcstrPropertyName = "wcstr"
const val nativePointedRawPtrPropertyName = "rawPtr"
const val cPointerRawValuePropertyName = "rawValue"
const val getObjCClassFunName = "getObjCClass"
const val objCObjectSuperInitCheckFunName = "superInitCheck"
const val allocObjCObjectFunName = "allocObjCObject"
const val typeOfFunName = "typeOf"
const val objCObjectInitByFunName = "initBy"
const val objCObjectRawPtrFunName = "objcPtr"
const val interpretObjCPointerFunName = "interpretObjCPointer"
const val interpretObjCPointerOrNullFunName = "interpretObjCPointerOrNull"
const val interpretNullablePointedFunName = "interpretNullablePointed"
const val interpretCPointerFunName = "interpretCPointer"
const val nativePointedGetRawPointerFunName = "getRawPointer"
const val cPointerGetRawValueFunName = "getRawValue"
const val cValueWriteFunName = "write"
const val cValueReadFunName = "readValue"
const val allocTypeFunName = "alloc"
val packageName = FqName("kotlinx.cinterop")
val cPointer = packageName.child(cPointerName).toUnsafe()
val nativePointed = packageName.child(nativePointedName).toUnsafe()
val objCObjectBase = packageName.child(objCObjectBaseName)
val objCOverrideInit = objCObjectBase.child(objCOverrideInitName)
val objCAction = packageName.child(objCActionName)
val objCOutlet = packageName.child(objCOutletName)
val objCMethodImp = packageName.child(objCMethodImpName)
val exportObjCClass = packageName.child(exportObjCClassName)
val cValue = packageName.child(cValueName)
val cValues = packageName.child(cValuesName)
val cValuesRef = packageName.child(cValuesRefName)
val cEnum = packageName.child(cEnumName)
val cStructVar = packageName.child(cStructVarName)
val cPointed = packageName.child(cPointedName)
val interopStubs = packageName.child(interopStubsName)
val managedType = packageName.child(managedTypeName)
}
private fun FqName.child(nameIdent: String) = child(Name.identifier(nameIdent))
internal class InteropBuiltIns(builtIns: KonanBuiltIns) {
private val packageScope = builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope
internal fun getContributedVariables(name: String) = packageScope.getContributedVariables(name)
internal fun getContributedFunctions(name: String) = packageScope.getContributedFunctions(name)
internal fun getContributedClass(name: String) = packageScope.getContributedClass(name)
}
private fun MemberScope.getContributedVariables(name: String) =
this.getContributedVariables(Name.identifier(name), NoLookupLocation.FROM_BUILTINS)
internal fun MemberScope.getContributedClass(name: String): ClassDescriptor =
this.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) as ClassDescriptor
private fun MemberScope.getContributedFunctions(name: String) =
this.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS)
internal val cKeywords = setOf(
// Actual C keywords.
"auto", "break", "case",
"char", "const", "continue",
"default", "do", "double",
"else", "enum", "extern",
"float", "for", "goto",
"if", "int", "long",
"register", "return",
"short", "signed", "sizeof", "static", "struct", "switch",
"typedef", "union", "unsigned",
"void", "volatile", "while",
// C99-specific.
"_Bool", "_Complex", "_Imaginary", "inline", "restrict",
// C11-specific.
"_Alignas", "_Alignof", "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local",
// Not exactly keywords, but reserved or standard-defined.
"and", "not", "or", "xor",
"bool", "complex", "imaginary",
// C++ keywords not listed above.
"alignas", "alignof", "and_eq", "asm",
"bitand", "bitor", "bool",
"catch", "char16_t", "char32_t", "class", "compl", "constexpr", "const_cast",
"decltype", "delete", "dynamic_cast",
"explicit", "export",
"false", "friend",
"inline",
"mutable",
"namespace", "new", "noexcept", "not_eq", "nullptr",
"operator", "or_eq",
"private", "protected", "public",
"reinterpret_cast",
"static_assert",
"template", "this", "thread_local", "throw", "true", "try", "typeid", "typename",
"using",
"virtual",
"wchar_t",
"xor_eq"
)
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NativeRuntimeNames
internal const val NATIVE_PTR_NAME = "NativePtr"
internal const val NON_NULL_NATIVE_PTR_NAME = "NonNullNativePtr"
internal const val IMMUTABLE_BLOB_OF = "immutableBlobOf"
object KonanFqNames {
val function = FqName("kotlin.Function")
val kFunction = FqName("kotlin.reflect.KFunction")
val packageName = FqName("kotlin.native")
val internalPackageName = FqName("kotlin.native.internal")
val nativePtr = internalPackageName.child(Name.identifier(NATIVE_PTR_NAME)).toUnsafe()
val nonNullNativePtr = internalPackageName.child(Name.identifier(NON_NULL_NATIVE_PTR_NAME)).toUnsafe()
val Vector128 = FqName("kotlinx.cinterop.Vector128")
val throws = FqName("kotlin.Throws")
val cancellationException = FqName("kotlin.coroutines.cancellation.CancellationException")
val threadLocal = FqName("kotlin.native.concurrent.ThreadLocal")
val sharedImmutable = FqName("kotlin.native.concurrent.SharedImmutable")
val volatile = FqName("kotlin.concurrent.Volatile")
val frozen = FqName("kotlin.native.internal.Frozen")
val frozenLegacyMM = FqName("kotlin.native.internal.FrozenLegacyMM")
val leakDetectorCandidate = FqName("kotlin.native.internal.LeakDetectorCandidate")
val canBePrecreated = FqName("kotlin.native.internal.CanBePrecreated")
val typedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic")
val constantConstructorIntrinsic = FqName("kotlin.native.internal.ConstantConstructorIntrinsic")
val objCMethod = FqName("kotlinx.cinterop.ObjCMethod")
val hasFinalizer = FqName("kotlin.native.internal.HasFinalizer")
val hasFreezeHook = FqName("kotlin.native.internal.HasFreezeHook")
val gcUnsafeCall = NativeRuntimeNames.Annotations.gcUnsafeCallClassId.asSingleFqName()
val eagerInitialization = FqName("kotlin.native.EagerInitialization")
val noReorderFields = FqName("kotlin.native.internal.NoReorderFields")
val objCName = FqName("kotlin.native.ObjCName")
val hidesFromObjC = FqName("kotlin.native.HidesFromObjC")
val refinesInSwift = FqName("kotlin.native.RefinesInSwift")
val shouldRefineInSwift = FqName("kotlin.native.ShouldRefineInSwift")
val reflectionPackageName = FqName("kotlin.native.internal.ReflectionPackageName")
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.konan
enum class ObjCExportSuspendFunctionLaunchThreadRestriction {
/**
* In this mode, suspend functions called from ObjC/Swift may only be called from the main thread
*/
MAIN,
/**
* In this mode, suspend functions called from ObjC/Swift may be called from any thread
*/
NONE,
;
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.konan
enum class UnitSuspendFunctionObjCExport {
/**
* In this mode suspend functions and methods with [Unit] return type are exported to Objective-C with an additional argument,
* continuation callback, with the following Objective-C signature: `(^)(KtKotlinUnit * _Nullable, NSError * _Nullable)`.
*/
LEGACY,
/**
* In this mode suspend functions and methods with [Unit] return type are exported to Objective-C with an additional argument,
* continuation callback, with the following Objective-C signature: `(^)(NSError * _Nullable)`.
*
* Methods overriding superclass methods or implementing interface requirements narrowing down a more general return type
* to [Unit] are exported like in [LEGACY] mode.
*
* Note that in Swift 5.5 and higher suspend functions exported this way are transparently mapped to
* async functions with `Void` return type
*/
PROPER,
;
companion object {
val DEFAULT = PROPER
}
}
@@ -0,0 +1,124 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.OverridingUtil
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.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
/**
* Implementation of given method.
*
* TODO: this method is actually a part of resolve and probably duplicates another one
*/
internal fun <T : CallableMemberDescriptor> T.resolveFakeOverride(allowAbstract: Boolean = false): T {
if (this.kind.isReal) {
return this
} else {
val overridden = OverridingUtil.getOverriddenDeclarations(this)
val filtered = OverridingUtil.filterOutOverridden(overridden)
// TODO: is it correct to take first?
@Suppress("UNCHECKED_CAST")
return filtered.first { allowAbstract || it.modality != Modality.ABSTRACT } as T
}
}
internal val ClassDescriptor.isArray: Boolean
get() = this.fqNameSafe.asString() in arrayTypes
internal val ClassDescriptor.isInterface: Boolean
get() = (this.kind == ClassKind.INTERFACE)
internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit()
internal fun ClassDescriptor.isNothing() = this.defaultType.isNothing()
internal val <T : CallableMemberDescriptor> T.allOverriddenDescriptors: List<T>
get() {
val result = mutableListOf<T>()
fun traverse(descriptor: T) {
result.add(descriptor)
@Suppress("UNCHECKED_CAST")
descriptor.overriddenDescriptors.forEach { traverse(it as T) }
}
traverse(this)
return result
}
internal val ClassDescriptor.contributedMethods: List<FunctionDescriptor>
get () = unsubstitutedMemberScope.contributedMethods
internal val MemberScope.contributedMethods: List<FunctionDescriptor>
get () {
val contributedDescriptors = this.getContributedDescriptors()
val functions = contributedDescriptors.filterIsInstance<FunctionDescriptor>()
val properties = contributedDescriptors.filterIsInstance<PropertyDescriptor>()
val getters = properties.mapNotNull { it.getter }
val setters = properties.mapNotNull { it.setter }
return functions + getters + setters
}
fun ClassDescriptor.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT
internal val FunctionDescriptor.target: FunctionDescriptor
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
internal fun DeclarationDescriptor.findPackageView(): PackageViewDescriptor {
val packageFragment = this.findPackage()
return packageFragment.module.getPackage(packageFragment.fqName)
}
internal fun DeclarationDescriptor.allContainingDeclarations(): List<DeclarationDescriptor> {
var list = mutableListOf<DeclarationDescriptor>()
var current = this.containingDeclaration
while (current != null) {
list.add(current)
current = current.containingDeclaration
}
return list
}
private fun getPackagesFqNames(module: ModuleDescriptor): Set<FqName> {
val result = mutableSetOf<FqName>()
val packageFragmentProvider = (module as? ModuleDescriptorImpl)?.packageFragmentProviderForModuleContentWithoutDependencies
fun getSubPackages(fqName: FqName) {
result.add(fqName)
val subPackages = packageFragmentProvider?.getSubPackagesOf(fqName) { true }
?: module.getSubPackagesOf(fqName) { true }
subPackages.forEach { getSubPackages(it) }
}
getSubPackages(FqName.ROOT)
return result
}
fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescriptor> =
getPackagesFqNames(this).flatMap {
getPackage(it).fragments.filter { it.module == this }.toSet()
}
val ClassDescriptor.enumEntries: List<ClassDescriptor>
get() {
assert(this.kind == ClassKind.ENUM_CLASS)
return this.unsubstitutedMemberScope.getContributedDescriptors()
.filterIsInstance<ClassDescriptor>()
.filter { it.kind == ClassKind.ENUM_ENTRY }
}
internal val DeclarationDescriptor.isExpectMember: Boolean
get() = this is MemberDescriptor && this.isExpect