Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenObjC / direct-method.m
blob8a3c2f575d2d328eba772c7e6734749c0bf6b618
1 // RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
3 struct my_complex_struct {
4   int a, b;
5 };
7 struct my_aggregate_struct {
8   int a, b;
9   char buf[128];
12 __attribute__((objc_root_class))
13 @interface Root
14 - (int)getInt __attribute__((objc_direct));
15 @property(direct, readonly) int intProperty;
16 @property(direct, readonly) int intProperty2;
17 @property(direct, readonly) id objectProperty;
18 @end
20 @implementation Root
21 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]"
22 - (int)intProperty2 {
23   return 42;
26 // CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"(
27 - (int)getInt __attribute__((objc_direct)) {
28   // loading parameters
29   // CHECK-LABEL: entry:
30   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
31   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
32   // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
34   // self nil-check
35   // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
36   // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null
37   // CHECK-NEXT: br i1 [[NILCHECK]],
39   // setting return value to nil
40   // CHECK-LABEL: objc_direct_method.self_is_nil:
41   // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,
42   // CHECK-NEXT: br label
44   // set value
45   // CHECK-LABEL: objc_direct_method.cont:
46   // CHECK: store{{.*}}[[RETVAL]],
47   // CHECK-NEXT: br label
49   // return
50   // CHECK-LABEL: return:
51   // CHECK: {{%.*}} = load{{.*}}[[RETVAL]],
52   // CHECK-NEXT: ret
53   return 42;
56 // CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"(
57 + (int)classGetInt __attribute__((objc_direct)) {
58   // loading parameters
59   // CHECK-LABEL: entry:
60   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
61   // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
63   // [self self]
64   // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
65   // CHECK-NEXT: [[SELFSEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
66   // CHECK-NEXT: [[SELF0:%.*]] = call {{.*}} @objc_msgSend
67   // CHECK-NEXT: store ptr [[SELF0]], ptr [[SELFADDR]],
69   // return
70   // CHECK-NEXT: ret
71   return 42;
74 // CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"(
75 - (struct my_complex_struct)getComplex __attribute__((objc_direct)) {
76   // loading parameters
77   // CHECK-LABEL: entry:
78   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
79   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
80   // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
82   // self nil-check
83   // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
84   // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null
85   // CHECK-NEXT: br i1 [[NILCHECK]],
87   // setting return value to nil
88   // CHECK-LABEL: objc_direct_method.self_is_nil:
89   // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,
90   // CHECK-NEXT: br label
92   // set value
93   // CHECK-LABEL: objc_direct_method.cont:
94   // CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RETVAL]],
95   // CHECK-NEXT: br label
97   // return
98   // CHECK-LABEL: return:
99   // CHECK-NEXT: {{%.*}} = load{{.*}}[[RETVAL]],
100   // CHECK-NEXT: ret
101   struct my_complex_struct st = {.a = 42};
102   return st;
105 // CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"(
106 + (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {
107   struct my_complex_struct st = {.a = 42};
108   return st;
109   // CHECK: ret i64
112 // CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
113 - (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
114   // CHECK: ptr noalias sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]],
116   // loading parameters
117   // CHECK-LABEL: entry:
118   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
119   // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
121   // self nil-check
122   // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
123   // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null
124   // CHECK-NEXT: br i1 [[NILCHECK]],
126   // setting return value to nil
127   // CHECK-LABEL: objc_direct_method.self_is_nil:
128   // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,
129   // CHECK-NEXT: br label
131   // set value
132   // CHECK-LABEL: objc_direct_method.cont:
133   // CHECK: br label
135   // return
136   // CHECK-LABEL: return:
137   // CHECK: ret void
138   struct my_aggregate_struct st = {.a = 42};
139   return st;
142 // CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"(
143 + (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) {
144   struct my_aggregate_struct st = {.a = 42};
145   return st;
146   // CHECK: ret void
149 // CHECK-LABEL: define hidden void @"\01-[Root accessCmd]"(
150 - (void)accessCmd __attribute__((objc_direct)) {
151   // CHECK-LABEL: entry:
152   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
153   // CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca ptr,
155   // loading the _cmd selector
156   // CHECK-LABEL: objc_direct_method.cont:
157   // CHECK-NEXT: [[CMD1:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
158   // CHECK-NEXT: store ptr [[CMD1]], ptr [[CMDVAL]],
159   SEL sel = _cmd;
162 @end
163 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
165 // Check the synthesized objectProperty calls objc_getProperty(); this also
166 // checks that the synthesized method passes undef for the `cmd` argument.
167 // CHECK-LABEL: define hidden ptr @"\01-[Root objectProperty]"(
168 // CHECK-LABEL: objc_direct_method.cont:
169 // 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]], {{.*}})
173 @interface Foo : Root {
174   id __strong _cause_cxx_destruct;
176 @property(nonatomic, readonly, direct) int getDirect_setDynamic;
177 @property(nonatomic, readonly) int getDynamic_setDirect;
178 @end
180 @interface Foo ()
181 @property(nonatomic, readwrite) int getDirect_setDynamic;
182 @property(nonatomic, readwrite, direct) int getDynamic_setDirect;
183 - (int)directMethodInExtension __attribute__((objc_direct));
184 @end
186 @interface Foo (Cat)
187 - (int)directMethodInCategory __attribute__((objc_direct));
188 @end
190 __attribute__((objc_direct_members))
191 @implementation Foo
192 // CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"(
193 - (int)directMethodInExtension {
194   return 42;
196 // CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"(
197 // CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"(
198 // CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"(
199 // CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(
200 // CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(
201 @end
203 @implementation Foo (Cat)
204 // CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"(
205 - (int)directMethodInCategory {
206   return 42;
208 // CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"(
209 - (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) {
210   return 42;
212 @end
214 int useRoot(Root *r) {
215   // CHECK-LABEL: define{{.*}} i32 @useRoot
216   // CHECK: %{{[^ ]*}} = call i32  @"\01-[Root getInt]"
217   // CHECK: %{{[^ ]*}} = call i32  @"\01-[Root intProperty]"
218   // CHECK: %{{[^ ]*}} = call i32  @"\01-[Root intProperty2]"
219   return [r getInt] + [r intProperty] + [r intProperty2];
222 int useFoo(Foo *f) {
223   // CHECK-LABEL: define{{.*}} i32 @useFoo
224   // CHECK: call void @"\01-[Foo setGetDynamic_setDirect:]"
225   // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo getDirect_setDynamic]"
226   // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInExtension]"
227   // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInCategory]"
228   // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInCategoryNoDecl]"
229   [f setGetDynamic_setDirect:1];
230   return [f getDirect_setDynamic] +
231          [f directMethodInExtension] +
232          [f directMethodInCategory] +
233          [f directMethodInCategoryNoDecl];
236 __attribute__((objc_root_class))
237 @interface RootDeclOnly
238 @property(direct, readonly) int intProperty;
239 @end
241 int useRootDeclOnly(RootDeclOnly *r) {
242   // CHECK-LABEL: define{{.*}} i32 @useRootDeclOnly
243   // CHECK: %{{[^ ]*}} = call i32 @"\01-[RootDeclOnly intProperty]"
244   return [r intProperty];