1 // 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 // 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. 5 void test0(id (^maker)(void)) { 6 maker(); 7 } 8 9 int (^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 25 void 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 65 void 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(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(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 109 void 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 165 void 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(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(i64 8, i8* [[VARPTR2]]) 189 // CHECK-NEXT: ret void 190 } 191 192 void 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(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(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 249 void 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: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8* 302 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) 303 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]* 304 // CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]] 305 // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to 306 // CHECK: call void @test8_helper( 307 // CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]*, [[TEST8]]** [[D0]] 308 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8* 309 // CHECK-NEXT: call void @objc_release(i8* [[T2]]) 310 // CHECK: ret void 311 312 extern void test8_helper(void (^)(void)); 313 test8_helper(^{ (void) self; }); 314 } 315 @end 316 317 id test9(void) { 318 typedef id __attribute__((ns_returns_retained)) blocktype(void); 319 extern void test9_consume_block(blocktype^); 320 return ^blocktype { 321 extern id test9_produce(void); 322 return test9_produce(); 323 }(); 324 325 // CHECK-LABEL: define i8* @test9( 326 // CHECK: load i8*, i8** getelementptr 327 // CHECK-NEXT: bitcast i8* 328 // CHECK-NEXT: call i8* 329 // CHECK-NEXT: tail call i8* @objc_autoreleaseReturnValue 330 // CHECK-NEXT: ret i8* 331 332 // CHECK: call i8* @test9_produce() 333 // CHECK-NEXT: call i8* @objc_retain 334 // CHECK-NEXT: ret i8* 335 } 336 337 // rdar://problem/9814099 338 // Test that we correctly initialize __block variables 339 // when the initialization captures the variable. 340 void test10a(void) { 341 __block void (^block)(void) = ^{ block(); }; 342 // CHECK-LABEL: define void @test10a() 343 // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]], 344 345 // Zero-initialization before running the initializer. 346 // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6 347 // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8 348 349 // Run the initializer as an assignment. 350 // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8* 351 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]]) 352 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()* 353 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1 354 // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]] 355 // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6 356 // CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8 357 // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8 358 // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8* 359 // CHECK-NEXT: call void @objc_release(i8* [[T7]]) 360 361 // Destroy at end of function. 362 // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6 363 // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8* 364 // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) 365 // CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]] 366 // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* 367 // CHECK-NEXT: call void @objc_release(i8* [[T2]]) 368 // CHECK: ret void 369 } 370 371 // <rdar://problem/10402698>: do this copy and dispose with 372 // objc_retainBlock/release instead of _Block_object_assign/destroy. 373 // We can also use _Block_object_assign/destroy with 374 // BLOCK_FIELD_IS_BLOCK as long as we don't pass BLOCK_BYREF_CALLER. 375 376 // CHECK-LABEL: define internal void @__Block_byref_object_copy_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { 377 // CHECK: [[D0:%.*]] = load i8*, i8** {{%.*}} 378 // CHECK-NEXT: [[D1:%.*]] = bitcast i8* [[D0]] to [[BYREF_T]]* 379 // CHECK-NEXT: [[D2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[D1]], i32 0, i32 6 380 // CHECK-NEXT: [[S0:%.*]] = load i8*, i8** {{%.*}} 381 // CHECK-NEXT: [[S1:%.*]] = bitcast i8* [[S0]] to [[BYREF_T]]* 382 // CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[S1]], i32 0, i32 6 383 // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[S2]], align 8 384 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 385 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) 386 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* 387 // CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8 388 // CHECK: ret void 389 390 // CHECK-LABEL: define internal void @__Block_byref_object_dispose_.{{[0-9]+}}(i8*) #{{[0-9]+}} { 391 // CHECK: [[T0:%.*]] = load i8*, i8** {{%.*}} 392 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]* 393 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T1]], i32 0, i32 6 394 // CHECK-NEXT: [[T3:%.*]] = load void ()*, void ()** [[T2]] 395 // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* 396 // CHECK-NEXT: call void @objc_release(i8* [[T4]]) 397 // CHECK-NEXT: ret void 398 399 // Test that we correctly assign to __block variables when the 400 // assignment captures the variable. 401 void test10b(void) { 402 __block void (^block)(void); 403 block = ^{ block(); }; 404 405 // CHECK-LABEL: define void @test10b() 406 // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]], 407 408 // Zero-initialize. 409 // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6 410 // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8 411 412 // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6 413 414 // The assignment. 415 // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8* 416 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]]) 417 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()* 418 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1 419 // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]] 420 // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T4]], i32 0, i32 6 421 // CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8 422 // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8 423 // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8* 424 // CHECK-NEXT: call void @objc_release(i8* [[T7]]) 425 426 // Destroy at end of function. 427 // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8* 428 // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) 429 // CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]] 430 // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* 431 // CHECK-NEXT: call void @objc_release(i8* [[T2]]) 432 // CHECK: ret void 433 } 434 435 // rdar://problem/10088932 436 void test11_helper(id); 437 void test11a(void) { 438 int x; 439 test11_helper(^{ (void) x; }); 440 441 // CHECK-LABEL: define void @test11a() 442 // CHECK: [[X:%.*]] = alloca i32, align 4 443 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 444 // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 445 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 446 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) 447 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* 448 // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* 449 // CHECK-NEXT: call void @test11_helper(i8* [[T4]]) 450 // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8* 451 // CHECK-NEXT: call void @objc_release(i8* [[T5]]) 452 // CHECK: ret void 453 } 454 void test11b(void) { 455 int x; 456 id b = ^{ (void) x; }; 457 458 // CHECK-LABEL: define void @test11b() 459 // CHECK: [[X:%.*]] = alloca i32, align 4 460 // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8 461 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 462 // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 463 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 464 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) 465 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* 466 // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* 467 // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8 468 // CHECK-NEXT: [[T5:%.*]] = load i8*, i8** [[B]] 469 // CHECK-NEXT: call void @objc_release(i8* [[T5]]) 470 // CHECK: ret void 471 } 472 473 // rdar://problem/9979150 474 @interface Test12 475 @property (strong) void(^ablock)(void); 476 @property (nonatomic, strong) void(^nblock)(void); 477 @end 478 @implementation Test12 479 @synthesize ablock, nblock; 480 // CHECK: define internal void ()* @"\01-[Test12 ablock]"( 481 // CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext true) 482 483 // CHECK: define internal void @"\01-[Test12 setAblock:]"( 484 // CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true) 485 486 // CHECK: define internal void ()* @"\01-[Test12 nblock]"( 487 // CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false) 488 489 // CHECK: define internal void @"\01-[Test12 setNblock:]"( 490 // CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true) 491 @end 492 493 // rdar://problem/10131784 494 void test13(id x) { 495 extern void test13_helper(id); 496 extern void test13_use(void(^)(void)); 497 498 void (^b)(void) = (x ? ^{test13_helper(x);} : 0); 499 test13_use(b); 500 501 // CHECK-LABEL: define void @test13( 502 // CHECK: [[X:%.*]] = alloca i8*, align 8 503 // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 504 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 505 // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 506 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) 507 // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8 508 // CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8* 509 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BPTR1]]) 510 // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 511 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8 512 // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null 513 // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] 514 // CHECK-NEXT: br i1 [[T1]], 515 516 // CHECK-NOT: br 517 // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 518 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8 519 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) 520 // CHECK-NEXT: store i8* [[T1]], i8** [[CAPTURE]], align 8 521 // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]] 522 // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 523 // CHECK-NEXT: br label 524 // CHECK: br label 525 // CHECK: [[T0:%.*]] = phi void ()* 526 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 527 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) 528 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* 529 // CHECK-NEXT: store void ()* [[T3]], void ()** [[B]], align 8 530 // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]], align 8 531 // CHECK-NEXT: call void @test13_use(void ()* [[T0]]) 532 // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]] 533 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 534 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) 535 // CHECK-NEXT: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8* 536 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[BPTR2]]) 537 538 // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]] 539 // CHECK-NEXT: br i1 [[T0]] 540 // CHECK: [[T0:%.*]] = load i8*, i8** [[CLEANUP_ADDR]] 541 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) 542 // CHECK-NEXT: br label 543 544 // CHECK: [[T0:%.*]] = load i8*, i8** [[X]] 545 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) 546 // CHECK-NEXT: ret void 547 } 548 549 // <rdar://problem/10907510> 550 void test14() { 551 void (^const x[1])(void) = { ^{} }; 552 } 553 554 // rdar://11149025 555 // Don't make invalid ASTs and crash. 556 void test15_helper(void (^block)(void), int x); 557 void test15(int a) { 558 test15_helper(^{ (void) a; }, ({ a; })); 559 } 560 561 // rdar://11016025 562 void test16() { 563 void (^BLKVAR)(void) = ^{ BLKVAR(); }; 564 565 // CHECK-LABEL: define void @test16( 566 // CHECK: [[BLKVAR:%.*]] = alloca void ()*, align 8 567 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], 568 // CHECK-NEXT: [[BLKVARPTR1:%.*]] = bitcast void ()** [[BLKVAR]] to i8* 569 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BLKVARPTR1]]) 570 // CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 571 // CHECK-NEXT: store void ()* null, void ()** [[BLKVAR]], align 8 572 } 573 574 // rdar://12151005 575 // 576 // This is an intentional exception to our conservative jump-scope 577 // checking for full-expressions containing block literals with 578 // non-trivial cleanups: if the block literal appears in the operand 579 // of a return statement, there's no need to extend its lifetime. 580 id (^test17(id self, int which))(void) { 581 switch (which) { 582 case 1: return ^{ return self; }; 583 case 0: return ^{ return self; }; 584 } 585 return (void*) 0; 586 } 587 // CHECK-LABEL: define i8* ()* @test17( 588 // CHECK: [[RET:%.*]] = alloca i8* ()*, align 589 // CHECK-NEXT: [[SELF:%.*]] = alloca i8*, 590 // CHECK: [[B0:%.*]] = alloca [[BLOCK:<.*>]], align 591 // CHECK: [[B1:%.*]] = alloca [[BLOCK]], align 592 // CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* 593 // CHECK-NEXT: store i8* [[T0]], i8** [[SELF]], align 594 // CHECK-NOT: objc_retain 595 // CHECK-NOT: objc_release 596 // CHECK: [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B0]], i32 0, i32 5 597 // CHECK-NOT: objc_retain 598 // CHECK-NOT: objc_release 599 // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B0]], i32 0, i32 5 600 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[SELF]], align 601 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) 602 // CHECK-NEXT: store i8* [[T2]], i8** [[T0]], 603 // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B0]] to i8* ()* 604 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8* 605 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) 606 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()* 607 // CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]] 608 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[DESTROY]] 609 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) 610 // CHECK-NEXT: store i32 611 // CHECK-NEXT: br label 612 // CHECK-NOT: objc_retain 613 // CHECK-NOT: objc_release 614 // CHECK: [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B1]], i32 0, i32 5 615 // CHECK-NOT: objc_retain 616 // CHECK-NOT: objc_release 617 // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B1]], i32 0, i32 5 618 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[SELF]], align 619 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) 620 // CHECK-NEXT: store i8* [[T2]], i8** [[T0]], 621 // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B1]] to i8* ()* 622 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8* 623 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) 624 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()* 625 // CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]] 626 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[DESTROY]] 627 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) 628 // CHECK-NEXT: store i32 629 // CHECK-NEXT: br label 630 631 void test18(id x) { 632 // CHECK-UNOPT-LABEL: define void @test18( 633 // CHECK-UNOPT: [[X:%.*]] = alloca i8*, 634 // CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], 635 // CHECK-UNOPT-NEXT: store i8* null, i8** [[X]] 636 // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], 637 // CHECK-UNOPT-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 638 // CHECK-UNOPT: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 639 // CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], 640 // CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) 641 // CHECK-UNOPT-NEXT: store i8* [[T1]], i8** [[SLOT]], 642 // CHECK-UNOPT-NEXT: bitcast 643 // CHECK-UNOPT-NEXT: call void @test18_helper( 644 // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) [[NUW:#[0-9]+]] 645 // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) [[NUW]] 646 // CHECK-UNOPT-NEXT: ret void 647 extern void test18_helper(id (^)(void)); 648 test18_helper(^{ return x; }); 649 650 // CHECK-UNOPT-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { 651 // CHECK-UNOPT: [[T0:%.*]] = load i8*, i8** 652 // CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* 653 // CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8** 654 // CHECK-UNOPT-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* 655 // CHECK-UNOPT-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[SRC]], i32 0, i32 5 656 // CHECK-UNOPT-NEXT: [[T1:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[DST]], i32 0, i32 5 657 // CHECK-UNOPT-NEXT: [[T2:%.*]] = load i8*, i8** [[T0]] 658 // CHECK-UNOPT-NEXT: store i8* null, i8** [[T1]] 659 // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) [[NUW]] 660 // CHECK-UNOPT-NEXT: ret void 661 662 // CHECK-UNOPT-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} { 663 // CHECK-UNOPT: [[T0:%.*]] = load i8*, i8** 664 // CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* 665 // CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5 666 // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) 667 // CHECK-UNOPT-NEXT: ret void 668 } 669 670 // rdar://13588325 671 void test19_sink(void (^)(int)); 672 void test19(void (^b)(void)) { 673 // CHECK-LABEL: define void @test19( 674 // Prologue. 675 // CHECK: [[B:%.*]] = alloca void ()*, 676 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], 677 // CHECK-NEXT: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8* 678 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) 679 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()* 680 // CHECK-NEXT: store void ()* [[T2]], void ()** [[B]] 681 682 // Block setup. We skip most of this. Note the bare retain. 683 // CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 684 // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 685 // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]], 686 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 687 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) 688 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* 689 // CHECK-NEXT: store void ()* [[T3]], void ()** [[SLOT]], 690 // Call. 691 // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void (i32)* 692 // CHECK-NEXT: call void @test19_sink(void (i32)* [[T0]]) 693 694 test19_sink(^(int x) { b(); }); 695 696 // Block teardown. 697 // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[SLOTREL]] 698 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 699 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) 700 701 // Local cleanup. 702 // CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]] 703 // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* 704 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) 705 706 // CHECK-NEXT: ret void 707 } 708 709 // CHECK: attributes [[NUW]] = { nounwind } 710 // CHECK-UNOPT: attributes [[NUW]] = { nounwind } 711