Skip to content

Commit 3679a6b

Browse files
committed
[ObjC] Check entire chain of superclasses to see if class has fixed offsets
As of now, we only check if a class directly inherits from NSObject to determine if said lass has fixed offsets and can therefore "opt-out" from the non-fragile ABI for ivars. However, if an NSObject subclass has fixed offsets, then so must the subclasses of that subclass, so this allows us to optimize instances of subclasses of subclasses that inherit from NSObject and so on. To determine this, we need to find that the compiler can see the implementation of each intermediate class, as that means it is statically linked. Perhaps there is another way to figure this out at link time as well, but that is for another time and another PR. Fixes: #81369
1 parent 4bdf6f7 commit 3679a6b

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

clang/lib/CodeGen/CGObjCMac.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,12 +1593,22 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
15931593
}
15941594

15951595
bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
1596-
// NSObject is a fixed size. If we can see the @implementation of a class
1597-
// which inherits from NSObject then we know that all it's offsets also must
1598-
// be fixed. FIXME: Can we do this if see a chain of super classes with
1599-
// implementations leading to NSObject?
1600-
return ID->getImplementation() && ID->getSuperClass() &&
1601-
ID->getSuperClass()->getName() == "NSObject";
1596+
// Test a class by checking its superclasses up to its base class if it has
1597+
// one
1598+
while (ID) {
1599+
// The base class NSObject is a fixed size
1600+
if (ID->getName() == "NSObject")
1601+
return true;
1602+
1603+
// If we cannot see the @implementation of a class, we cannot assume fixed
1604+
// offsets
1605+
if (!ID->getImplementation())
1606+
return false;
1607+
1608+
// Test superclass
1609+
ID = ID->getSuperClass();
1610+
}
1611+
return false;
16021612
}
16031613

16041614
public:

clang/test/CodeGenObjC/constant-non-fragile-ivar-offset.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// CHECK: @"OBJC_IVAR_$_AnotherClass.privateId" = constant i64 24
88
// CHECK: @"OBJC_IVAR_$_AnotherClass.anotherPrivateId" = hidden constant i64 32
99
// CHECK: @"OBJC_IVAR_$_SuperClass.superClassIvar" = constant i64 20
10-
// CHECK: @"OBJC_IVAR_$_SubClass.subClassIvar" = global i64 24
10+
// CHECK: @"OBJC_IVAR_$_SubClass.subClassIvar" = constant i64 24
1111
// CHECK: @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar" = hidden global i64 12
1212

1313
@interface NSObject {
@@ -83,7 +83,7 @@ @interface SubClass : SuperClass
8383

8484
@implementation SubClass
8585
- (void)exampleMethod {
86-
// CHECK: load i64, ptr @"OBJC_IVAR_$SuperClass
86+
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$SuperClass
8787
superClassIvar = 100; // Access superclass ivar
8888
subClassIvar = 3.14; // Access subclass ivar
8989
}

0 commit comments

Comments
 (0)