Skip to content

Commit 6720465

Browse files
authored
[ObjC] Expand isClassLayoutKnownStatically to base classes as long as the implementation of it is known (#85465)
Only NSObject we can trust the layout of won't change even though we cannot directly see its @implementation
1 parent aeca2aa commit 6720465

16 files changed

+94
-54
lines changed

clang/lib/CodeGen/CGObjCMac.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,8 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
15451545
bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
15461546
// Test a class by checking its superclasses up to
15471547
// its base class if it has one.
1548-
for (; ID; ID = ID->getSuperClass()) {
1548+
assert(ID != nullptr && "Passed a null class to check layout");
1549+
for (; ID != nullptr; ID = ID->getSuperClass()) {
15491550
// The layout of base class NSObject
15501551
// is guaranteed to be statically known
15511552
if (ID->getIdentifier()->getName() == "NSObject")
@@ -1556,7 +1557,9 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
15561557
if (!ID->getImplementation())
15571558
return false;
15581559
}
1559-
return false;
1560+
1561+
// We know the layout of all the intermediate classes and superclasses.
1562+
return true;
15601563
}
15611564

15621565
public:

clang/test/CodeGenObjC/arc-blocks.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,16 +422,16 @@ @interface Test12
422422
@implementation Test12
423423
@synthesize ablock, nblock;
424424
// CHECK: define internal ptr @"\01-[Test12 ablock]"(
425-
// CHECK: call ptr @objc_getProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef {{%.*}}, i1 noundef zeroext true)
425+
// CHECK: call ptr @objc_getProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef 0, i1 noundef zeroext true)
426426

427427
// CHECK: define internal void @"\01-[Test12 setAblock:]"(
428-
// CHECK: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef {{%.*}}, ptr noundef {{%.*}}, i1 noundef zeroext true, i1 noundef zeroext true)
428+
// CHECK: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef 0, ptr noundef {{%.*}}, i1 noundef zeroext true, i1 noundef zeroext true)
429429

430430
// CHECK: define internal ptr @"\01-[Test12 nblock]"(
431-
// CHECK: %add.ptr = getelementptr inbounds i8, ptr %0, i64 %ivar
431+
// CHECK: %add.ptr = getelementptr inbounds i8, ptr %0, i64 8
432432

433433
// CHECK: define internal void @"\01-[Test12 setNblock:]"(
434-
// CHECK: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef {{%.*}}, ptr noundef {{%.*}}, i1 noundef zeroext false, i1 noundef zeroext true)
434+
// CHECK: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef 8, ptr noundef {{%.*}}, i1 noundef zeroext false, i1 noundef zeroext true)
435435
@end
436436

437437
void test13(id x) {

clang/test/CodeGenObjC/arc-property.m

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,14 @@ @implementation Test1
2222
@end
2323
// The getter should be a simple load.
2424
// CHECK: define internal ptr @"\01-[Test1 pointer]"(
25-
// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test1.pointer"
26-
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr {{%.*}}, i64 [[OFFSET]]
25+
// CHECK: [[T1:%.*]] = getelementptr inbounds i8, ptr {{%.*}}, i64 0
2726
// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[T1]], align 8
2827
// CHECK-NEXT: ret ptr [[T3]]
2928

3029
// The setter should be using objc_setProperty.
3130
// CHECK: define internal void @"\01-[Test1 setPointer:]"(
32-
// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test1.pointer"
33-
// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr {{%.*}}
34-
// CHECK-NEXT: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef [[OFFSET]], ptr noundef [[T1]], i1 noundef zeroext false, i1 noundef zeroext false)
31+
// CHECK: [[T1:%.*]] = load ptr, ptr {{%.*}}
32+
// CHECK: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef 0, ptr noundef {{%.*}}, i1 noundef zeroext false, i1 noundef zeroext false)
3533
// CHECK-NEXT: ret void
3634

3735

@@ -52,26 +50,22 @@ - (void) test {
5250
// CHECK: define internal void @"\01-[Test2 test]"(
5351
// CHECK: [[T0:%.*]] = load ptr, ptr @theGlobalClass, align 8
5452
// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr
55-
// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
56-
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 [[OFFSET]]
53+
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 0
5754
// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T3]], ptr [[T0]]) [[NUW:#[0-9]+]]
5855
// CHECK-NEXT: ret void
5956

6057
// CHECK: define internal ptr @"\01-[Test2 theClass]"(
61-
// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
62-
// CHECK-NEXT: [[T0:%.*]] = tail call ptr @objc_getProperty(ptr noundef {{.*}}, ptr noundef {{.*}}, i64 noundef [[OFFSET]], i1 noundef zeroext true)
58+
// CHECK: [[T0:%.*]] = tail call ptr @objc_getProperty(ptr noundef {{.*}}, ptr noundef {{.*}}, i64 noundef 0, i1 noundef zeroext true)
6359
// CHECK-NEXT: ret ptr [[T0]]
6460

6561
// CHECK: define internal void @"\01-[Test2 setTheClass:]"(
66-
// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
67-
// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr {{%.*}}
68-
// CHECK-NEXT: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef [[OFFSET]], ptr noundef [[T1]], i1 noundef zeroext true, i1 noundef zeroext true)
62+
// CHECK: [[T1:%.*]] = load ptr, ptr {{%.*}}
63+
// CHECK: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef 0, ptr noundef {{%.*}}, i1 noundef zeroext true, i1 noundef zeroext true)
6964
// CHECK-NEXT: ret void
7065

7166
// CHECK: define internal void @"\01-[Test2 .cxx_destruct]"(
7267
// CHECK: [[T0:%.*]] = load ptr, ptr
73-
// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
74-
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[OFFSET]]
68+
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 0
7569
// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T2]], ptr null) [[NUW]]
7670
// CHECK-NEXT: ret void
7771

clang/test/CodeGenObjC/arc-weak-property.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s
22

3-
@interface WeakPropertyTest {
3+
@interface SuperClass
4+
@end
5+
6+
@interface WeakPropertyTest : SuperClass {
47
__weak id PROP;
58
}
69
@property () __weak id PROP;

clang/test/CodeGenObjC/arc.m

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,7 @@ @interface Test26 { id x[4]; } @end
577577
@implementation Test26 @end
578578
// CHECK: define internal void @"\01-[Test26 .cxx_destruct]"(
579579
// CHECK: [[SELF:%.*]] = load ptr, ptr
580-
// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test26.x"
581-
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 [[OFFSET]]
580+
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 0
582581
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x ptr], ptr [[T1]], i32 0, i32 0
583582
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 4
584583
// CHECK-NEXT: br label
@@ -616,8 +615,7 @@ @implementation Test28
616615
@end
617616
// CHECK: define internal void @"\01-[Test28 .cxx_destruct]"
618617
// CHECK: [[SELF:%.*]] = load ptr, ptr
619-
// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test28.prop"
620-
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 [[OFFSET]]
618+
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 0
621619
// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null)
622620
// CHECK-NEXT: ret void
623621

@@ -738,8 +736,7 @@ - (id) init {
738736

739737
// Assignment.
740738
// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[SELF]]
741-
// CHECK-NEXT: [[IVAR:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test30.helper"
742-
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 [[IVAR]]
739+
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 0
743740
// CHECK-NEXT#: [[T5:%.*]] = load ptr, ptr [[T3]]
744741
// CHECK-NEXT#: [[T6:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]])
745742
// CHECK-NEXT#: call void @llvm.objc.release(ptr [[T5]])
@@ -1137,23 +1134,20 @@ @implementation Test57
11371134
@end
11381135
// CHECK: define internal ptr @"\01-[Test57 strong]"(
11391136
// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}
1140-
// CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.strong"
1141-
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]]
1137+
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 0
11421138
// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]
11431139
// CHECK-NEXT: ret ptr [[T5]]
11441140

11451141
// CHECK: define internal ptr @"\01-[Test57 weak]"(
11461142
// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}
1147-
// CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.weak"
1148-
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]]
1143+
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 8
11491144
// CHECK-NEXT: [[T5:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T3]])
11501145
// CHECK-NEXT: [[T6:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T5]])
11511146
// CHECK-NEXT: ret ptr [[T6]]
11521147

