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