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. 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(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 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(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 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(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 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: [[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 317id 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. 340void 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. 401void 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 436void test11_helper(id); 437void 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} 454void 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 494void 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> 550void test14() { 551 void (^const x[1])(void) = { ^{} }; 552} 553 554// rdar://11149025 555// Don't make invalid ASTs and crash. 556void test15_helper(void (^block)(void), int x); 557void test15(int a) { 558 test15_helper(^{ (void) a; }, ({ a; })); 559} 560 561// rdar://11016025 562void 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. 580id (^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 631void 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 671void test19_sink(void (^)(int)); 672void 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