11531148
// CHECK: define internal ptr @"\01-[Test57 unsafe]"(
11541149
// CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}
1155-
// CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.unsafe"
1156-
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]]
1150+
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 16
11571151
// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]
11581152
// CHECK-NEXT: ret ptr [[T5]]
11591153

clang/test/CodeGenObjC/arm64-int32-ivar.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
// CHECK: @"OBJC_IVAR_$_I.IVAR2" = global i32 8
44
// CHECK: @"OBJC_IVAR_$_I.IVAR1" = global i32 0
5-
@interface I
5+
@interface SuperClass
6+
@end
7+
8+
@interface I : SuperClass
69
{
710
id IVAR1;
811
id IVAR2;

clang/test/CodeGenObjC/bitfield-ivar-offsets.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
// RUN: grep -F '@"OBJC_IVAR_$_I0._b4" = global i64 7, section "__DATA, __objc_ivar", align 8' %t
99
// RUN: not grep -F '@"OBJC_IVAR_$_I0." = global' %t
1010

11-
@interface I0 {
11+
@interface SuperClass
12+
@end
13+
14+
@interface I0 : SuperClass {
1215
unsigned _b0:4;
1316
unsigned _b1:5;
1417
unsigned _b2:5;

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

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
// CHECK: @"OBJC_IVAR_$_IntermediateClass._intermediateProperty" = hidden constant i64 48
99
// CHECK: @"OBJC_IVAR_$_SubClass.subClassIvar" = constant i64 56
1010
// CHECK: @"OBJC_IVAR_$_SubClass._subClassProperty" = hidden constant i64 64
11+
12+
// CHECK: @"OBJC_IVAR_$_RootClass.these" = constant i64 0
13+
// CHECK: @"OBJC_IVAR_$_RootClass.never" = constant i64 4
14+
// CHECK: @"OBJC_IVAR_$_RootClass.change" = constant i64 8
15+
// CHECK: @"OBJC_IVAR_$_StillStaticLayout.static_layout_ivar" = hidden constant i64 12
16+
1117
// CHECK: @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar" = hidden global i64 12
1218
// CHECK: @"OBJC_IVAR_$_SuperClass2._superClassProperty2" = hidden constant i64 20
1319
// CHECK: @"OBJC_IVAR_$_IntermediateClass2._IntermediateClass2Property" = hidden constant i64 24
@@ -123,12 +129,34 @@ -(void)intermediateSubclassVar {
123129
// CHECK: getelementptr inbounds i8, ptr %1, i64 64
124130
@end
125131

126-
@interface NotNSObject {
127-
int these, might, change;
132+
__attribute((objc_root_class)) @interface RootClass {
133+
int these, never, change;
128134
}
129135
@end
130136

131-
@interface NotStaticLayout : NotNSObject
137+
@implementation RootClass
138+
@end
139+
140+
@interface StillStaticLayout : RootClass
141+
@end
142+
143+
@implementation StillStaticLayout {
144+
int static_layout_ivar;
145+
}
146+
147+
// CHECK-LABEL: define internal void @"\01-[StillStaticLayout meth]"
148+
-(void)meth {
149+
static_layout_ivar = 0;
150+
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$StillStaticLayout.static_layout_ivar
151+
}
152+
@end
153+
154+
@interface NotNSObject
155+
@end
156+
157+
@interface NotStaticLayout : NotNSObject {
158+
int these, might, change;
159+
}
132160
@end
133161

134162
@implementation NotStaticLayout {

clang/test/CodeGenObjC/direct-method.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,7 @@ - (void)accessCmd __attribute__((objc_direct)) {
167167
// CHECK-LABEL: define hidden ptr @"\01-[Root objectProperty]"(
168168
// CHECK-LABEL: objc_direct_method.cont:
169169
// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
170-
// CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
171-
// CHECK-NEXT: call ptr @objc_getProperty(ptr noundef [[SELFVAL]], ptr noundef poison, i64 noundef [[IVAR]], {{.*}})
170+
// CHECK-NEXT: call ptr @objc_getProperty(ptr noundef [[SELFVAL]], ptr noundef poison, i64 noundef 8, {{.*}})
172171

173172
@interface Foo : Root {
174173
id __strong _cause_cxx_destruct;

clang/test/CodeGenObjC/hidden-visibility.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %clang_cc1 -triple i386-apple-macosx -fvisibility=hidden -emit-llvm -o - %s | FileCheck %s
2-
// CHECK: @"OBJC_IVAR_$_I.P" = hidden
32
// CHECK: @"OBJC_CLASS_$_I" = hidden
43
// CHECK: @"OBJC_METACLASS_$_I" = hidden
4+
// CHECK: @"OBJC_IVAR_$_I.P" = hidden
55
// CHECK: @"_OBJC_PROTOCOL_$_Prot0" = weak hidden
66

77
@interface I {

0 commit comments

Comments
 (0)