llvm-project/clang/test/CodeGenObjC/constant-non-fragile-ivar-offset.m
AZero13 6720465c47
[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
2025-03-04 08:34:18 -08:00

216 lines
6.8 KiB
Objective-C

// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 -emit-llvm %s -o - | FileCheck %s
// CHECK: @"OBJC_IVAR_$_StaticLayout.static_layout_ivar" = hidden constant i64 20
// CHECK: @"OBJC_IVAR_$_SuperClass.superClassIvar" = hidden constant i64 20
// CHECK: @"OBJC_IVAR_$_SuperClass._superClassProperty" = hidden constant i64 24
// CHECK: @"OBJC_IVAR_$_IntermediateClass.intermediateClassIvar" = constant i64 32
// CHECK: @"OBJC_IVAR_$_IntermediateClass.intermediateClassIvar2" = constant i64 40
// CHECK: @"OBJC_IVAR_$_IntermediateClass._intermediateProperty" = hidden constant i64 48
// CHECK: @"OBJC_IVAR_$_SubClass.subClassIvar" = constant i64 56
// CHECK: @"OBJC_IVAR_$_SubClass._subClassProperty" = hidden constant i64 64
// CHECK: @"OBJC_IVAR_$_RootClass.these" = constant i64 0
// CHECK: @"OBJC_IVAR_$_RootClass.never" = constant i64 4
// CHECK: @"OBJC_IVAR_$_RootClass.change" = constant i64 8
// CHECK: @"OBJC_IVAR_$_StillStaticLayout.static_layout_ivar" = hidden constant i64 12
// CHECK: @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar" = hidden global i64 12
// CHECK: @"OBJC_IVAR_$_SuperClass2._superClassProperty2" = hidden constant i64 20
// CHECK: @"OBJC_IVAR_$_IntermediateClass2._IntermediateClass2Property" = hidden constant i64 24
// CHECK: @"OBJC_IVAR_$_SubClass2._subClass2Property" = hidden constant i64 28
@interface NSObject {
int these, will, never, change, ever;
}
@end
@interface StaticLayout : NSObject
@end
@implementation StaticLayout {
int static_layout_ivar;
}
// CHECK-LABEL: define internal void @"\01-[StaticLayout meth]"
-(void)meth {
static_layout_ivar = 0;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_StaticLayout
// CHECK: getelementptr inbounds i8, ptr %0, i64 20
}
@end
@interface SuperClass : NSObject
@property (nonatomic, assign) int superClassProperty;
@end
@implementation SuperClass {
int superClassIvar; // Declare an ivar
}
// CHECK-LABEL: define internal void @"\01-[SuperClass superClassMethod]"
- (void)superClassMethod {
_superClassProperty = 42;
superClassIvar = 10;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SuperClass
// CHECK: getelementptr inbounds i8, ptr %1, i64 20
}
// Implicitly synthesized method here
// CHECK-LABEL: define internal i32 @"\01-[SuperClass superClassProperty]"
// CHECK: getelementptr inbounds i8, ptr %0, i64 24
// CHECK-LABEL: define internal void @"\01-[SuperClass setSuperClassProperty:]"
// CHECK: getelementptr inbounds i8, ptr %1, i64 24
@end
@interface IntermediateClass : SuperClass {
double intermediateClassIvar;
@protected
int intermediateClassIvar2;
}
@property (nonatomic, strong) SuperClass *intermediateProperty;
@end
@implementation IntermediateClass
@synthesize intermediateProperty = _intermediateProperty;
// CHECK-LABEL: define internal void @"\01-[IntermediateClass intermediateClassMethod]"
- (void)intermediateClassMethod {
intermediateClassIvar = 3.14;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_IntermediateClass
// CHECK: getelementptr inbounds i8, ptr %0, i64 32
}
// CHECK-LABEL: define internal void @"\01-[IntermediateClass intermediateClassPropertyMethod]"
- (void)intermediateClassPropertyMethod {
self.intermediateProperty = 0;
// CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
// CHECK: call void @objc_msgSend(ptr noundef %0, ptr noundef %1, ptr noundef null)
}
// CHECK-LABEL: define internal void @"\01-[IntermediateClass intermediateClassPropertyMethodDirect]"
- (void)intermediateClassPropertyMethodDirect {
_intermediateProperty = 0;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_IntermediateClass._intermediateProperty"
// CHECK: getelementptr inbounds i8, ptr %0, i64 48
}
@end
@interface SubClass : IntermediateClass {
double subClassIvar;
}
@property (nonatomic, assign) SubClass *subClassProperty;
@end
@implementation SubClass
// CHECK-LABEL: define internal void @"\01-[SubClass subclassVar]"
- (void)subclassVar {
subClassIvar = 6.28;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SubClass
// CHECK: getelementptr inbounds i8, ptr %0, i64 56
}
// CHECK-LABEL: define internal void @"\01-[SubClass intermediateSubclassVar]"
-(void)intermediateSubclassVar {
intermediateClassIvar = 3.14;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_IntermediateClass
// CHECK: getelementptr inbounds i8, ptr %0, i64 32
}
// Implicit synthesized method here:
// CHECK-LABEL: define internal ptr @"\01-[SubClass subClassProperty]"
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SubClass._subClassProperty"
// CHECK: getelementptr inbounds i8, ptr %0, i64 64
// CHECK-LABEL: define internal void @"\01-[SubClass setSubClassProperty:]"
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SubClass._subClassProperty"
// CHECK: getelementptr inbounds i8, ptr %1, i64 64
@end
__attribute((objc_root_class)) @interface RootClass {
int these, never, change;
}
@end
@implementation RootClass
@end
@interface StillStaticLayout : RootClass
@end
@implementation StillStaticLayout {
int static_layout_ivar;
}
// CHECK-LABEL: define internal void @"\01-[StillStaticLayout meth]"
-(void)meth {
static_layout_ivar = 0;
// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$StillStaticLayout.static_layout_ivar
}
@end
@interface NotNSObject
@end
@interface NotStaticLayout : NotNSObject {
int these, might, change;
}
@end
@implementation NotStaticLayout {
int not_static_layout_ivar;
}
// CHECK-LABEL: define internal void @"\01-[NotStaticLayout meth]"
-(void)meth {
not_static_layout_ivar = 0;
// CHECK: load i64, ptr @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar
}
@end
// CHECK: define internal i32 @"\01-[IntermediateClass2 IntermediateClass2Property]"(ptr noundef %[[SELF:.*]],
// CHECK: %[[SELF_ADDR:.*]] = alloca ptr, align 8
// CHECK: store ptr %[[SELF]], ptr %[[SELF_ADDR]], align 8
// CHECK: %[[V0:.*]] = load ptr, ptr %[[SELF_ADDR]], align 8
// CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24
// CHECK: %[[LOAD:.*]] = load atomic i32, ptr %[[ADD_PTR]] unordered, align 4
// CHECK: ret i32 %[[LOAD]]
// CHECK: define internal i32 @"\01-[SubClass2 subClass2Property]"(ptr noundef %[[SELF:.*]],
// CHECK: %[[SELF_ADDR:.*]] = alloca ptr, align 8
// CHECK: store ptr %[[SELF]], ptr %[[SELF_ADDR]], align 8
// CHECK: %[[V0:.*]] = load ptr, ptr %[[SELF_ADDR]], align 8
// CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 28
// CHECK: %[[LOAD:.*]] = load atomic i32, ptr %[[ADD_PTR]] unordered, align 4
// CHECK: ret i32 %[[LOAD]]
@interface SuperClass2 : NSObject
@property int superClassProperty2;
@end
@interface IntermediateClass2 : SuperClass2
@property int IntermediateClass2Property;
@end
@interface IntermediateClass3 : SuperClass2
@property int IntermediateClass3Property;
@end
@interface SubClass2 : IntermediateClass2
@property int subClass2Property;
@end
@implementation IntermediateClass3
@end
@implementation SuperClass2
@end
@implementation IntermediateClass2
@end
@implementation SubClass2
@end