[K/N] Modularise :kotlin-native:native.backend to extract objc header generation (1/2)
^KT-63905
This commit is contained in:
committed by
Space Team
parent
4294c7bab7
commit
ae9f3d66c2
@@ -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")
|
||||
}
|
||||
+19
@@ -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,
|
||||
;
|
||||
}
|
||||
+31
@@ -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
|
||||
}
|
||||
}
|
||||
+124
@@ -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
|
||||
Reference in New Issue
Block a user