| // 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 |