[RTTI][Objective-C] Omit RTTI for external Obj-C classes

This commit is contained in:
Sergey Bogolepov
2020-02-04 13:13:39 +07:00
committed by Sergey Bogolepov
parent 7b73595aca
commit d250058943
4 changed files with 50 additions and 17 deletions
@@ -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()
@@ -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<IrE
override fun visitClass(declaration: IrClass) {
context.log{"visitClass : ${ir2string(declaration)}"}
if (declaration.isNonGeneratedAnnotation()) {
if (declaration.isNonGeneratedAnnotation() || !declaration.requiresCodeGeneration()) {
// For non-generated annotation classes generate only nested classes.
declaration.declarations
.filterIsInstance<IrClass>()
@@ -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
@@ -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)
)