llvm-project
245 строк · 7.8 Кб
1// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
2
3struct my_complex_struct {
4int a, b;
5};
6
7struct my_aggregate_struct {
8int a, b;
9char buf[128];
10};
11
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
19
20@implementation Root
21// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]"
22- (int)intProperty2 {
23return 42;
24}
25
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]],
33
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]],
38
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
43
44// set value
45// CHECK-LABEL: objc_direct_method.cont:
46// CHECK: store{{.*}}[[RETVAL]],
47// CHECK-NEXT: br label
48
49// return
50// CHECK-LABEL: return:
51// CHECK: {{%.*}} = load{{.*}}[[RETVAL]],
52// CHECK-NEXT: ret
53return 42;
54}
55
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]],
62
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]],
68
69// return
70// CHECK-NEXT: ret
71return 42;
72}
73
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]],
81
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]],
86
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
91
92// set value
93// CHECK-LABEL: objc_direct_method.cont:
94// CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RETVAL]],
95// CHECK-NEXT: br label
96
97// return
98// CHECK-LABEL: return:
99// CHECK-NEXT: {{%.*}} = load{{.*}}[[RETVAL]],
100// CHECK-NEXT: ret
101struct my_complex_struct st = {.a = 42};
102return st;
103}
104
105// CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"(
106+ (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {
107struct my_complex_struct st = {.a = 42};
108return st;
109// CHECK: ret i64
110}
111
112// CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
113- (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
114// CHECK: ptr dead_on_unwind noalias writable sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]],
115
116// loading parameters
117// CHECK-LABEL: entry:
118// CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
119// CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
120
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]],
125
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
130
131// set value
132// CHECK-LABEL: objc_direct_method.cont:
133// CHECK: br label
134
135// return
136// CHECK-LABEL: return:
137// CHECK: ret void
138struct my_aggregate_struct st = {.a = 42};
139return st;
140}
141
142// CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"(
143+ (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) {
144struct my_aggregate_struct st = {.a = 42};
145return st;
146// CHECK: ret void
147}
148
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,
154
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]],
159SEL sel = _cmd;
160}
161
162@end
163// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
164
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]], {{.*}})
172
173@interface Foo : Root {
174id __strong _cause_cxx_destruct;
175}
176@property(nonatomic, readonly, direct) int getDirect_setDynamic;
177@property(nonatomic, readonly) int getDynamic_setDirect;
178@end
179
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
185
186@interface Foo (Cat)
187- (int)directMethodInCategory __attribute__((objc_direct));
188@end
189
190__attribute__((objc_direct_members))
191@implementation Foo
192// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"(
193- (int)directMethodInExtension {
194return 42;
195}
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
202
203@implementation Foo (Cat)
204// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"(
205- (int)directMethodInCategory {
206return 42;
207}
208// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"(
209- (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) {
210return 42;
211}
212@end
213
214int 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]"
219return [r getInt] + [r intProperty] + [r intProperty2];
220}
221
222int 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];
230return [f getDirect_setDynamic] +
231[f directMethodInExtension] +
232[f directMethodInCategory] +
233[f directMethodInCategoryNoDecl];
234}
235
236__attribute__((objc_root_class))
237@interface RootDeclOnly
238@property(direct, readonly) int intProperty;
239@end
240
241int useRootDeclOnly(RootDeclOnly *r) {
242// CHECK-LABEL: define{{.*}} i32 @useRootDeclOnly
243// CHECK: %{{[^ ]*}} = call i32 @"\01-[RootDeclOnly intProperty]"
244return [r intProperty];
245}
246