xref: /aosp_15_r20/external/clang/test/CodeGenObjC/arc-blocks.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
2*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT %s
3*67e74705SXin Li
4*67e74705SXin Li// This shouldn't crash.
5*67e74705SXin Livoid test0(id (^maker)(void)) {
6*67e74705SXin Li  maker();
7*67e74705SXin Li}
8*67e74705SXin Li
9*67e74705SXin Liint (^test1(int x))(void) {
10*67e74705SXin Li  // CHECK-LABEL:    define i32 ()* @test1(
11*67e74705SXin Li  // CHECK:      [[X:%.*]] = alloca i32,
12*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
13*67e74705SXin Li  // CHECK-NEXT: store i32 {{%.*}}, i32* [[X]]
14*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()*
15*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8*
16*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) [[NUW:#[0-9]+]]
17*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()*
18*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8*
19*67e74705SXin Li  // CHECK-NEXT: [[T5:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) [[NUW]]
20*67e74705SXin Li  // CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()*
21*67e74705SXin Li  // CHECK-NEXT: ret i32 ()* [[T6]]
22*67e74705SXin Li  return ^{ return x; };
23*67e74705SXin Li}
24*67e74705SXin Li
25*67e74705SXin Livoid test2(id x) {
26*67e74705SXin Li// CHECK-LABEL:    define void @test2(
27*67e74705SXin Li// CHECK:      [[X:%.*]] = alloca i8*,
28*67e74705SXin Li// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
29*67e74705SXin Li// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
30*67e74705SXin Li// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
31*67e74705SXin Li// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
32*67e74705SXin Li// CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
33*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]],
34*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
35*67e74705SXin Li// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
36*67e74705SXin Li// CHECK-NEXT: bitcast
37*67e74705SXin Li// CHECK-NEXT: call void @test2_helper(
38*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOTREL]]
39*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
40*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
41*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
42*67e74705SXin Li// CHECK-NEXT: ret void
43*67e74705SXin Li  extern void test2_helper(id (^)(void));
44*67e74705SXin Li  test2_helper(^{ return x; });
45*67e74705SXin Li
46*67e74705SXin Li// CHECK-LABEL:    define internal void @__copy_helper_block_(i8*, i8*) #{{[0-9]+}} {
47*67e74705SXin Li// CHECK:      [[T0:%.*]] = load i8*, i8**
48*67e74705SXin Li// CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
49*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8**
50*67e74705SXin Li// CHECK-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
51*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[SRC]], i32 0, i32 5
52*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
53*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
54*67e74705SXin Li// CHECK-NEXT: ret void
55*67e74705SXin Li
56*67e74705SXin Li// CHECK-LABEL:    define internal void @__destroy_helper_block_(i8*) #{{[0-9]+}} {
57*67e74705SXin Li// CHECK:      [[T0:%.*]] = load i8*, i8**
58*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
59*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5
60*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[T2]]
61*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T3]])
62*67e74705SXin Li// CHECK-NEXT: ret void
63*67e74705SXin Li}
64*67e74705SXin Li
65*67e74705SXin Livoid test3(void (^sink)(id*)) {
66*67e74705SXin Li  __strong id strong;
67*67e74705SXin Li  sink(&strong);
68*67e74705SXin Li
69*67e74705SXin Li  // CHECK-LABEL:    define void @test3(
70*67e74705SXin Li  // CHECK:      [[SINK:%.*]] = alloca void (i8**)*
71*67e74705SXin Li  // CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
72*67e74705SXin Li  // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
73*67e74705SXin Li  // CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8*
74*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_retain(
75*67e74705SXin Li  // CHECK-NEXT: bitcast i8*
76*67e74705SXin Li  // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
77*67e74705SXin Li  // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
78*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
79*67e74705SXin Li  // CHECK-NEXT: store i8* null, i8** [[STRONG]]
80*67e74705SXin Li
81*67e74705SXin Li  // CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
82*67e74705SXin Li  // CHECK-NEXT: bitcast
83*67e74705SXin Li  // CHECK-NEXT: getelementptr
84*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = bitcast
85*67e74705SXin Li  // CHECK-NEXT: [[V:%.*]] = load i8*, i8** [[STRONG]]
86*67e74705SXin Li  // CHECK-NEXT: store i8* [[V]], i8** [[TEMP]]
87*67e74705SXin Li  // CHECK-NEXT: [[F0:%.*]] = load i8*, i8**
88*67e74705SXin Li  // CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)*
89*67e74705SXin Li  // CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP]])
90*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]]
91*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
92*67e74705SXin Li  // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[V]]) [[NUW]]
93*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[STRONG]]
94*67e74705SXin Li  // CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]]
95*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
96*67e74705SXin Li
97*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[STRONG]]
98*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
99*67e74705SXin Li  // CHECK-NEXT: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
100*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])
101*67e74705SXin Li
102*67e74705SXin Li  // CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
103*67e74705SXin Li  // CHECK-NEXT: bitcast
104*67e74705SXin Li  // CHECK-NEXT: call void @objc_release
105*67e74705SXin Li  // CHECK-NEXT: ret void
106*67e74705SXin Li
107*67e74705SXin Li}
108*67e74705SXin Li
109*67e74705SXin Livoid test4(void) {
110*67e74705SXin Li  id test4_source(void);
111*67e74705SXin Li  void test4_helper(void (^)(void));
112*67e74705SXin Li  __block id var = test4_source();
113*67e74705SXin Li  test4_helper(^{ var = 0; });
114*67e74705SXin Li
115*67e74705SXin Li  // CHECK-LABEL:    define void @test4()
116*67e74705SXin Li  // CHECK:      [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
117*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
118*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 2
119*67e74705SXin Li  // 0x02000000 - has copy/dispose helpers strong
120*67e74705SXin Li  // CHECK-NEXT: store i32 838860800, i32* [[T0]]
121*67e74705SXin Li  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
122*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source()
123*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
124*67e74705SXin Li  // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
125*67e74705SXin Li  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
126*67e74705SXin Li  // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
127*67e74705SXin Li  // CHECK:      store i32 -1040187392,
128*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
129*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8**
130*67e74705SXin Li  // CHECK:      call void @test4_helper(
131*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
132*67e74705SXin Li  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
133*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]]
134*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
135*67e74705SXin Li  // CHECK: ret void
136*67e74705SXin Li
137*67e74705SXin Li  // CHECK-LABEL:    define internal void @__Block_byref_object_copy_(i8*, i8*) #{{[0-9]+}} {
138*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
139*67e74705SXin Li  // CHECK-NEXT: load i8*, i8**
140*67e74705SXin Li  // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
141*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
142*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[T1]]
143*67e74705SXin Li  // CHECK-NEXT: store i8* [[T2]], i8** [[T0]]
144*67e74705SXin Li  // CHECK-NEXT: store i8* null, i8** [[T1]]
145*67e74705SXin Li
146*67e74705SXin Li  // CHECK-LABEL:    define internal void @__Block_byref_object_dispose_(i8*) #{{[0-9]+}} {
147*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
148*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
149*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
150*67e74705SXin Li
151*67e74705SXin Li  // CHECK-LABEL:    define internal void @__test4_block_invoke
152*67e74705SXin Li  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
153*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align 8
154*67e74705SXin Li  // CHECK-NEXT: store i8* null, i8** [[SLOT]],
155*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
156*67e74705SXin Li  // CHECK-NEXT: ret void
157*67e74705SXin Li
158*67e74705SXin Li  // CHECK-LABEL:    define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
159*67e74705SXin Li  // CHECK:      call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
160*67e74705SXin Li
161*67e74705SXin Li  // CHECK-LABEL:    define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
162*67e74705SXin Li  // CHECK:      call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
163*67e74705SXin Li}
164*67e74705SXin Li
165*67e74705SXin Livoid test5(void) {
166*67e74705SXin Li  extern id test5_source(void);
167*67e74705SXin Li  void test5_helper(void (^)(void));
168*67e74705SXin Li  __unsafe_unretained id var = test5_source();
169*67e74705SXin Li  test5_helper(^{ (void) var; });
170*67e74705SXin Li
171*67e74705SXin Li  // CHECK-LABEL:    define void @test5()
172*67e74705SXin Li  // CHECK:      [[VAR:%.*]] = alloca i8*
173*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
174*67e74705SXin Li  // CHECK-NEXT: [[VARPTR1:%.*]] = bitcast i8** [[VAR]] to i8*
175*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[VARPTR1]])
176*67e74705SXin Li  // CHECK: [[T0:%.*]] = call i8* @test5_source()
177*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
178*67e74705SXin Li  // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
179*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
180*67e74705SXin Li  // 0x40800000 - has signature but no copy/dispose, as well as BLOCK_HAS_EXTENDED_LAYOUT
181*67e74705SXin Li  // CHECK:      store i32 -1073741824, i32*
182*67e74705SXin Li  // CHECK:      [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
183*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[VAR]]
184*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]
185*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
186*67e74705SXin Li  // CHECK: call void @test5_helper
187*67e74705SXin Li  // CHECK-NEXT: [[VARPTR2:%.*]] = bitcast i8** [[VAR]] to i8*
188*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[VARPTR2]])
189*67e74705SXin Li  // CHECK-NEXT: ret void
190*67e74705SXin Li}
191*67e74705SXin Li
192*67e74705SXin Livoid test6(void) {
193*67e74705SXin Li  id test6_source(void);
194*67e74705SXin Li  void test6_helper(void (^)(void));
195*67e74705SXin Li  __block __weak id var = test6_source();
196*67e74705SXin Li  test6_helper(^{ var = 0; });
197*67e74705SXin Li
198*67e74705SXin Li  // CHECK-LABEL:    define void @test6()
199*67e74705SXin Li  // CHECK:      [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
200*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
201*67e74705SXin Li  // CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
202*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 48, i8* [[VARPTR1]])
203*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 2
204*67e74705SXin Li  // 0x02000000 - has copy/dispose helpers weak
205*67e74705SXin Li  // CHECK-NEXT: store i32 1107296256, i32* [[T0]]
206*67e74705SXin Li  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
207*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source()
208*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
209*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]])
210*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
211*67e74705SXin Li  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
212*67e74705SXin Li  // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
213*67e74705SXin Li  // CHECK:      store i32 -1040187392,
214*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
215*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8**
216*67e74705SXin Li  // CHECK:      call void @test6_helper(
217*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
218*67e74705SXin Li  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
219*67e74705SXin Li  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
220*67e74705SXin Li  // CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
221*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.end(i64 48, i8* [[VARPTR2]])
222*67e74705SXin Li  // CHECK-NEXT: ret void
223*67e74705SXin Li
224*67e74705SXin Li  // CHECK-LABEL:    define internal void @__Block_byref_object_copy_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
225*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
226*67e74705SXin Li  // CHECK-NEXT: load i8*, i8**
227*67e74705SXin Li  // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
228*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
229*67e74705SXin Li  // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
230*67e74705SXin Li
231*67e74705SXin Li  // CHECK-LABEL:    define internal void @__Block_byref_object_dispose_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
232*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
233*67e74705SXin Li  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
234*67e74705SXin Li
235*67e74705SXin Li  // CHECK-LABEL:    define internal void @__test6_block_invoke
236*67e74705SXin Li  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
237*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null)
238*67e74705SXin Li  // CHECK-NEXT: ret void
239*67e74705SXin Li
240*67e74705SXin Li  // CHECK-LABEL:    define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
241*67e74705SXin Li  // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
242*67e74705SXin Li  // CHECK:      call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
243*67e74705SXin Li
244*67e74705SXin Li  // CHECK-LABEL:    define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
245*67e74705SXin Li  // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
246*67e74705SXin Li  // CHECK:      call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
247*67e74705SXin Li}
248*67e74705SXin Li
249*67e74705SXin Livoid test7(void) {
250*67e74705SXin Li  id test7_source(void);
251*67e74705SXin Li  void test7_helper(void (^)(void));
252*67e74705SXin Li  void test7_consume(id);
253*67e74705SXin Li  __weak id var = test7_source();
254*67e74705SXin Li  test7_helper(^{ test7_consume(var); });
255*67e74705SXin Li
256*67e74705SXin Li  // CHECK-LABEL:    define void @test7()
257*67e74705SXin Li  // CHECK:      [[VAR:%.*]] = alloca i8*,
258*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
259*67e74705SXin Li  // CHECK:      [[T0:%.*]] = call i8* @test7_source()
260*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
261*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]])
262*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
263*67e74705SXin Li  // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
264*67e74705SXin Li  // CHECK:      store i32 -1040187392,
265*67e74705SXin Li  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
266*67e74705SXin Li  // CHECK-NEXT: call void @objc_copyWeak(i8** [[SLOT]], i8** [[VAR]])
267*67e74705SXin Li  // CHECK:      call void @test7_helper(
268*67e74705SXin Li  // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})
269*67e74705SXin Li  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
270*67e74705SXin Li  // CHECK: ret void
271*67e74705SXin Li
272*67e74705SXin Li  // CHECK-LABEL:    define internal void @__test7_block_invoke
273*67e74705SXin Li  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* {{%.*}}, i32 0, i32 5
274*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[SLOT]])
275*67e74705SXin Li  // CHECK-NEXT: call void @test7_consume(i8* [[T0]])
276*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
277*67e74705SXin Li  // CHECK: ret void
278*67e74705SXin Li
279*67e74705SXin Li  // CHECK-LABEL:    define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
280*67e74705SXin Li  // CHECK:      getelementptr
281*67e74705SXin Li  // CHECK-NEXT: getelementptr
282*67e74705SXin Li  // CHECK-NEXT: call void @objc_copyWeak(
283*67e74705SXin Li
284*67e74705SXin Li  // CHECK-LABEL:    define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
285*67e74705SXin Li  // CHECK:      getelementptr
286*67e74705SXin Li  // CHECK-NEXT: call void @objc_destroyWeak(
287*67e74705SXin Li}
288*67e74705SXin Li
289*67e74705SXin Li@interface Test8 @end
290*67e74705SXin Li@implementation Test8
291*67e74705SXin Li- (void) test {
292*67e74705SXin Li// CHECK:    define internal void @"\01-[Test8 test]"
293*67e74705SXin Li// CHECK:      [[SELF:%.*]] = alloca [[TEST8:%.*]]*,
294*67e74705SXin Li// CHECK-NEXT: alloca i8*
295*67e74705SXin Li// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
296*67e74705SXin Li// CHECK: store
297*67e74705SXin Li// CHECK-NEXT: store
298*67e74705SXin Li// CHECK:      [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
299*67e74705SXin Li// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
300*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]*, [[TEST8]]** [[SELF]],
301*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
302*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
303*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]*
304*67e74705SXin Li// CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]]
305*67e74705SXin Li// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
306*67e74705SXin Li// CHECK: call void @test8_helper(
307*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]*, [[TEST8]]** [[D0]]
308*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
309*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T2]])
310*67e74705SXin Li// CHECK: ret void
311*67e74705SXin Li
312*67e74705SXin Li  extern void test8_helper(void (^)(void));
313*67e74705SXin Li  test8_helper(^{ (void) self; });
314*67e74705SXin Li}
315*67e74705SXin Li@end
316*67e74705SXin Li
317*67e74705SXin Liid test9(void) {
318*67e74705SXin Li  typedef id __attribute__((ns_returns_retained)) blocktype(void);
319*67e74705SXin Li  extern void test9_consume_block(blocktype^);
320*67e74705SXin Li  return ^blocktype {
321*67e74705SXin Li      extern id test9_produce(void);
322*67e74705SXin Li      return test9_produce();
323*67e74705SXin Li  }();
324*67e74705SXin Li
325*67e74705SXin Li// CHECK-LABEL:    define i8* @test9(
326*67e74705SXin Li// CHECK:      load i8*, i8** getelementptr
327*67e74705SXin Li// CHECK-NEXT: bitcast i8*
328*67e74705SXin Li// CHECK-NEXT: call i8*
329*67e74705SXin Li// CHECK-NEXT: tail call i8* @objc_autoreleaseReturnValue
330*67e74705SXin Li// CHECK-NEXT: ret i8*
331*67e74705SXin Li
332*67e74705SXin Li// CHECK:      call i8* @test9_produce()
333*67e74705SXin Li// CHECK-NEXT: call i8* @objc_retain
334*67e74705SXin Li// CHECK-NEXT: ret i8*
335*67e74705SXin Li}
336*67e74705SXin Li
337*67e74705SXin Li// rdar://problem/9814099
338*67e74705SXin Li// Test that we correctly initialize __block variables
339*67e74705SXin Li// when the initialization captures the variable.
340*67e74705SXin Livoid test10a(void) {
341*67e74705SXin Li  __block void (^block)(void) = ^{ block(); };
342*67e74705SXin Li  // CHECK-LABEL:    define void @test10a()
343*67e74705SXin Li  // CHECK:      [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
344*67e74705SXin Li
345*67e74705SXin Li  // Zero-initialization before running the initializer.
346*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
347*67e74705SXin Li  // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
348*67e74705SXin Li
349*67e74705SXin Li  // Run the initializer as an assignment.
350*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
351*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
352*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
353*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
354*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
355*67e74705SXin Li  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6
356*67e74705SXin Li  // CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
357*67e74705SXin Li  // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
358*67e74705SXin Li  // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
359*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T7]])
360*67e74705SXin Li
361*67e74705SXin Li  // Destroy at end of function.
362*67e74705SXin Li  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
363*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
364*67e74705SXin Li  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
365*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
366*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
367*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
368*67e74705SXin Li  // CHECK: ret void
369*67e74705SXin Li}
370*67e74705SXin Li
371*67e74705SXin Li// <rdar://problem/10402698>: do this copy and dispose with
372*67e74705SXin Li// objc_retainBlock/release instead of _Block_object_assign/destroy.
373*67e74705SXin Li// We can also use _Block_object_assign/destroy with
374*67e74705SXin Li// BLOCK_FIELD_IS_BLOCK as long as we don't pass BLOCK_BYREF_CALLER.
375*67e74705SXin Li
376*67e74705SXin Li// CHECK-LABEL: define internal void @__Block_byref_object_copy_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
377*67e74705SXin Li// CHECK:      [[D0:%.*]] = load i8*, i8** {{%.*}}
378*67e74705SXin Li// CHECK-NEXT: [[D1:%.*]] = bitcast i8* [[D0]] to [[BYREF_T]]*
379*67e74705SXin Li// CHECK-NEXT: [[D2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[D1]], i32 0, i32 6
380*67e74705SXin Li// CHECK-NEXT: [[S0:%.*]] = load i8*, i8** {{%.*}}
381*67e74705SXin Li// CHECK-NEXT: [[S1:%.*]] = bitcast i8* [[S0]] to [[BYREF_T]]*
382*67e74705SXin Li// CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[S1]], i32 0, i32 6
383*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[S2]], align 8
384*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
385*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
386*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
387*67e74705SXin Li// CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8
388*67e74705SXin Li// CHECK: ret void
389*67e74705SXin Li
390*67e74705SXin Li// CHECK-LABEL: define internal void @__Block_byref_object_dispose_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
391*67e74705SXin Li// CHECK:      [[T0:%.*]] = load i8*, i8** {{%.*}}
392*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]*
393*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T1]], i32 0, i32 6
394*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = load void ()*, void ()** [[T2]]
395*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
396*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T4]])
397*67e74705SXin Li// CHECK-NEXT: ret void
398*67e74705SXin Li
399*67e74705SXin Li// Test that we correctly assign to __block variables when the
400*67e74705SXin Li// assignment captures the variable.
401*67e74705SXin Livoid test10b(void) {
402*67e74705SXin Li  __block void (^block)(void);
403*67e74705SXin Li  block = ^{ block(); };
404*67e74705SXin Li
405*67e74705SXin Li  // CHECK-LABEL:    define void @test10b()
406*67e74705SXin Li  // CHECK:      [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
407*67e74705SXin Li
408*67e74705SXin Li  // Zero-initialize.
409*67e74705SXin Li  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
410*67e74705SXin Li  // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
411*67e74705SXin Li
412*67e74705SXin Li  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
413*67e74705SXin Li
414*67e74705SXin Li  // The assignment.
415*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
416*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
417*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
418*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
419*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
420*67e74705SXin Li  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6
421*67e74705SXin Li  // CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
422*67e74705SXin Li  // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
423*67e74705SXin Li  // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
424*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T7]])
425*67e74705SXin Li
426*67e74705SXin Li  // Destroy at end of function.
427*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
428*67e74705SXin Li  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
429*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
430*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
431*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
432*67e74705SXin Li  // CHECK: ret void
433*67e74705SXin Li}
434*67e74705SXin Li
435*67e74705SXin Li// rdar://problem/10088932
436*67e74705SXin Livoid test11_helper(id);
437*67e74705SXin Livoid test11a(void) {
438*67e74705SXin Li  int x;
439*67e74705SXin Li  test11_helper(^{ (void) x; });
440*67e74705SXin Li
441*67e74705SXin Li  // CHECK-LABEL:    define void @test11a()
442*67e74705SXin Li  // CHECK:      [[X:%.*]] = alloca i32, align 4
443*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
444*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
445*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
446*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
447*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
448*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
449*67e74705SXin Li  // CHECK-NEXT: call void @test11_helper(i8* [[T4]])
450*67e74705SXin Li  // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*
451*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T5]])
452*67e74705SXin Li  // CHECK: ret void
453*67e74705SXin Li}
454*67e74705SXin Livoid test11b(void) {
455*67e74705SXin Li  int x;
456*67e74705SXin Li  id b = ^{ (void) x; };
457*67e74705SXin Li
458*67e74705SXin Li  // CHECK-LABEL:    define void @test11b()
459*67e74705SXin Li  // CHECK:      [[X:%.*]] = alloca i32, align 4
460*67e74705SXin Li  // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8
461*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
462*67e74705SXin Li  // CHECK:      [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
463*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
464*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
465*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
466*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
467*67e74705SXin Li  // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8
468*67e74705SXin Li  // CHECK-NEXT: [[T5:%.*]] = load i8*, i8** [[B]]
469*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T5]])
470*67e74705SXin Li  // CHECK: ret void
471*67e74705SXin Li}
472*67e74705SXin Li
473*67e74705SXin Li// rdar://problem/9979150
474*67e74705SXin Li@interface Test12
475*67e74705SXin Li@property (strong) void(^ablock)(void);
476*67e74705SXin Li@property (nonatomic, strong) void(^nblock)(void);
477*67e74705SXin Li@end
478*67e74705SXin Li@implementation Test12
479*67e74705SXin Li@synthesize ablock, nblock;
480*67e74705SXin Li// CHECK:    define internal void ()* @"\01-[Test12 ablock]"(
481*67e74705SXin Li// CHECK:    call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext true)
482*67e74705SXin Li
483*67e74705SXin Li// CHECK:    define internal void @"\01-[Test12 setAblock:]"(
484*67e74705SXin Li// CHECK:    call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true)
485*67e74705SXin Li
486*67e74705SXin Li// CHECK:    define internal void ()* @"\01-[Test12 nblock]"(
487*67e74705SXin Li// CHECK:    call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false)
488*67e74705SXin Li
489*67e74705SXin Li// CHECK:    define internal void @"\01-[Test12 setNblock:]"(
490*67e74705SXin Li// CHECK:    call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true)
491*67e74705SXin Li@end
492*67e74705SXin Li
493*67e74705SXin Li// rdar://problem/10131784
494*67e74705SXin Livoid test13(id x) {
495*67e74705SXin Li  extern void test13_helper(id);
496*67e74705SXin Li  extern void test13_use(void(^)(void));
497*67e74705SXin Li
498*67e74705SXin Li  void (^b)(void) = (x ? ^{test13_helper(x);} : 0);
499*67e74705SXin Li  test13_use(b);
500*67e74705SXin Li
501*67e74705SXin Li  // CHECK-LABEL:    define void @test13(
502*67e74705SXin Li  // CHECK:      [[X:%.*]] = alloca i8*, align 8
503*67e74705SXin Li  // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
504*67e74705SXin Li  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
505*67e74705SXin Li  // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
506*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
507*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
508*67e74705SXin Li  // CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8*
509*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BPTR1]])
510*67e74705SXin Li  // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
511*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8
512*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
513*67e74705SXin Li  // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]]
514*67e74705SXin Li  // CHECK-NEXT: br i1 [[T1]],
515*67e74705SXin Li
516*67e74705SXin Li  // CHECK-NOT:  br
517*67e74705SXin Li  // CHECK:      [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
518*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8
519*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
520*67e74705SXin Li  // CHECK-NEXT: store i8* [[T1]], i8** [[CAPTURE]], align 8
521*67e74705SXin Li  // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
522*67e74705SXin Li  // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
523*67e74705SXin Li  // CHECK-NEXT: br label
524*67e74705SXin Li  // CHECK:      br label
525*67e74705SXin Li  // CHECK:      [[T0:%.*]] = phi void ()*
526*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
527*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
528*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
529*67e74705SXin Li  // CHECK-NEXT: store void ()* [[T3]], void ()** [[B]], align 8
530*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]], align 8
531*67e74705SXin Li  // CHECK-NEXT: call void @test13_use(void ()* [[T0]])
532*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]
533*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
534*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
535*67e74705SXin Li  // CHECK-NEXT: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8*
536*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[BPTR2]])
537*67e74705SXin Li
538*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]]
539*67e74705SXin Li  // CHECK-NEXT: br i1 [[T0]]
540*67e74705SXin Li  // CHECK:      [[T0:%.*]] = load i8*, i8** [[CLEANUP_ADDR]]
541*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
542*67e74705SXin Li  // CHECK-NEXT: br label
543*67e74705SXin Li
544*67e74705SXin Li  // CHECK:      [[T0:%.*]] = load i8*, i8** [[X]]
545*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
546*67e74705SXin Li  // CHECK-NEXT: ret void
547*67e74705SXin Li}
548*67e74705SXin Li
549*67e74705SXin Li// <rdar://problem/10907510>
550*67e74705SXin Livoid test14() {
551*67e74705SXin Li  void (^const x[1])(void) = { ^{} };
552*67e74705SXin Li}
553*67e74705SXin Li
554*67e74705SXin Li// rdar://11149025
555*67e74705SXin Li// Don't make invalid ASTs and crash.
556*67e74705SXin Livoid test15_helper(void (^block)(void), int x);
557*67e74705SXin Livoid test15(int a) {
558*67e74705SXin Li  test15_helper(^{ (void) a; }, ({ a; }));
559*67e74705SXin Li}
560*67e74705SXin Li
561*67e74705SXin Li// rdar://11016025
562*67e74705SXin Livoid test16() {
563*67e74705SXin Li  void (^BLKVAR)(void) = ^{ BLKVAR(); };
564*67e74705SXin Li
565*67e74705SXin Li  // CHECK-LABEL: define void @test16(
566*67e74705SXin Li  // CHECK: [[BLKVAR:%.*]]  = alloca void ()*, align 8
567*67e74705SXin Li  // CHECK-NEXT:  [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
568*67e74705SXin Li  // CHECK-NEXT:  [[BLKVARPTR1:%.*]] = bitcast void ()** [[BLKVAR]] to i8*
569*67e74705SXin Li  // CHECK-NEXT:  call void @llvm.lifetime.start(i64 8, i8* [[BLKVARPTR1]])
570*67e74705SXin Li  // CHECK-NEXT:  [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
571*67e74705SXin Li  // CHECK-NEXT:  store void ()* null, void ()** [[BLKVAR]], align 8
572*67e74705SXin Li}
573*67e74705SXin Li
574*67e74705SXin Li// rdar://12151005
575*67e74705SXin Li//
576*67e74705SXin Li// This is an intentional exception to our conservative jump-scope
577*67e74705SXin Li// checking for full-expressions containing block literals with
578*67e74705SXin Li// non-trivial cleanups: if the block literal appears in the operand
579*67e74705SXin Li// of a return statement, there's no need to extend its lifetime.
580*67e74705SXin Liid (^test17(id self, int which))(void) {
581*67e74705SXin Li  switch (which) {
582*67e74705SXin Li  case 1: return ^{ return self; };
583*67e74705SXin Li  case 0: return ^{ return self; };
584*67e74705SXin Li  }
585*67e74705SXin Li  return (void*) 0;
586*67e74705SXin Li}
587*67e74705SXin Li// CHECK-LABEL:    define i8* ()* @test17(
588*67e74705SXin Li// CHECK:      [[RET:%.*]] = alloca i8* ()*, align
589*67e74705SXin Li// CHECK-NEXT: [[SELF:%.*]] = alloca i8*,
590*67e74705SXin Li// CHECK:      [[B0:%.*]] = alloca [[BLOCK:<.*>]], align
591*67e74705SXin Li// CHECK:      [[B1:%.*]] = alloca [[BLOCK]], align
592*67e74705SXin Li// CHECK:      [[T0:%.*]] = call i8* @objc_retain(i8*
593*67e74705SXin Li// CHECK-NEXT: store i8* [[T0]], i8** [[SELF]], align
594*67e74705SXin Li// CHECK-NOT:  objc_retain
595*67e74705SXin Li// CHECK-NOT:  objc_release
596*67e74705SXin Li// CHECK:      [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B0]], i32 0, i32 5
597*67e74705SXin Li// CHECK-NOT:  objc_retain
598*67e74705SXin Li// CHECK-NOT:  objc_release
599*67e74705SXin Li// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B0]], i32 0, i32 5
600*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[SELF]], align
601*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
602*67e74705SXin Li// CHECK-NEXT: store i8* [[T2]], i8** [[T0]],
603*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B0]] to i8* ()*
604*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8*
605*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
606*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()*
607*67e74705SXin Li// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]]
608*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[DESTROY]]
609*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T0]])
610*67e74705SXin Li// CHECK-NEXT: store i32
611*67e74705SXin Li// CHECK-NEXT: br label
612*67e74705SXin Li// CHECK-NOT:  objc_retain
613*67e74705SXin Li// CHECK-NOT:  objc_release
614*67e74705SXin Li// CHECK:      [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B1]], i32 0, i32 5
615*67e74705SXin Li// CHECK-NOT:  objc_retain
616*67e74705SXin Li// CHECK-NOT:  objc_release
617*67e74705SXin Li// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B1]], i32 0, i32 5
618*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[SELF]], align
619*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
620*67e74705SXin Li// CHECK-NEXT: store i8* [[T2]], i8** [[T0]],
621*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B1]] to i8* ()*
622*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8*
623*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
624*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()*
625*67e74705SXin Li// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]]
626*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[DESTROY]]
627*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T0]])
628*67e74705SXin Li// CHECK-NEXT: store i32
629*67e74705SXin Li// CHECK-NEXT: br label
630*67e74705SXin Li
631*67e74705SXin Livoid test18(id x) {
632*67e74705SXin Li// CHECK-UNOPT-LABEL:    define void @test18(
633*67e74705SXin Li// CHECK-UNOPT:      [[X:%.*]] = alloca i8*,
634*67e74705SXin Li// CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
635*67e74705SXin Li// CHECK-UNOPT-NEXT: store i8* null, i8** [[X]]
636*67e74705SXin Li// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]],
637*67e74705SXin Li// CHECK-UNOPT-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
638*67e74705SXin Li// CHECK-UNOPT:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
639*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8** [[X]],
640*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
641*67e74705SXin Li// CHECK-UNOPT-NEXT: store i8* [[T1]], i8** [[SLOT]],
642*67e74705SXin Li// CHECK-UNOPT-NEXT: bitcast
643*67e74705SXin Li// CHECK-UNOPT-NEXT: call void @test18_helper(
644*67e74705SXin Li// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) [[NUW:#[0-9]+]]
645*67e74705SXin Li// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) [[NUW]]
646*67e74705SXin Li// CHECK-UNOPT-NEXT: ret void
647*67e74705SXin Li  extern void test18_helper(id (^)(void));
648*67e74705SXin Li  test18_helper(^{ return x; });
649*67e74705SXin Li
650*67e74705SXin Li// CHECK-UNOPT-LABEL:    define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
651*67e74705SXin Li// CHECK-UNOPT:      [[T0:%.*]] = load i8*, i8**
652*67e74705SXin Li// CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
653*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8**
654*67e74705SXin Li// CHECK-UNOPT-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
655*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[SRC]], i32 0, i32 5
656*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T1:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[DST]], i32 0, i32 5
657*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T2:%.*]] = load i8*, i8** [[T0]]
658*67e74705SXin Li// CHECK-UNOPT-NEXT: store i8* null, i8** [[T1]]
659*67e74705SXin Li// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) [[NUW]]
660*67e74705SXin Li// CHECK-UNOPT-NEXT: ret void
661*67e74705SXin Li
662*67e74705SXin Li// CHECK-UNOPT-LABEL:    define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
663*67e74705SXin Li// CHECK-UNOPT:      [[T0:%.*]] = load i8*, i8**
664*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
665*67e74705SXin Li// CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5
666*67e74705SXin Li// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null)
667*67e74705SXin Li// CHECK-UNOPT-NEXT: ret void
668*67e74705SXin Li}
669*67e74705SXin Li
670*67e74705SXin Li// rdar://13588325
671*67e74705SXin Livoid test19_sink(void (^)(int));
672*67e74705SXin Livoid test19(void (^b)(void)) {
673*67e74705SXin Li// CHECK-LABEL:    define void @test19(
674*67e74705SXin Li//   Prologue.
675*67e74705SXin Li// CHECK:      [[B:%.*]] = alloca void ()*,
676*67e74705SXin Li// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
677*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
678*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
679*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
680*67e74705SXin Li// CHECK-NEXT: store void ()* [[T2]], void ()** [[B]]
681*67e74705SXin Li
682*67e74705SXin Li//   Block setup.  We skip most of this.  Note the bare retain.
683*67e74705SXin Li// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
684*67e74705SXin Li// CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
685*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]],
686*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
687*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
688*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
689*67e74705SXin Li// CHECK-NEXT: store void ()* [[T3]], void ()** [[SLOT]],
690*67e74705SXin Li//   Call.
691*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void (i32)*
692*67e74705SXin Li// CHECK-NEXT: call void @test19_sink(void (i32)* [[T0]])
693*67e74705SXin Li
694*67e74705SXin Li  test19_sink(^(int x) { b(); });
695*67e74705SXin Li
696*67e74705SXin Li//   Block teardown.
697*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[SLOTREL]]
698*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
699*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T1]])
700*67e74705SXin Li
701*67e74705SXin Li//   Local cleanup.
702*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]
703*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
704*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T1]])
705*67e74705SXin Li
706*67e74705SXin Li// CHECK-NEXT: ret void
707*67e74705SXin Li}
708*67e74705SXin Li
709*67e74705SXin Li// CHECK: attributes [[NUW]] = { nounwind }
710*67e74705SXin Li// CHECK-UNOPT: attributes [[NUW]] = { nounwind }
711