1// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
2
3struct my_complex_struct {
4  int a, b;
5};
6
7struct my_aggregate_struct {
8  int a, b;
9  char 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@end
18
19@implementation Root
20// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]"
21- (int)intProperty2 {
22  return 42;
23}
24
25// CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"(
26- (int)getInt __attribute__((objc_direct)) {
27  // loading parameters
28  // CHECK-LABEL: entry:
29  // CHECK-NEXT: [[RETVAL:%.*]] = alloca
30  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
31  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
32  // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
33  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
34
35  // self nil-check
36  // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
37  // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
38  // CHECK-NEXT: br i1 [[NILCHECK]],
39
40  // setting return value to nil
41  // CHECK-LABEL: objc_direct_method.self_is_nil:
42  // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
43  // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
44  // CHECK-NEXT: br label
45
46  // set value
47  // CHECK-LABEL: objc_direct_method.cont:
48  // CHECK: store{{.*}}[[RETVAL]],
49  // CHECK-NEXT: br label
50
51  // return
52  // CHECK-LABEL: return:
53  // CHECK: {{%.*}} = load{{.*}}[[RETVAL]],
54  // CHECK-NEXT: ret
55  return 42;
56}
57
58// CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"(
59+ (int)classGetInt __attribute__((objc_direct)) {
60  // loading parameters
61  // CHECK-LABEL: entry:
62  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*,
63  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
64  // CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]],
65  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
66
67  // [self self]
68  // CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]],
69  // CHECK-NEXT: [[SELFSEL:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
70  // CHECK-NEXT: [[SELF0:%.*]] = call {{.*}} @objc_msgSend
71  // CHECK-NEXT: store i8* [[SELF0]], i8** [[SELFADDR]],
72
73  // return
74  // CHECK-NEXT: ret
75  return 42;
76}
77
78// CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"(
79- (struct my_complex_struct)getComplex __attribute__((objc_direct)) {
80  // loading parameters
81  // CHECK-LABEL: entry:
82  // CHECK-NEXT: [[RETVAL:%.*]] = alloca
83  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
84  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
85  // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
86  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
87
88  // self nil-check
89  // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
90  // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
91  // CHECK-NEXT: br i1 [[NILCHECK]],
92
93  // setting return value to nil
94  // CHECK-LABEL: objc_direct_method.self_is_nil:
95  // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
96  // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
97  // CHECK-NEXT: br label
98
99  // set value
100  // CHECK-LABEL: objc_direct_method.cont:
101  // CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]]
102  // CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RET1]],
103  // CHECK-NEXT: br label
104
105  // return
106  // CHECK-LABEL: return:
107  // CHECK: [[RET2:%.*]] = bitcast{{.*}}[[RETVAL]]
108  // CHECK-NEXT: {{%.*}} = load{{.*}}[[RET2]],
109  // CHECK-NEXT: ret
110  struct my_complex_struct st = {.a = 42};
111  return st;
112}
113
114// CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"(
115+ (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {
116  struct my_complex_struct st = {.a = 42};
117  return st;
118  // CHECK: ret i64
119}
120
121// CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
122- (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
123  // CHECK: %struct.my_aggregate_struct* noalias sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]],
124
125  // loading parameters
126  // CHECK-LABEL: entry:
127  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
128  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
129  // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
130  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
131
132  // self nil-check
133  // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
134  // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
135  // CHECK-NEXT: br i1 [[NILCHECK]],
136
137  // setting return value to nil
138  // CHECK-LABEL: objc_direct_method.self_is_nil:
139  // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
140  // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
141  // CHECK-NEXT: br label
142
143  // set value
144  // CHECK-LABEL: objc_direct_method.cont:
145  // CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]]
146  // CHECK: br label
147
148  // return
149  // CHECK-LABEL: return:
150  // CHECK: ret void
151  struct my_aggregate_struct st = {.a = 42};
152  return st;
153}
154
155// CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"(
156+ (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) {
157  struct my_aggregate_struct st = {.a = 42};
158  return st;
159  // CHECK: ret void
160}
161
162@end
163// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
164
165@interface Foo : Root {
166  id __strong _cause_cxx_destruct;
167}
168@property(nonatomic, readonly, direct) int getDirect_setDynamic;
169@property(nonatomic, readonly) int getDynamic_setDirect;
170@end
171
172@interface Foo ()
173@property(nonatomic, readwrite) int getDirect_setDynamic;
174@property(nonatomic, readwrite, direct) int getDynamic_setDirect;
175- (int)directMethodInExtension __attribute__((objc_direct));
176@end
177
178@interface Foo (Cat)
179- (int)directMethodInCategory __attribute__((objc_direct));
180@end
181
182__attribute__((objc_direct_members))
183@implementation Foo
184// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"(
185- (int)directMethodInExtension {
186  return 42;
187}
188// CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"(
189// CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"(
190// CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"(
191// CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(
192// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(
193@end
194
195@implementation Foo (Cat)
196// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"(
197- (int)directMethodInCategory {
198  return 42;
199}
200// CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"(
201- (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) {
202  return 42;
203}
204@end
205
206int useRoot(Root *r) {
207  // CHECK-LABEL: define{{.*}} i32 @useRoot
208  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]"
209  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]"
210  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]"
211  return [r getInt] + [r intProperty] + [r intProperty2];
212}
213
214int useFoo(Foo *f) {
215  // CHECK-LABEL: define{{.*}} i32 @useFoo
216  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]"
217  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]"
218  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]"
219  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]"
220  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]"
221  [f setGetDynamic_setDirect:1];
222  return [f getDirect_setDynamic] +
223         [f directMethodInExtension] +
224         [f directMethodInCategory] +
225         [f directMethodInCategoryNoDecl];
226}
227
228__attribute__((objc_root_class))
229@interface RootDeclOnly
230@property(direct, readonly) int intProperty;
231@end
232
233int useRootDeclOnly(RootDeclOnly *r) {
234  // CHECK-LABEL: define{{.*}} i32 @useRootDeclOnly
235  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[RootDeclOnly intProperty]"
236  return [r intProperty];
237}
238