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@end
15
16@implementation Root
17// CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"(
18- (int)getInt __attribute__((objc_direct)) {
19  // loading parameters
20  // CHECK-LABEL: entry:
21  // CHECK-NEXT: [[RETVAL:%.*]] = alloca
22  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
23  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
24  // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
25  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
26
27  // self nil-check
28  // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
29  // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
30  // CHECK-NEXT: br i1 [[NILCHECK]],
31
32  // setting return value to nil
33  // CHECK-LABEL: objc_direct_method.self_is_nil:
34  // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
35  // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
36  // CHECK-NEXT: br label
37
38  // set value
39  // CHECK-LABEL: objc_direct_method.cont:
40  // CHECK: store{{.*}}[[RETVAL]],
41  // CHECK-NEXT: br label
42
43  // return
44  // CHECK-LABEL: return:
45  // CHECK: {{%.*}} = load{{.*}}[[RETVAL]],
46  // CHECK-NEXT: ret
47  return 42;
48}
49
50// CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"(
51+ (int)classGetInt __attribute__((objc_direct)) {
52  // loading parameters
53  // CHECK-LABEL: entry:
54  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*,
55  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
56  // CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]],
57  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
58
59  // [self self]
60  // CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]],
61  // CHECK-NEXT: [[SELFSEL:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
62  // CHECK-NEXT: [[SELF0:%.*]] = call {{.*}} @objc_msgSend
63  // CHECK-NEXT: store i8* [[SELF0]], i8** [[SELFADDR]],
64
65  // return
66  // CHECK-NEXT: ret
67  return 42;
68}
69
70// CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"(
71- (struct my_complex_struct)getComplex __attribute__((objc_direct)) {
72  // loading parameters
73  // CHECK-LABEL: entry:
74  // CHECK-NEXT: [[RETVAL:%.*]] = alloca
75  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
76  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
77  // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
78  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
79
80  // self nil-check
81  // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
82  // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
83  // CHECK-NEXT: br i1 [[NILCHECK]],
84
85  // setting return value to nil
86  // CHECK-LABEL: objc_direct_method.self_is_nil:
87  // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
88  // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
89  // CHECK-NEXT: br label
90
91  // set value
92  // CHECK-LABEL: objc_direct_method.cont:
93  // CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]]
94  // CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RET1]],
95  // CHECK-NEXT: br label
96
97  // return
98  // CHECK-LABEL: return:
99  // CHECK: [[RET2:%.*]] = bitcast{{.*}}[[RETVAL]]
100  // CHECK-NEXT: {{%.*}} = load{{.*}}[[RET2]],
101  // CHECK-NEXT: ret
102  struct my_complex_struct st = {.a = 42};
103  return st;
104}
105
106// CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"(
107+ (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {
108  struct my_complex_struct st = {.a = 42};
109  return st;
110  // CHECK: ret i64
111}
112
113// CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
114- (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
115  // CHECK: %struct.my_aggregate_struct* noalias sret [[RETVAL:%[^,]*]],
116
117  // loading parameters
118  // CHECK-LABEL: entry:
119  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
120  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
121  // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
122  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
123
124  // self nil-check
125  // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
126  // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq %0* [[SELF]], null
127  // CHECK-NEXT: br i1 [[NILCHECK]],
128
129  // setting return value to nil
130  // CHECK-LABEL: objc_direct_method.self_is_nil:
131  // CHECK: [[RET0:%.*]] = bitcast{{.*}}[[RETVAL]]
132  // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RET0]], i8 0,
133  // CHECK-NEXT: br label
134
135  // set value
136  // CHECK-LABEL: objc_direct_method.cont:
137  // CHECK: [[RET1:%.*]] = bitcast{{.*}}[[RETVAL]]
138  // CHECK: br label
139
140  // return
141  // CHECK-LABEL: return:
142  // CHECK: ret void
143  struct my_aggregate_struct st = {.a = 42};
144  return st;
145}
146
147// CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"(
148+ (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) {
149  struct my_aggregate_struct st = {.a = 42};
150  return st;
151  // CHECK: ret void
152}
153
154@end
155
156@interface Foo : Root {
157  id __strong _cause_cxx_destruct;
158}
159@property(nonatomic, readonly, direct) int getDirect_setDynamic;
160@property(nonatomic, readonly) int getDynamic_setDirect;
161@end
162
163@interface Foo ()
164@property(nonatomic, readwrite) int getDirect_setDynamic;
165@property(nonatomic, readwrite, direct) int getDynamic_setDirect;
166@end
167
168__attribute__((objc_direct_members))
169@implementation Foo
170// CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"(
171// CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"(
172// CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"(
173// CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(
174// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(
175@end
176