1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s |
2 | // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s |
3 | |
4 | // rdar://13129783. Check both native/non-native arc platforms. Here we check |
5 | // that they treat nonlazybind differently. |
6 | // RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s |
7 | // RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s |
8 | |
9 | // ARC-ALIEN: declare extern_weak void @llvm.objc.storeStrong(i8**, i8*) |
10 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.retain(i8*) |
11 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.autoreleaseReturnValue(i8*) |
12 | // ARC-ALIEN: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] |
13 | // ARC-ALIEN: declare extern_weak void @llvm.objc.release(i8*) |
14 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) |
15 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.initWeak(i8**, i8*) |
16 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.storeWeak(i8**, i8*) |
17 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.loadWeakRetained(i8**) |
18 | // ARC-ALIEN: declare extern_weak void @llvm.objc.destroyWeak(i8**) |
19 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.autorelease(i8*) |
20 | // ARC-ALIEN: declare extern_weak i8* @llvm.objc.retainAutorelease(i8*) |
21 | |
22 | // ARC-NATIVE: declare void @llvm.objc.storeStrong(i8**, i8*) |
23 | // ARC-NATIVE: declare i8* @llvm.objc.retain(i8*) |
24 | // ARC-NATIVE: declare i8* @llvm.objc.autoreleaseReturnValue(i8*) |
25 | // ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] |
26 | // ARC-NATIVE: declare void @llvm.objc.release(i8*) |
27 | // ARC-NATIVE: declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) |
28 | // ARC-NATIVE: declare i8* @llvm.objc.initWeak(i8**, i8*) |
29 | // ARC-NATIVE: declare i8* @llvm.objc.storeWeak(i8**, i8*) |
30 | // ARC-NATIVE: declare i8* @llvm.objc.loadWeakRetained(i8**) |
31 | // ARC-NATIVE: declare void @llvm.objc.destroyWeak(i8**) |
32 | // ARC-NATIVE: declare i8* @llvm.objc.autorelease(i8*) |
33 | // ARC-NATIVE: declare i8* @llvm.objc.retainAutorelease(i8*) |
34 | |
35 | // CHECK-LABEL: define void @test0 |
36 | void test0(id x) { |
37 | // CHECK: [[X:%.*]] = alloca i8* |
38 | // CHECK-NEXT: [[PARM:%.*]] = call i8* @llvm.objc.retain(i8* {{.*}}) |
39 | // CHECK-NEXT: store i8* [[PARM]], i8** [[X]] |
40 | // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]] |
41 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) |
42 | // CHECK-NEXT: ret void |
43 | } |
44 | |
45 | // CHECK-LABEL: define i8* @test1(i8* |
46 | id test1(id x) { |
47 | // CHECK: [[X:%.*]] = alloca i8* |
48 | // CHECK-NEXT: [[Y:%.*]] = alloca i8* |
49 | // CHECK-NEXT: [[PARM:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}}) |
50 | // CHECK-NEXT: store i8* [[PARM]], i8** [[X]] |
51 | // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8* |
52 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]]) |
53 | // CHECK-NEXT: store i8* null, i8** [[Y]] |
54 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] |
55 | // CHECK-NEXT: [[RET:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) |
56 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] |
57 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
58 | // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8* |
59 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]]) |
60 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] |
61 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
62 | // CHECK-NEXT: [[T1:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[RET]]) |
63 | // CHECK-NEXT: ret i8* [[T1]] |
64 | id y; |
65 | return y; |
66 | } |
67 | |
68 | @interface Test2 |
69 | + (void) class_method; |
70 | - (void) inst_method; |
71 | @end |
72 | @implementation Test2 |
73 | |
74 | // The self pointer of a class method is not retained. |
75 | // CHECK: define internal void @"\01+[Test2 class_method]" |
76 | // CHECK: alloca |
77 | // CHECK-NEXT: alloca |
78 | // CHECK-NEXT: store |
79 | // CHECK-NEXT: store |
80 | // CHECK-NEXT: ret void |
81 | + (void) class_method {} |
82 | |
83 | // The self pointer of an instance method is not retained. |
84 | // CHECK: define internal void @"\01-[Test2 inst_method]" |
85 | // CHECK: alloca |
86 | // CHECK-NEXT: alloca |
87 | // CHECK-NEXT: store |
88 | // CHECK-NEXT: store |
89 | // CHECK-NEXT: ret void |
90 | - (void) inst_method {} |
91 | @end |
92 | |
93 | @interface Test3 |
94 | + (id) alloc; |
95 | - (id) initWith: (int) x; |
96 | - (id) copy; |
97 | @end |
98 | |
99 | // CHECK-LABEL: define void @test3_unelided() |
100 | void test3_unelided() { |
101 | extern void test3_helper(void); |
102 | |
103 | // CHECK: [[X:%.*]] = alloca [[TEST3:%.*]]* |
104 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST3]]** [[X]] to i8* |
105 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
106 | // CHECK-NEXT: store [[TEST3]]* null, [[TEST3]]** [[X]], align |
107 | Test3 *x; |
108 | |
109 | // Call to +alloc. |
110 | // CHECK-NEXT: load {{.*}}, {{.*}}* @"OBJC_CLASSLIST_REFERENCES_ |
111 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
112 | // CHECK-NEXT: bitcast |
113 | // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend |
114 | // CHECK-NEXT: bitcast |
115 | // CHECK-NEXT: bitcast |
116 | // CHECK-NEXT: call void @llvm.objc.release(i8* |
117 | [Test3 alloc]; |
118 | |
119 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]*, [[TEST3]]** [[X]] |
120 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
121 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* |
122 | // CHECK-NEXT: [[COPY:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend {{.*}})(i8* [[T1]], |
123 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[COPY]]) [[NUW:#[0-9]+]] |
124 | [x copy]; |
125 | |
126 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]*, [[TEST3]]** [[X]] |
127 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* |
128 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]] |
129 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST3]]** [[X]] to i8* |
130 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
131 | // CHECK-NEXT: ret void |
132 | } |
133 | |
134 | // CHECK-LABEL: define void @test3() |
135 | void test3() { |
136 | // CHECK: [[X:%.*]] = alloca i8* |
137 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
138 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
139 | |
140 | id x = [[Test3 alloc] initWith: 5]; |
141 | |
142 | // Call to +alloc. |
143 | // CHECK-NEXT: load {{.*}}, {{.*}}* @"OBJC_CLASSLIST_REFERENCES_ |
144 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
145 | // CHECK-NEXT: bitcast |
146 | // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend |
147 | // CHECK-NEXT: bitcast |
148 | |
149 | // Call to -initWith: with elided retain of consumed argument. |
150 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
151 | // CHECK-NEXT: bitcast |
152 | // CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* |
153 | // CHECK-NEXT: bitcast |
154 | // CHECK-NEXT: [[INIT:%.*]] = bitcast |
155 | // Assignment for initialization, retention elided. |
156 | // CHECK-NEXT: store i8* [[INIT]], i8** [[X]] |
157 | |
158 | // Call to -copy. |
159 | // CHECK-NEXT: [[V:%.*]] = load i8*, i8** [[X]] |
160 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
161 | // CHECK-NEXT: [[COPY:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend {{.*}})(i8* [[V]], |
162 | |
163 | // Assignment to x. |
164 | // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]] |
165 | // CHECK-NEXT: store i8* [[COPY]], i8** [[X]] |
166 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]] |
167 | |
168 | x = [x copy]; |
169 | |
170 | // Cleanup for x. |
171 | // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]] |
172 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]] |
173 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
174 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
175 | // CHECK-NEXT: ret void |
176 | } |
177 | |
178 | // CHECK-LABEL: define i8* @test4() |
179 | id test4() { |
180 | // Call to +alloc. |
181 | // CHECK: load {{.*}}, {{.*}}* @"OBJC_CLASSLIST_REFERENCES_ |
182 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
183 | // CHECK-NEXT: bitcast |
184 | // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend |
185 | // CHECK-NEXT: [[ALLOC:%.*]] = bitcast |
186 | |
187 | // Call to -initWith: with elided retain of consumed argument. |
188 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
189 | // CHECK-NEXT: [[ALLOC:%.*]] = bitcast |
190 | // CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* [[ALLOC]], |
191 | |
192 | // Initialization of return value, occurring within full-expression. |
193 | // Retain/release elided. |
194 | // CHECK-NEXT: bitcast |
195 | // CHECK-NEXT: [[INIT:%.*]] = bitcast |
196 | // CHECK-NEXT: [[RET:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[INIT]]) |
197 | |
198 | // CHECK-NEXT: ret i8* [[RET]] |
199 | |
200 | return [[Test3 alloc] initWith: 6]; |
201 | } |
202 | |
203 | @interface Test5 { |
204 | @public |
205 | id var; |
206 | } |
207 | @end |
208 | |
209 | // CHECK-LABEL: define void @test5 |
210 | void test5(Test5 *x, id y) { |
211 | // Prologue. |
212 | // CHECK: [[X:%.*]] = alloca [[TEST5:%.*]]*, |
213 | // CHECK-NEXT: [[Y:%.*]] = alloca i8* |
214 | // CHECK-NEXT: bitcast [[TEST5]]* {{%.*}} to i8* |
215 | // CHECK-NEXT: call i8* @llvm.objc.retain |
216 | // CHECK-NEXT: [[PARMX:%.*]] = bitcast i8* {{%.*}} to [[TEST5]]* |
217 | // CHECK-NEXT: store [[TEST5]]* [[PARMX]], [[TEST5]]** [[X]] |
218 | // CHECK-NEXT: call i8* @llvm.objc.retain |
219 | // CHECK-NEXT: store |
220 | |
221 | // CHECK-NEXT: load [[TEST5]]*, [[TEST5]]** [[X]] |
222 | // CHECK-NEXT: load i64, i64* @"OBJC_IVAR_$_Test5.var" |
223 | // CHECK-NEXT: bitcast |
224 | // CHECK-NEXT: getelementptr |
225 | // CHECK-NEXT: [[VAR:%.*]] = bitcast |
226 | // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[VAR]] |
227 | // CHECK-NEXT: store i8* null, i8** [[VAR]] |
228 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]] |
229 | x->var = 0; |
230 | |
231 | // CHECK-NEXT: [[YVAL:%.*]] = load i8*, i8** [[Y]] |
232 | // CHECK-NEXT: load [[TEST5]]*, [[TEST5]]** [[X]] |
233 | // CHECK-NEXT: load i64, i64* @"OBJC_IVAR_$_Test5.var" |
234 | // CHECK-NEXT: bitcast |
235 | // CHECK-NEXT: getelementptr |
236 | // CHECK-NEXT: [[VAR:%.*]] = bitcast |
237 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[YVAL]]) [[NUW]] |
238 | // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[VAR]] |
239 | // CHECK-NEXT: store i8* [[T0]], i8** [[VAR]] |
240 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]] |
241 | x->var = y; |
242 | |
243 | // Epilogue. |
244 | // CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[Y]] |
245 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]] |
246 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST5]]*, [[TEST5]]** [[X]] |
247 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST5]]* [[T0]] to i8* |
248 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]] |
249 | // CHECK-NEXT: ret void |
250 | } |
251 | |
252 | id test6_helper(void) __attribute__((ns_returns_retained)); |
253 | // CHECK-LABEL: define void @test6() |
254 | void test6() { |
255 | // CHECK: [[X:%.*]] = alloca i8* |
256 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
257 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
258 | // CHECK-NEXT: [[CALL:%.*]] = call i8* @test6_helper() |
259 | // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] |
260 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] |
261 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release |
262 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
263 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
264 | // CHECK-NEXT: ret void |
265 | id x = test6_helper(); |
266 | } |
267 | |
268 | void test7_helper(id __attribute__((ns_consumed))); |
269 | // CHECK-LABEL: define void @test7() |
270 | void test7() { |
271 | // CHECK: [[X:%.*]] = alloca i8* |
272 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
273 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
274 | // CHECK-NEXT: store i8* null, i8** [[X]] |
275 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] |
276 | // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) [[NUW]] |
277 | // CHECK-NEXT: call void @test7_helper(i8* [[T1]]) |
278 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] |
279 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release |
280 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
281 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
282 | // CHECK-NEXT: ret void |
283 | id x; |
284 | test7_helper(x); |
285 | } |
286 | |
287 | id test8_helper(void) __attribute__((ns_returns_retained)); |
288 | void test8() { |
289 | __unsafe_unretained id x = test8_helper(); |
290 | // CHECK: [[X:%.*]] = alloca i8* |
291 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
292 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
293 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test8_helper() |
294 | // CHECK-NEXT: store i8* [[T0]], i8** [[X]] |
295 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release |
296 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
297 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
298 | // CHECK-NEXT: ret void |
299 | } |
300 | |
301 | @interface Test10 |
302 | @property (retain) Test10 *me; |
303 | @end |
304 | void test10() { |
305 | Test10 *x; |
306 | id y = x.me.me; |
307 | |
308 | // CHECK-LABEL: define void @test10() |
309 | // CHECK: [[X:%.*]] = alloca [[TEST10:%.*]]*, align |
310 | // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align |
311 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST10]]** [[X]] to i8* |
312 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
313 | // CHECK-NEXT: store [[TEST10]]* null, [[TEST10]]** [[X]] |
314 | // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8* |
315 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]]) |
316 | // CHECK-NEXT: load [[TEST10]]*, [[TEST10]]** [[X]], align |
317 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_{{[0-9]*}} |
318 | // CHECK-NEXT: bitcast |
319 | // CHECK-NEXT: [[T0:%.*]] = call [[TEST10]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend |
320 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8* |
321 | // CHECK-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) |
322 | // CHECK-NEXT: [[V:%.*]] = bitcast i8* [[T2]] to [[TEST10]]* |
323 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_{{[0-9]*}} |
324 | // CHECK-NEXT: bitcast |
325 | // CHECK-NEXT: [[T0:%.*]] = call [[TEST10]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend |
326 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8* |
327 | // CHECK-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) |
328 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST10]]* |
329 | // CHECK-NEXT: [[T4:%.*]] = bitcast [[TEST10]]* [[T3]] to i8* |
330 | // CHECK-NEXT: store i8* [[T4]], i8** [[Y]] |
331 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST10]]* [[V]] to i8* |
332 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
333 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] |
334 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
335 | // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8* |
336 | // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]]) |
337 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST10]]*, [[TEST10]]** [[X]] |
338 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8* |
339 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
340 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST10]]** [[X]] to i8* |
341 | // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
342 | // CHECK-NEXT: ret void |
343 | } |
344 | |
345 | void test11(id (*f)(void) __attribute__((ns_returns_retained))) { |
346 | // CHECK-LABEL: define void @test11( |
347 | // CHECK: [[F:%.*]] = alloca i8* ()*, align |
348 | // CHECK-NEXT: [[X:%.*]] = alloca i8*, align |
349 | // CHECK-NEXT: store i8* ()* {{%.*}}, i8* ()** [[F]], align |
350 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
351 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
352 | // CHECK-NEXT: [[T0:%.*]] = load i8* ()*, i8* ()** [[F]], align |
353 | // CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]() |
354 | // CHECK-NEXT: store i8* [[T1]], i8** [[X]], align |
355 | // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]] |
356 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T3]]) [[NUW]], !clang.imprecise_release |
357 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
358 | // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
359 | // CHECK-NEXT: ret void |
360 | id x = f(); |
361 | } |
362 | |
363 | void test12(void) { |
364 | extern id test12_helper(void); |
365 | |
366 | // CHECK-LABEL: define void @test12() |
367 | // CHECK: [[X:%.*]] = alloca i8*, align |
368 | // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align |
369 | |
370 | __weak id x = test12_helper(); |
371 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
372 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
373 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper() |
374 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
375 | // CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[X]], i8* [[T1]]) |
376 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
377 | |
378 | x = test12_helper(); |
379 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper() |
380 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
381 | // CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[X]], i8* [[T1]]) |
382 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
383 | |
384 | id y = x; |
385 | // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8* |
386 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]]) |
387 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[X]]) |
388 | // CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align |
389 | |
390 | // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[Y]] |
391 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]]) [[NUW]], !clang.imprecise_release |
392 | // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8* |
393 | // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]]) |
394 | // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[X]]) |
395 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
396 | // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
397 | // CHECK: ret void |
398 | } |
399 | |
400 | // Indirect consuming calls. |
401 | void test13(void) { |
402 | // CHECK-LABEL: define void @test13() |
403 | // CHECK: [[X:%.*]] = alloca i8*, align |
404 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
405 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
406 | // CHECK-NEXT: store i8* null, i8** [[X]], align |
407 | id x; |
408 | |
409 | typedef void fnty(id __attribute__((ns_consumed))); |
410 | extern fnty *test13_func; |
411 | // CHECK-NEXT: [[FN:%.*]] = load void (i8*)*, void (i8*)** @test13_func, align |
412 | // CHECK-NEXT: [[X_VAL:%.*]] = load i8*, i8** [[X]], align |
413 | // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @llvm.objc.retain(i8* [[X_VAL]]) [[NUW]] |
414 | // CHECK-NEXT: call void [[FN]](i8* [[X_TMP]]) |
415 | test13_func(x); |
416 | |
417 | extern fnty ^test13_block; |
418 | // CHECK-NEXT: [[TMP:%.*]] = load void (i8*)*, void (i8*)** @test13_block, align |
419 | // CHECK-NEXT: [[BLOCK:%.*]] = bitcast void (i8*)* [[TMP]] to [[BLOCKTY:%.*]]* |
420 | // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds [[BLOCKTY]], [[BLOCKTY]]* [[BLOCK]], i32 0, i32 3 |
421 | // CHECK-NEXT: [[BLOCK_OPAQUE:%.*]] = bitcast [[BLOCKTY]]* [[BLOCK]] to i8* |
422 | // CHECK-NEXT: [[X_VAL:%.*]] = load i8*, i8** [[X]], align |
423 | // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @llvm.objc.retain(i8* [[X_VAL]]) [[NUW]] |
424 | // CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load i8*, i8** [[BLOCK_FN_PTR]] |
425 | // CHECK-NEXT: [[BLOCK_FN:%.*]] = bitcast i8* [[BLOCK_FN_TMP]] to void (i8*, i8*)* |
426 | // CHECK-NEXT: call void [[BLOCK_FN]](i8* [[BLOCK_OPAQUE]], i8* [[X_TMP]]) |
427 | test13_block(x); |
428 | |
429 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] |
430 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]] |
431 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
432 | // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
433 | // CHECK-NEXT: ret void |
434 | } |
435 | |
436 | @interface Test16_super @end |
437 | @interface Test16 : Test16_super { |
438 | id z; |
439 | } |
440 | @property (assign) int x; |
441 | @property (retain) id y; |
442 | - (void) dealloc; |
443 | @end |
444 | @implementation Test16 |
445 | @synthesize x; |
446 | @synthesize y; |
447 | - (void) dealloc { |
448 | // CHECK: define internal void @"\01-[Test16 dealloc]"( |
449 | // CHECK: [[SELF:%.*]] = alloca [[TEST16:%.*]]*, align |
450 | // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align |
451 | // CHECK-NEXT: alloca |
452 | // CHECK-NEXT: store [[TEST16]]* {{%.*}}, [[TEST16]]** [[SELF]], align |
453 | // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] |
454 | // CHECK-NEXT: [[BASE:%.*]] = load [[TEST16]]*, [[TEST16]]** [[SELF]] |
455 | |
456 | // Call super. |
457 | // CHECK-NEXT: [[BASE2:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* |
458 | // CHECK-NEXT: [[T0:%.*]] = getelementptr |
459 | // CHECK-NEXT: store i8* [[BASE2]], i8** [[T0]] |
460 | // CHECK-NEXT: load {{%.*}}*, {{%.*}}** @"OBJC_CLASSLIST_SUP_REFS_$_ |
461 | // CHECK-NEXT: bitcast |
462 | // CHECK-NEXT: getelementptr |
463 | // CHECK-NEXT: store |
464 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
465 | // CHECK-NEXT: call void bitcast (i8* ({{.*}})* @objc_msgSendSuper2 to void ( |
466 | // CHECK-NEXT: ret void |
467 | } |
468 | |
469 | // .cxx_destruct |
470 | // CHECK: define internal void @"\01-[Test16 .cxx_destruct]"( |
471 | // CHECK: [[SELF:%.*]] = alloca [[TEST16:%.*]]*, align |
472 | // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align |
473 | // CHECK-NEXT: store [[TEST16]]* {{%.*}}, [[TEST16]]** [[SELF]], align |
474 | // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] |
475 | // CHECK-NEXT: [[BASE:%.*]] = load [[TEST16]]*, [[TEST16]]** [[SELF]] |
476 | |
477 | // Destroy y. |
478 | // CHECK-NEXT: [[Y_OFF:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test16.y" |
479 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* |
480 | // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[Y_OFF]] |
481 | // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** |
482 | // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T2]], i8* null) [[NUW]] |
483 | |
484 | // Destroy z. |
485 | // CHECK-NEXT: [[Z_OFF:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test16.z" |
486 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* |
487 | // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[Z_OFF]] |
488 | // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** |
489 | // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T2]], i8* null) [[NUW]] |
490 | |
491 | // CHECK-NEXT: ret void |
492 | |
493 | @end |
494 | |
495 | // This shouldn't crash. |
496 | @interface Test17A |
497 | @property (assign) int x; |
498 | @end |
499 | @interface Test17B : Test17A |
500 | @end |
501 | @implementation Test17B |
502 | - (int) x { return super.x + 1; } |
503 | @end |
504 | |
505 | void test19() { |
506 | // CHECK-LABEL: define void @test19() |
507 | // CHECK: [[X:%.*]] = alloca [5 x i8*], align 16 |
508 | // CHECK: call void @llvm.lifetime.start |
509 | // CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8* |
510 | // CHECK: call void @llvm.memset.p0i8.i64(i8* align 16 [[T0]], i8 0, i64 40, i1 false) |
511 | id x[5]; |
512 | |
513 | extern id test19_helper(void); |
514 | x[2] = test19_helper(); |
515 | |
516 | // CHECK-NEXT: [[CALL:%.*]] = call i8* @test19_helper() |
517 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]]) [[NUW]] |
518 | // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[X]], i64 0, i64 2 |
519 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]] |
520 | // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]] |
521 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]] |
522 | |
523 | // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[X]], i32 0, i32 0 |
524 | // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[BEGIN]], i64 5 |
525 | // CHECK-NEXT: br label |
526 | |
527 | // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] |
528 | // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1 |
529 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]] |
530 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release |
531 | // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] |
532 | // CHECK-NEXT: br i1 [[EQ]], |
533 | |
534 | // CHECK: ret void |
535 | } |
536 | |
537 | void test20(unsigned n) { |
538 | // CHECK-LABEL: define void @test20 |
539 | // CHECK: [[N:%.*]] = alloca i32, align 4 |
540 | // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8* |
541 | // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8 |
542 | // CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4 |
543 | |
544 | id x[n]; |
545 | |
546 | // Capture the VLA size. |
547 | // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[N]], align 4 |
548 | // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64 |
549 | |
550 | // Save the stack pointer. |
551 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave() |
552 | // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]] |
553 | |
554 | // Allocate the VLA. |
555 | // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16 |
556 | |
557 | // Store the VLA #elements expression. |
558 | // CHECK-NEXT: store i64 [[DIM]], i64* [[VLA_EXPR]], align 8 |
559 | |
560 | // Zero-initialize. |
561 | // CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8* |
562 | // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8 |
563 | // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 16 [[T0]], i8 0, i64 [[T1]], i1 false) |
564 | |
565 | // Destroy. |
566 | // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[VLA]], i64 [[DIM]] |
567 | // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq i8** [[VLA]], [[END]] |
568 | // CHECK-NEXT: br i1 [[EMPTY]] |
569 | |
570 | // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] |
571 | // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1 |
572 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]] |
573 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release |
574 | // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[VLA]] |
575 | // CHECK-NEXT: br i1 [[EQ]], |
576 | |
577 | // CHECK: [[T0:%.*]] = load i8*, i8** [[SAVED_STACK]] |
578 | // CHECK-NEXT: call void @llvm.stackrestore(i8* [[T0]]) |
579 | // CHECK-NEXT: ret void |
580 | } |
581 | |
582 | void test21(unsigned n) { |
583 | // CHECK-LABEL: define void @test21 |
584 | // CHECK: [[N:%.*]] = alloca i32, align 4 |
585 | // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8* |
586 | // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8 |
587 | // CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4 |
588 | |
589 | id x[2][n][3]; |
590 | |
591 | // Capture the VLA size. |
592 | // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[N]], align 4 |
593 | // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64 |
594 | |
595 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave() |
596 | // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]] |
597 | |
598 | |
599 | // Allocate the VLA. |
600 | // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] |
601 | // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16 |
602 | |
603 | // Store the VLA #elements expression. |
604 | // CHECK-NEXT: store i64 [[DIM]], i64* [[VLA_EXPR]], align 8 |
605 | |
606 | // Zero-initialize. |
607 | // CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8* |
608 | // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]] |
609 | // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24 |
610 | // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 16 [[T0]], i8 0, i64 [[T2]], i1 false) |
611 | |
612 | // Destroy. |
613 | // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] |
614 | // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x i8*], [3 x i8*]* [[VLA]], i32 0, i32 0 |
615 | // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3 |
616 | // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[BEGIN]], i64 [[T1]] |
617 | // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq i8** [[BEGIN]], [[END]] |
618 | // CHECK-NEXT: br i1 [[EMPTY]] |
619 | |
620 | // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] |
621 | // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1 |
622 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]] |
623 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release |
624 | // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] |
625 | // CHECK-NEXT: br i1 [[EQ]], |
626 | |
627 | // CHECK: [[T0:%.*]] = load i8*, i8** [[SAVED_STACK]] |
628 | // CHECK-NEXT: call void @llvm.stackrestore(i8* [[T0]]) |
629 | // CHECK-NEXT: ret void |
630 | } |
631 | |
632 | // rdar://problem/8922540 |
633 | // Note that we no longer emit .release_ivars flags. |
634 | // rdar://problem/12492434 |
635 | // Note that we set the flag saying that we need destruction *and* |
636 | // the flag saying that we don't also need construction. |
637 | // CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = private global [[RO_T:%.*]] { i32 390, |
638 | @interface Test23 { id x; } @end |
639 | @implementation Test23 @end |
640 | |
641 | // CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test24" = private global [[RO_T:%.*]] { i32 130, |
642 | @interface Test24 {} @end |
643 | @implementation Test24 @end |
644 | |
645 | // rdar://problem/8941012 |
646 | @interface Test26 { id x[4]; } @end |
647 | @implementation Test26 @end |
648 | // CHECK: define internal void @"\01-[Test26 .cxx_destruct]"( |
649 | // CHECK: [[SELF:%.*]] = load [[TEST26:%.*]]*, [[TEST26:%.*]]** |
650 | // CHECK-NEXT: [[OFFSET:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test26.x" |
651 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST26]]* [[SELF]] to i8* |
652 | // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]] |
653 | // CHECK-NEXT: [[X:%.*]] = bitcast i8* [[T1]] to [4 x i8*]* |
654 | // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[X]], i32 0, i32 0 |
655 | // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[BEGIN]], i64 4 |
656 | // CHECK-NEXT: br label |
657 | // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] |
658 | // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1 |
659 | // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[CUR]], i8* null) |
660 | // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] |
661 | // CHECK-NEXT: br i1 [[ISDONE]], |
662 | // CHECK: ret void |
663 | |
664 | // Check that 'init' retains self. |
665 | @interface Test27 |
666 | - (id) init; |
667 | @end |
668 | @implementation Test27 |
669 | - (id) init { return self; } |
670 | // CHECK: define internal i8* @"\01-[Test27 init]" |
671 | // CHECK: [[SELF:%.*]] = alloca [[TEST27:%.*]]*, |
672 | // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, |
673 | // CHECK-NEXT: store [[TEST27]]* {{%.*}}, [[TEST27]]** [[SELF]] |
674 | // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] |
675 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]*, [[TEST27]]** [[SELF]] |
676 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8* |
677 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) |
678 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST27]]* |
679 | // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST27]]* [[T3]] to i8* |
680 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]*, [[TEST27]]** [[SELF]] |
681 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8* |
682 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
683 | // CHECK-NEXT: ret i8* [[RET]] |
684 | |
685 | @end |
686 | |
687 | // rdar://problem/8087194 |
688 | @interface Test28 |
689 | @property (copy) id prop; |
690 | @end |
691 | @implementation Test28 |
692 | @synthesize prop; |
693 | @end |
694 | // CHECK: define internal void @"\01-[Test28 .cxx_destruct]" |
695 | // CHECK: [[SELF:%.*]] = load [[TEST28:%.*]]*, [[TEST28:%.*]]** |
696 | // CHECK-NEXT: [[OFFSET:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test28.prop" |
697 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST28]]* [[SELF]] to i8* |
698 | // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]] |
699 | // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** |
700 | // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T2]], i8* null) |
701 | // CHECK-NEXT: ret void |
702 | |
703 | @interface Test29_super |
704 | - (id) initWithAllocator: (id) allocator; |
705 | @end |
706 | @interface Test29 : Test29_super |
707 | - (id) init; |
708 | - (id) initWithAllocator: (id) allocator; |
709 | @end |
710 | @implementation Test29 |
711 | static id _test29_allocator = 0; |
712 | - (id) init { |
713 | // CHECK: define internal i8* @"\01-[Test29 init]"([[TEST29:%[^*]*]]* {{%.*}}, |
714 | // CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8 |
715 | // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8 |
716 | // CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]] |
717 | // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] |
718 | |
719 | // Evaluate arguments. Note that the send argument is evaluated |
720 | // before the zeroing of self. |
721 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]], align 8 |
722 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @_test29_allocator, align 8 |
723 | |
724 | // Implicit null of 'self', i.e. direct transfer of ownership. |
725 | // CHECK-NEXT: store [[TEST29]]* null, [[TEST29]]** [[SELF]] |
726 | |
727 | // Actual message send. |
728 | // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
729 | // CHECK-NEXT: [[T3:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* |
730 | // CHECK-NEXT: [[CALL:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T3]], i8* [[T2]], i8* [[T1]]) |
731 | |
732 | // Implicit write of result back into 'self'. This is not supposed to |
733 | // be detectable because we're supposed to ban accesses to the old |
734 | // self value past the delegate init call. |
735 | // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* |
736 | // CHECK-NEXT: store [[TEST29]]* [[T0]], [[TEST29]]** [[SELF]] |
737 | |
738 | // Return statement. |
739 | // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[CALL]] |
740 | // CHECK-NEXT: [[CALL:%.*]] = bitcast |
741 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[CALL]]) [[NUW]] |
742 | // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]* |
743 | // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8* |
744 | |
745 | // Cleanup. |
746 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]] |
747 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* |
748 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release |
749 | |
750 | // Return. |
751 | // CHECK-NEXT: ret i8* [[RET]] |
752 | return [self initWithAllocator: _test29_allocator]; |
753 | } |
754 | - (id) initWithAllocator: (id) allocator { |
755 | // CHECK: define internal i8* @"\01-[Test29 initWithAllocator:]"( |
756 | // CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8 |
757 | // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8 |
758 | // CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca i8*, align 8 |
759 | // CHECK-NEXT: alloca |
760 | // CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]] |
761 | // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] |
762 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}}) |
763 | // CHECK-NEXT: store i8* [[T0]], i8** [[ALLOCATOR]] |
764 | |
765 | // Evaluate arguments. Note that the send argument is evaluated |
766 | // before the zeroing of self. |
767 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]] |
768 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[ALLOCATOR]], align 8 |
769 | |
770 | // Implicit null of 'self', i.e. direct transfer of ownership. |
771 | // CHECK-NEXT: store [[TEST29]]* null, [[TEST29]]** [[SELF]] |
772 | |
773 | // Actual message send. |
774 | // CHECK: [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2 |
775 | |
776 | // Implicit write of result back into 'self'. This is not supposed to |
777 | // be detectable because we're supposed to ban accesses to the old |
778 | // self value past the delegate init call. |
779 | // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* |
780 | // CHECK-NEXT: store [[TEST29]]* [[T0]], [[TEST29]]** [[SELF]] |
781 | |
782 | // Assignment. |
783 | // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* |
784 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* |
785 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) [[NUW]] |
786 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST29]]* |
787 | // CHECK-NEXT: [[T4:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]], align |
788 | // CHECK-NEXT: store [[TEST29]]* [[T3]], [[TEST29]]** [[SELF]], align |
789 | // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST29]]* [[T4]] to i8* |
790 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]]) |
791 | |
792 | // Return statement. |
793 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]] |
794 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* |
795 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) [[NUW]] |
796 | // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]* |
797 | // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8* |
798 | |
799 | // Cleanup. |
800 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[ALLOCATOR]] |
801 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release |
802 | |
803 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]] |
804 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* |
805 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release |
806 | |
807 | // Return. |
808 | // CHECK-NEXT: ret i8* [[RET]] |
809 | self = [super initWithAllocator: allocator]; |
810 | return self; |
811 | } |
812 | @end |
813 | |
814 | typedef struct Test30_helper Test30_helper; |
815 | @interface Test30 |
816 | - (id) init; |
817 | - (Test30_helper*) initHelper; |
818 | @end |
819 | @implementation Test30 { |
820 | char *helper; |
821 | } |
822 | - (id) init { |
823 | // CHECK: define internal i8* @"\01-[Test30 init]"([[TEST30:%[^*]*]]* {{%.*}}, |
824 | // CHECK: [[RET:%.*]] = alloca [[TEST30]]* |
825 | // CHECK-NEXT: alloca i8* |
826 | // CHECK-NEXT: store [[TEST30]]* {{%.*}}, [[TEST30]]** [[SELF]] |
827 | // CHECK-NEXT: store |
828 | |
829 | // Call. |
830 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]] |
831 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
832 | // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* |
833 | // CHECK-NEXT: [[CALL:%.*]] = call [[TEST30_HELPER:%.*]]* bitcast {{.*}} @objc_msgSend {{.*}}(i8* [[T2]], i8* [[T1]]) |
834 | |
835 | // Assignment. |
836 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST30_HELPER]]* [[CALL]] to i8* |
837 | // CHECK-NEXT: [[T1:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]] |
838 | // CHECK-NEXT: [[IVAR:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test30.helper" |
839 | // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST30]]* [[T1]] to i8* |
840 | // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[IVAR]] |
841 | // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** |
842 | // CHECK-NEXT#: [[T5:%.*]] = load i8*, i8** [[T4]] |
843 | // CHECK-NEXT#: [[T6:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) |
844 | // CHECK-NEXT#: call void @llvm.objc.release(i8* [[T5]]) |
845 | // CHECK-NEXT: store i8* [[T0]], i8** [[T4]] |
846 | |
847 | // Return. |
848 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]] |
849 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* |
850 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) |
851 | // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST30]]* |
852 | // CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST30]]* [[T1]] to i8* |
853 | |
854 | // Cleanup. |
855 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]] |
856 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* |
857 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
858 | |
859 | // Epilogue. |
860 | // CHECK-NEXT: ret i8* [[RET]] |
861 | self->helper = [self initHelper]; |
862 | return self; |
863 | } |
864 | - (Test30_helper*) initHelper { |
865 | // CHECK: define internal [[TEST30_HELPER]]* @"\01-[Test30 initHelper]"( |
866 | // CHECK: alloca |
867 | // CHECK-NEXT: alloca |
868 | // CHECK-NEXT: store |
869 | // CHECK-NEXT: store |
870 | // CHECK-NEXT: ret [[TEST30_HELPER]]* null |
871 | return 0; |
872 | } |
873 | |
874 | @end |
875 | |
876 | __attribute__((ns_returns_retained)) id test32(void) { |
877 | // CHECK-LABEL: define i8* @test32() |
878 | // CHECK: [[CALL:%.*]] = call i8* @test32_helper() |
879 | // CHECK-NEXT: [[T0:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]]) |
880 | // CHECK-NEXT: ret i8* [[T0]] |
881 | extern id test32_helper(void); |
882 | return test32_helper(); |
883 | } |
884 | |
885 | @class Test33_a; |
886 | @interface Test33 |
887 | - (void) give: (Test33_a **) x; |
888 | - (void) take: (Test33_a **) x; |
889 | - (void) giveStrong: (out __strong Test33_a **) x; |
890 | - (void) takeStrong: (inout __strong Test33_a **) x; |
891 | - (void) giveOut: (out Test33_a **) x; |
892 | @end |
893 | void test33(Test33 *ptr) { |
894 | Test33_a *a; |
895 | [ptr give: &a]; |
896 | [ptr take: &a]; |
897 | [ptr giveStrong: &a]; |
898 | [ptr takeStrong: &a]; |
899 | [ptr giveOut: &a]; |
900 | |
901 | // CHECK: define void @test33([[TEST33:%.*]]* |
902 | // CHECK: [[PTR:%.*]] = alloca [[TEST33]]* |
903 | // CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]]* |
904 | // CHECK-NEXT: [[TEMP0:%.*]] = alloca [[A_T]]* |
905 | // CHECK-NEXT: [[TEMP1:%.*]] = alloca [[A_T]]* |
906 | // CHECK-NEXT: [[TEMP2:%.*]] = alloca [[A_T]]* |
907 | // CHECK-NEXT: bitcast |
908 | // CHECK-NEXT: llvm.objc.retain |
909 | // CHECK-NEXT: bitcast |
910 | // CHECK-NEXT: store |
911 | // CHECK-NEXT: bitcast |
912 | // CHECK-NEXT: call void @llvm.lifetime.start |
913 | // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[A]] |
914 | |
915 | // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]] |
916 | // CHECK-NEXT: [[W0:%.*]] = load [[A_T]]*, [[A_T]]** [[A]] |
917 | // CHECK-NEXT: store [[A_T]]* [[W0]], [[A_T]]** [[TEMP0]] |
918 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
919 | // CHECK-NEXT: bitcast |
920 | // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP0]]) |
921 | // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]*, [[A_T]]** [[TEMP0]] |
922 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* |
923 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) |
924 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* |
925 | // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use([[A_T]]* [[W0]]) [[NUW]] |
926 | // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]*, [[A_T]]** [[A]] |
927 | // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] |
928 | // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* |
929 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]]) |
930 | |
931 | // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]] |
932 | // CHECK-NEXT: [[W0:%.*]] = load [[A_T]]*, [[A_T]]** [[A]] |
933 | // CHECK-NEXT: store [[A_T]]* [[W0]], [[A_T]]** [[TEMP1]] |
934 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
935 | // CHECK-NEXT: bitcast |
936 | // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP1]]) |
937 | // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]*, [[A_T]]** [[TEMP1]] |
938 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* |
939 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) |
940 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* |
941 | // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use([[A_T]]* [[W0]]) [[NUW]] |
942 | // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]*, [[A_T]]** [[A]] |
943 | // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] |
944 | // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* |
945 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]]) |
946 | |
947 | // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]] |
948 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
949 | // CHECK-NEXT: bitcast |
950 | // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[A]]) |
951 | |
952 | // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]] |
953 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
954 | // CHECK-NEXT: bitcast |
955 | // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[A]]) |
956 | |
957 | // 'out' |
958 | // CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]] |
959 | // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[TEMP2]] |
960 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
961 | // CHECK-NEXT: bitcast |
962 | // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP2]]) |
963 | // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]*, [[A_T]]** [[TEMP2]] |
964 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* |
965 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) |
966 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* |
967 | // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]*, [[A_T]]** [[A]] |
968 | // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] |
969 | // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* |
970 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]]) |
971 | |
972 | // CHECK-NEXT: load |
973 | // CHECK-NEXT: bitcast |
974 | // CHECK-NEXT: llvm.objc.release |
975 | // CHECK-NEXT: bitcast |
976 | // CHECK-NEXT: call void @llvm.lifetime.end |
977 | // CHECK-NEXT: load |
978 | // CHECK-NEXT: bitcast |
979 | // CHECK-NEXT: llvm.objc.release |
980 | // CHECK-NEXT: ret void |
981 | } |
982 | |
983 | |
984 | // CHECK-LABEL: define void @test36 |
985 | void test36(id x) { |
986 | // CHECK: [[X:%.*]] = alloca i8* |
987 | |
988 | // CHECK: call i8* @llvm.objc.retain |
989 | // CHECK: call i8* @llvm.objc.retain |
990 | // CHECK: call i8* @llvm.objc.retain |
991 | id array[3] = { @"A", x, @"y" }; |
992 | |
993 | // CHECK: [[T0:%.*]] = load i8*, i8** [[X]] |
994 | // CHECK-NEXT: store i8* null, i8** [[X]] |
995 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
996 | x = 0; |
997 | |
998 | // CHECK: br label |
999 | // CHECK: call void @llvm.objc.release |
1000 | // CHECK: br i1 |
1001 | |
1002 | // CHECK: call void @llvm.objc.release |
1003 | // CHECK-NEXT: ret void |
1004 | } |
1005 | |
1006 | @class Test37; |
1007 | void test37(void) { |
1008 | extern void test37_helper(id *); |
1009 | Test37 *var; |
1010 | test37_helper(&var); |
1011 | |
1012 | // CHECK-LABEL: define void @test37() |
1013 | // CHECK: [[VAR:%.*]] = alloca [[TEST37:%.*]]*, |
1014 | // CHECK-NEXT: [[TEMP:%.*]] = alloca i8* |
1015 | // CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8* |
1016 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[VARPTR1]]) |
1017 | // CHECK-NEXT: store [[TEST37]]* null, [[TEST37]]** [[VAR]] |
1018 | |
1019 | // CHECK-NEXT: [[W0:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]] |
1020 | // CHECK-NEXT: [[W1:%.*]] = bitcast [[TEST37]]* [[W0]] to i8* |
1021 | // CHECK-NEXT: store i8* [[W1]], i8** [[TEMP]] |
1022 | // CHECK-NEXT: call void @test37_helper(i8** [[TEMP]]) |
1023 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]] |
1024 | // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST37]]* |
1025 | // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST37]]* [[T1]] to i8* |
1026 | // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retain(i8* [[T2]]) |
1027 | // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST37]]* |
1028 | // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[W1]]) [[NUW]] |
1029 | // CHECK-NEXT: [[T5:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]] |
1030 | // CHECK-NEXT: store [[TEST37]]* [[T4]], [[TEST37]]** [[VAR]] |
1031 | // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST37]]* [[T5]] to i8* |
1032 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T6]]) |
1033 | |
1034 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]] |
1035 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8* |
1036 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1037 | // CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8* |
1038 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[VARPTR2]]) |
1039 | // CHECK-NEXT: ret void |
1040 | } |
1041 | |
1042 | @interface Test43 @end |
1043 | @implementation Test43 |
1044 | - (id) test __attribute__((ns_returns_retained)) { |
1045 | extern id test43_produce(void); |
1046 | return test43_produce(); |
1047 | // CHECK: call i8* @test43_produce() |
1048 | // CHECK-NEXT: notail call i8* @llvm.objc.retainAutoreleasedReturnValue( |
1049 | // CHECK-NEXT: ret |
1050 | } |
1051 | @end |
1052 | |
1053 | @interface Test45 |
1054 | @property (retain) id x; |
1055 | @end |
1056 | @implementation Test45 |
1057 | @synthesize x; |
1058 | @end |
1059 | // CHECK: define internal i8* @"\01-[Test45 x]"( |
1060 | // CHECK: [[CALL:%.*]] = tail call i8* @objc_getProperty( |
1061 | // CHECK-NEXT: ret i8* [[CALL]] |
1062 | |
1063 | // rdar://problem/9315552 |
1064 | void test46(__weak id *wp, __weak volatile id *wvp) { |
1065 | extern id test46_helper(void); |
1066 | |
1067 | // TODO: this is sub-optimal, we should retain at the actual call site. |
1068 | |
1069 | // CHECK: [[T0:%.*]] = call i8* @test46_helper() |
1070 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1071 | // CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8 |
1072 | // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]]) |
1073 | // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retain(i8* [[T3]]) |
1074 | // CHECK-NEXT: store i8* [[T4]], i8** |
1075 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1076 | id x = *wp = test46_helper(); |
1077 | |
1078 | // CHECK: [[T0:%.*]] = call i8* @test46_helper() |
1079 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1080 | // CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8 |
1081 | // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]]) |
1082 | // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retain(i8* [[T3]]) |
1083 | // CHECK-NEXT: store i8* [[T4]], i8** |
1084 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1085 | id y = *wvp = test46_helper(); |
1086 | } |
1087 | |
1088 | // rdar://problem/9378887 |
1089 | void test47(void) { |
1090 | extern id test47_helper(void); |
1091 | id x = x = test47_helper(); |
1092 | |
1093 | // CHECK-LABEL: define void @test47() |
1094 | // CHECK: [[X:%.*]] = alloca i8* |
1095 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
1096 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
1097 | // CHECK-NEXT: store i8* null, i8** [[X]] |
1098 | // CHECK-NEXT: [[CALL:%.*]] = call i8* @test47_helper() |
1099 | // CHECK-NEXT: [[T0:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]]) |
1100 | // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] |
1101 | // CHECK-NEXT: store i8* [[T0]], i8** [[X]] |
1102 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1103 | // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) |
1104 | // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]] |
1105 | // CHECK-NEXT: store i8* [[T2]], i8** [[X]] |
1106 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T3]]) |
1107 | // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[X]] |
1108 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]]) |
1109 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
1110 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
1111 | // CHECK-NEXT: ret void |
1112 | } |
1113 | |
1114 | void test48(void) { |
1115 | extern id test48_helper(void); |
1116 | __weak id x = x = test48_helper(); |
1117 | // CHECK-LABEL: define void @test48() |
1118 | // CHECK: [[X:%.*]] = alloca i8* |
1119 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
1120 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
1121 | // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.initWeak(i8** [[X]], i8* null) |
1122 | // CHECK-NEXT: [[T1:%.*]] = call i8* @test48_helper() |
1123 | // CHECK-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) |
1124 | // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[X]], i8* [[T2]]) |
1125 | // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[X]], i8* [[T3]]) |
1126 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]]) |
1127 | // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[X]]) |
1128 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
1129 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
1130 | // CHECK-NEXT: ret void |
1131 | } |
1132 | |
1133 | void test49(void) { |
1134 | extern id test49_helper(void); |
1135 | __autoreleasing id x = x = test49_helper(); |
1136 | // CHECK-LABEL: define void @test49() |
1137 | // CHECK: [[X:%.*]] = alloca i8* |
1138 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
1139 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
1140 | // CHECK-NEXT: store i8* null, i8** [[X]] |
1141 | // CHECK-NEXT: [[CALL:%.*]] = call i8* @test49_helper() |
1142 | // CHECK-NEXT: [[T0:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]]) |
1143 | // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.autorelease(i8* [[T0]]) |
1144 | // CHECK-NEXT: store i8* [[T2]], i8** [[X]] |
1145 | // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]]) |
1146 | // CHECK-NEXT: store i8* [[T3]], i8** [[X]] |
1147 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
1148 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
1149 | // CHECK-NEXT: ret void |
1150 | } |
1151 | |
1152 | // rdar://9380136 |
1153 | id x(); |
1154 | void test50(id y) { |
1155 | ({x();}); |
1156 | // CHECK: [[T0:%.*]] = call i8* @llvm.objc.retain |
1157 | // CHECK: call void @llvm.objc.release |
1158 | } |
1159 | |
1160 | |
1161 | // rdar://9400762 |
1162 | struct CGPoint { |
1163 | float x; |
1164 | float y; |
1165 | }; |
1166 | typedef struct CGPoint CGPoint; |
1167 | |
1168 | @interface Foo |
1169 | @property (assign) CGPoint point; |
1170 | @end |
1171 | |
1172 | @implementation Foo |
1173 | @synthesize point; |
1174 | @end |
1175 | |
1176 | // rdar://problem/9400398 |
1177 | id test52(void) { |
1178 | id test52_helper(int) __attribute__((ns_returns_retained)); |
1179 | return ({ int x = 5; test52_helper(x); }); |
1180 | |
1181 | // CHECK-LABEL: define i8* @test52() |
1182 | // CHECK: [[X:%.*]] = alloca i32 |
1183 | // CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8* |
1184 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i32* [[X]] to i8* |
1185 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[XPTR1]]) |
1186 | // CHECK-NEXT: store i32 5, i32* [[X]], |
1187 | // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]], |
1188 | // CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]]) |
1189 | // CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]] |
1190 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i32* [[X]] to i8* |
1191 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[XPTR2]]) |
1192 | // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[TMPALLOCA]] |
1193 | // CHECK-NEXT: [[T3:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T2]]) |
1194 | // CHECK-NEXT: ret i8* [[T3]] |
1195 | } |
1196 | |
1197 | // rdar://problem/9400644 |
1198 | void test53(void) { |
1199 | id test53_helper(void); |
1200 | id x = ({ id y = test53_helper(); y; }); |
1201 | (void) x; |
1202 | // CHECK-LABEL: define void @test53() |
1203 | // CHECK: [[X:%.*]] = alloca i8*, |
1204 | // CHECK-NEXT: [[Y:%.*]] = alloca i8*, |
1205 | // CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*, |
1206 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
1207 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
1208 | // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8* |
1209 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]]) |
1210 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper() |
1211 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1212 | // CHECK-NEXT: store i8* [[T1]], i8** [[Y]], |
1213 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]], |
1214 | // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) |
1215 | // CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]] |
1216 | // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[Y]] |
1217 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]]) |
1218 | // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8* |
1219 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]]) |
1220 | // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[TMPALLOCA]] |
1221 | // CHECK-NEXT: store i8* [[T3]], i8** [[X]], |
1222 | // CHECK-NEXT: load i8*, i8** [[X]], |
1223 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] |
1224 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
1225 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
1226 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
1227 | // CHECK-NEXT: ret void |
1228 | } |
1229 | |
1230 | // <rdar://problem/9758798> |
1231 | // CHECK-LABEL: define void @test54(i32 %first, ...) |
1232 | void test54(int first, ...) { |
1233 | __builtin_va_list arglist; |
1234 | // CHECK: call void @llvm.va_start |
1235 | __builtin_va_start(arglist, first); |
1236 | // CHECK: call i8* @llvm.objc.retain |
1237 | id obj = __builtin_va_arg(arglist, id); |
1238 | // CHECK: call void @llvm.va_end |
1239 | __builtin_va_end(arglist); |
1240 | // CHECK: call void @llvm.objc.release |
1241 | // CHECK: ret void |
1242 | } |
1243 | |
1244 | // PR10228 |
1245 | @interface Test55Base @end |
1246 | @interface Test55 : Test55Base @end |
1247 | @implementation Test55 (Category) |
1248 | - (void) dealloc {} |
1249 | @end |
1250 | // CHECK: define internal void @"\01-[Test55(Category) dealloc]"( |
1251 | // CHECK-NOT: ret |
1252 | // CHECK: call void bitcast (i8* ({{%.*}}*, i8*, ...)* @objc_msgSendSuper2 to void ({{%.*}}*, i8*)*)( |
1253 | |
1254 | // rdar://problem/8024350 |
1255 | @protocol Test56Protocol |
1256 | + (id) make __attribute__((ns_returns_retained)); |
1257 | @end |
1258 | @interface Test56<Test56Protocol> @end |
1259 | @implementation Test56 |
1260 | // CHECK: define internal i8* @"\01+[Test56 make]"( |
1261 | + (id) make { |
1262 | extern id test56_helper(void); |
1263 | // CHECK: [[T0:%.*]] = call i8* @test56_helper() |
1264 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1265 | // CHECK-NEXT: ret i8* [[T1]] |
1266 | return test56_helper(); |
1267 | } |
1268 | @end |
1269 | void test56_test(void) { |
1270 | id x = [Test56 make]; |
1271 | // CHECK-LABEL: define void @test56_test() |
1272 | // CHECK: [[X:%.*]] = alloca i8*, align 8 |
1273 | // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* |
1274 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]]) |
1275 | // CHECK: [[T0:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)( |
1276 | // CHECK-NEXT: store i8* [[T0]], i8** [[X]] |
1277 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] |
1278 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
1279 | // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* |
1280 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]]) |
1281 | // CHECK-NEXT: ret void |
1282 | } |
1283 | |
1284 | // rdar://problem/9784964 |
1285 | @interface Test57 |
1286 | @property (nonatomic, strong) id strong; |
1287 | @property (nonatomic, weak) id weak; |
1288 | @property (nonatomic, unsafe_unretained) id unsafe; |
1289 | @end |
1290 | @implementation Test57 |
1291 | @synthesize strong, weak, unsafe; |
1292 | @end |
1293 | // CHECK: define internal i8* @"\01-[Test57 strong]"( |
1294 | // CHECK: [[T0:%.*]] = load [[TEST57:%.*]]*, [[TEST57:%.*]]** {{%.*}} |
1295 | // CHECK-NEXT: [[T1:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test57.strong" |
1296 | // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* |
1297 | // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]] |
1298 | // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** |
1299 | // CHECK-NEXT: [[T5:%.*]] = load i8*, i8** [[T4]] |
1300 | // CHECK-NEXT: ret i8* [[T5]] |
1301 | |
1302 | // CHECK: define internal i8* @"\01-[Test57 weak]"( |
1303 | // CHECK: [[T0:%.*]] = load [[TEST57]]*, [[TEST57]]** {{%.*}} |
1304 | // CHECK-NEXT: [[T1:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test57.weak" |
1305 | // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* |
1306 | // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]] |
1307 | // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** |
1308 | // CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T4]]) |
1309 | // CHECK-NEXT: [[T6:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T5]]) |
1310 | // CHECK-NEXT: ret i8* [[T6]] |
1311 | |
1312 | // CHECK: define internal i8* @"\01-[Test57 unsafe]"( |
1313 | // CHECK: [[T0:%.*]] = load [[TEST57]]*, [[TEST57]]** {{%.*}} |
1314 | // CHECK-NEXT: [[T1:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test57.unsafe" |
1315 | // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* |
1316 | // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]] |
1317 | // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** |
1318 | // CHECK-NEXT: [[T5:%.*]] = load i8*, i8** [[T4]] |
1319 | // CHECK-NEXT: ret i8* [[T5]] |
1320 | |
1321 | // rdar://problem/9842343 |
1322 | void test59(void) { |
1323 | extern id test59_getlock(void); |
1324 | extern void test59_body(void); |
1325 | @synchronized (test59_getlock()) { |
1326 | test59_body(); |
1327 | } |
1328 | |
1329 | // CHECK-LABEL: define void @test59() |
1330 | // CHECK: [[T0:%.*]] = call i8* @test59_getlock() |
1331 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1332 | // CHECK-NEXT: call i32 @objc_sync_enter(i8* [[T1]]) |
1333 | // CHECK-NEXT: call void @test59_body() |
1334 | // CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T1]]) |
1335 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1336 | // CHECK-NEXT: ret void |
1337 | } |
1338 | |
1339 | // Verify that we don't try to reclaim the result of performSelector. |
1340 | // rdar://problem/9887545 |
1341 | @interface Test61 |
1342 | - (id) performSelector: (SEL) selector; |
1343 | - (void) test61_void; |
1344 | - (id) test61_id; |
1345 | @end |
1346 | void test61(void) { |
1347 | // CHECK-LABEL: define void @test61() |
1348 | // CHECK: [[Y:%.*]] = alloca i8*, align 8 |
1349 | |
1350 | extern id test61_make(void); |
1351 | |
1352 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make() |
1353 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1354 | // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
1355 | // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
1356 | // CHECK-NEXT: [[T4:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T1]], i8* [[T3]], i8* [[T2]]) |
1357 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1358 | [test61_make() performSelector: @selector(test61_void)]; |
1359 | |
1360 | // CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8* |
1361 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]]) |
1362 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make() |
1363 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1364 | // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
1365 | // CHECK-NEXT: [[T3:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ |
1366 | // CHECK-NEXT: [[T4:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T1]], i8* [[T3]], i8* [[T2]]) |
1367 | // CHECK-NEXT: [[T5:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]]) |
1368 | // CHECK-NEXT: store i8* [[T5]], i8** [[Y]] |
1369 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) |
1370 | id y = [test61_make() performSelector: @selector(test61_id)]; |
1371 | |
1372 | // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] |
1373 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
1374 | // CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8* |
1375 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]]) |
1376 | // CHECK-NEXT: ret void |
1377 | } |
1378 | |
1379 | // rdar://problem/9891815 |
1380 | void test62(void) { |
1381 | // CHECK-LABEL: define void @test62() |
1382 | // CHECK: [[I:%.*]] = alloca i32, align 4 |
1383 | // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca i8* |
1384 | // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i1 |
1385 | extern id test62_make(void); |
1386 | extern void test62_body(void); |
1387 | |
1388 | // CHECK-NEXT: [[IPTR:%.*]] = bitcast i32* [[I]] to i8* |
1389 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[IPTR]]) |
1390 | // CHECK-NEXT: store i32 0, i32* [[I]], align 4 |
1391 | // CHECK-NEXT: br label |
1392 | |
1393 | // CHECK: [[T0:%.*]] = load i32, i32* [[I]], align 4 |
1394 | // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 20 |
1395 | // CHECK-NEXT: br i1 [[T1]], |
1396 | |
1397 | for (unsigned i = 0; i != 20; ++i) { |
1398 | // CHECK: [[T0:%.*]] = load i32, i32* [[I]], align 4 |
1399 | // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 |
1400 | // CHECK-NEXT: store i1 false, i1* [[CLEANUP_REQUIRED]] |
1401 | // CHECK-NEXT: br i1 [[T1]], |
1402 | // CHECK: [[T0:%.*]] = call i8* @test62_make() |
1403 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1404 | // CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_VALUE]] |
1405 | // CHECK-NEXT: store i1 true, i1* [[CLEANUP_REQUIRED]] |
1406 | // CHECK-NEXT: [[T2:%.*]] = icmp ne i8* [[T1]], null |
1407 | // CHECK-NEXT: br label |
1408 | // CHECK: [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ] |
1409 | // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_REQUIRED]] |
1410 | // CHECK-NEXT: br i1 [[T0]], |
1411 | // CHECK: [[T0:%.*]] = load i8*, i8** [[CLEANUP_VALUE]] |
1412 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) |
1413 | // CHECK-NEXT: br label |
1414 | // CHECK: br i1 [[COND]] |
1415 | // CHECK: call void @test62_body() |
1416 | // CHECK-NEXT: br label |
1417 | // CHECK: br label |
1418 | if (i != 0 && test62_make() != 0) |
1419 | test62_body(); |
1420 | } |
1421 | |
1422 | // CHECK: [[T0:%.*]] = load i32, i32* [[I]], align 4 |
1423 | // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 1 |
1424 | // CHECK-NEXT: store i32 [[T1]], i32* [[I]] |
1425 | // CHECK-NEXT: br label |
1426 | |
1427 | // CHECK: ret void |
1428 | } |
1429 | |
1430 | // rdar://9971982 |
1431 | @class NSString; |
1432 | |
1433 | @interface Person { |
1434 | NSString *name; |
1435 | } |
1436 | @property NSString *address; |
1437 | @end |
1438 | |
1439 | @implementation Person |
1440 | @synthesize address; |
1441 | @end |
1442 | // CHECK: tail call i8* @objc_getProperty |
1443 | // CHECK: call void @objc_setProperty |
1444 | |
1445 | // Verify that we successfully parse and preserve this attribute in |
1446 | // this position. |
1447 | @interface Test66 |
1448 | - (void) consume: (id __attribute__((ns_consumed))) ptr; |
1449 | @end |
1450 | void test66(void) { |
1451 | extern Test66 *test66_receiver(void); |
1452 | extern id test66_arg(void); |
1453 | [test66_receiver() consume: test66_arg()]; |
1454 | } |
1455 | // CHECK-LABEL: define void @test66() |
1456 | // CHECK: [[T0:%.*]] = call [[TEST66:%.*]]* @test66_receiver() |
1457 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST66]]* [[T0]] to i8* |
1458 | // CHECK-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) |
1459 | // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST66]]* |
1460 | // CHECK-NEXT: [[T4:%.*]] = call i8* @test66_arg() |
1461 | // CHECK-NEXT: [[T5:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]]) |
1462 | // CHECK-NEXT: [[T6:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES |
1463 | // CHECK-NEXT: [[T7:%.*]] = bitcast [[TEST66]]* [[T3]] to i8* |
1464 | // CHECK-NEXT: [[SIX:%.*]] = icmp eq i8* [[T7]], null |
1465 | // CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label [[CALL:%.*]] |
1466 | // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]]) |
1467 | // CHECK-NEXT: br label [[CONT:%.*]] |
1468 | // CHECK: call void @llvm.objc.release(i8* [[T5]]) [[NUW]] |
1469 | // CHECK-NEXT: br label [[CONT:%.*]] |
1470 | // CHECK: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8* |
1471 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T8]]) |
1472 | // CHECK-NEXT: ret void |
1473 | |
1474 | // rdar://problem/9953540 |
1475 | Class test67_helper(void); |
1476 | void test67(void) { |
1477 | Class cl = test67_helper(); |
1478 | } |
1479 | // CHECK-LABEL: define void @test67() |
1480 | // CHECK: [[CL:%.*]] = alloca i8*, align 8 |
1481 | // CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8* |
1482 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CLPTR1]]) |
1483 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper() |
1484 | // CHECK-NEXT: store i8* [[T0]], i8** [[CL]], align 8 |
1485 | // CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8* |
1486 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CLPTR2]]) |
1487 | // CHECK-NEXT: ret void |
1488 | |
1489 | Class test68_helper(void); |
1490 | void test68(void) { |
1491 | __strong Class cl = test67_helper(); |
1492 | } |
1493 | // CHECK-LABEL: define void @test68() |
1494 | // CHECK: [[CL:%.*]] = alloca i8*, align 8 |
1495 | // CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8* |
1496 | // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CLPTR1]]) |
1497 | // CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper() |
1498 | // CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]]) |
1499 | // CHECK-NEXT: store i8* [[T1]], i8** [[CL]], align 8 |
1500 | // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[CL]] |
1501 | // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]]) |
1502 | // CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8* |
1503 | // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CLPTR2]]) |
1504 | // CHECK-NEXT: ret void |
1505 | |
1506 | // rdar://problem/10564852 |
1507 | @interface Test69 @end |
1508 | @implementation Test69 |
1509 | - (id) foo { return self; } |
1510 | @end |
1511 | // CHECK: define internal i8* @"\01-[Test69 foo]"( |
1512 | // CHECK: [[SELF:%.*]] = alloca [[TEST69:%.*]]*, align 8 |
1513 | // CHECK: [[T0:%.*]] = load [[TEST69]]*, [[TEST69]]** [[SELF]], align 8 |
1514 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8* |
1515 | // CHECK-NEXT: ret i8* [[T1]] |
1516 | |
1517 | // rdar://problem/10907547 |
1518 | void test70(id i) { |
1519 | // CHECK-LABEL: define void @test70 |
1520 | // CHECK: store i8* null, i8** |
1521 | // CHECK: store i8* null, i8** |
1522 | // CHECK: [[ID:%.*]] = call i8* @llvm.objc.retain(i8* |
1523 | // CHECK: store i8* [[ID]], i8** |
1524 | id x[3] = { |
1525 | [2] = i |
1526 | }; |
1527 | } |
1528 | |
1529 | // Be sure that we emit lifetime intrinsics only after dtors |
1530 | struct AggDtor { |
1531 | char cs[40]; |
1532 | id x; |
1533 | }; |
1534 | |
1535 | struct AggDtor getAggDtor(void); |
1536 | |
1537 | // CHECK-LABEL: define void @test71 |
1538 | void test71(void) { |
1539 | // FIXME: It would be nice if the __destructor_8_s40 for the first call (and |
1540 | // the following lifetime.end) came before the second call. |
1541 | // |
1542 | // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8* |
1543 | // CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]]) |
1544 | // CHECK: call void @getAggDtor(%struct.AggDtor* sret %[[TMP1]]) |
1545 | // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8* |
1546 | // CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]]) |
1547 | // CHECK: call void @getAggDtor(%struct.AggDtor* sret %[[TMP2]]) |
1548 | // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2]] to i8** |
1549 | // CHECK: call void @__destructor_8_s40(i8** %[[T]]) |
1550 | // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8* |
1551 | // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]]) |
1552 | // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1]] to i8** |
1553 | // CHECK: call void @__destructor_8_s40(i8** %[[T]]) |
1554 | // CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8* |
1555 | // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]]) |
1556 | getAggDtor(); |
1557 | getAggDtor(); |
1558 | } |
1559 | |
1560 | // ARC-ALIEN: attributes [[NLB]] = { nonlazybind } |
1561 | // ARC-NATIVE: attributes [[NLB]] = { nonlazybind } |
1562 | // CHECK: attributes [[NUW]] = { nounwind } |
1563 | |