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