diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt index 9d97968d98d..309bdb56628 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt @@ -15,3 +15,20 @@ internal fun IrClass.isNonGeneratedAnnotation(): Boolean = !this.annotations.hasAnnotation(serialInfoAnnotationFqName) private val serialInfoAnnotationFqName = FqName("kotlinx.serialization.SerialInfo") + +/** + * We don't need to generate RTTI in some cases, e.g. Objective-C external classes. + */ +internal fun IrClass.requiresRtti(): Boolean = when { + // TODO: Support more cases + // Sadly, we still need to emit RTTI for Kotlin inheritors of Obj-C classes. + // The reason for it is that we need to know a layout of the object to correctly + // deinitialize it. + this.isExternalObjCClass() -> false + else -> true +} + +internal fun IrClass.requiresCodeGeneration(): Boolean = + // For now these two sets (classes that require RTTI and classes that require codegen) + // are the same, but they might diverge later. + requiresRtti() \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index a010be125a7..101a98b17f2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -97,9 +97,9 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid { override fun visitClass(declaration: IrClass) { super.visitClass(declaration) - - generator.generate(declaration) - + if (declaration.requiresRtti()) { + generator.generate(declaration) + } if (declaration.isKotlinObjCClass()) { kotlinObjCClassInfoGenerator.generate(declaration) } @@ -772,7 +772,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index 14f19576a53..fe1b4b7c67c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -157,8 +157,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : } override fun visitClass(declaration: IrClass) { - this.classes[declaration] = createClassDeclarations(declaration) - + if (declaration.requiresRtti()) { + this.classes[declaration] = createClassDeclarations(declaration) + } super.visitClass(declaration) } @@ -308,6 +309,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : val containingClass = declaration.parent as? IrClass if (containingClass != null) { + if (!containingClass.requiresRtti()) return val classDeclarations = this.classes[containingClass] ?: error(containingClass.descriptor.toString()) val allFields = context.getLayoutBuilder(containingClass).fields diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index c6739010468..c966152f508 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -185,6 +185,20 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { return LLVMStoreSizeOfType(llvmTargetData, classType).toInt() } + private fun getClassId(irClass: IrClass): Int { + if (irClass.isKotlinObjCClass()) return 0 + val hierarchyInfo = if (context.ghaEnabled()) { + context.getLayoutBuilder(irClass).hierarchyInfo + } else { + ClassGlobalHierarchyInfo.DUMMY + } + return if (irClass.isInterface) { + hierarchyInfo.interfaceId + } else { + hierarchyInfo.classIdLo + } + } + fun generate(irClass: IrClass) { val className = irClass.fqNameForIrSerialization @@ -195,11 +209,16 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val instanceSize = getInstanceSize(bodyType, className) - val superTypeOrAny = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner - val superType = if (irClass.isAny()) NullPointer(runtime.typeInfoType) - else superTypeOrAny.typeInfoPtr + val superType = when { + irClass.isAny() -> NullPointer(runtime.typeInfoType) + irClass.isKotlinObjCClass() -> context.ir.symbols.any.owner.typeInfoPtr + else -> { + val superTypeOrAny = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner + superTypeOrAny.typeInfoPtr + } + } - val implementedInterfaces = irClass.implementedInterfaces + val implementedInterfaces = irClass.implementedInterfaces.filter { it.requiresRtti() } val interfaces = implementedInterfaces.map { it.typeInfoPtr } val interfacesPtr = staticData.placeGlobalConstArray("kintf:$className", @@ -235,10 +254,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val reflectionInfo = getReflectionInfo(irClass) val typeInfoGlobal = llvmDeclarations.typeInfoGlobal - val hierarchyInfo = - if (context.ghaEnabled()) - context.getLayoutBuilder(irClass).hierarchyInfo - else ClassGlobalHierarchyInfo.DUMMY val typeInfo = TypeInfo( irClass.typeInfoPtr, makeExtendedInfo(irClass), @@ -251,9 +266,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { reflectionInfo.packageName, reflectionInfo.relativeName, flagsFromClass(irClass), - if (irClass.isInterface) - hierarchyInfo.interfaceId - else hierarchyInfo.classIdLo, + getClassId(irClass), llvmDeclarations.writableTypeInfoGlobal?.pointer, associatedObjects = genAssociatedObjects(irClass) )