1// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-NOARC %s 2// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -fobjc-arc -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-ARC %s 3 4typedef void (^BlockTy)(void); 5 6union U { 7 int *i; 8 long long *ll; 9} __attribute__((transparent_union)); 10 11void escapingFunc0(BlockTy); 12void noescapeFunc0(id, __attribute__((noescape)) BlockTy); 13void noescapeFunc1(__attribute__((noescape)) int *); 14void noescapeFunc2(__attribute__((noescape)) id); 15void noescapeFunc3(__attribute__((noescape)) union U); 16 17// Block descriptors of non-escaping blocks don't need pointers to copy/dispose 18// helper functions. 19 20// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } 21 22// When the block is non-escaping, copy/dispose helpers aren't generated, so the 23// block layout string must include information about __strong captures. 24 25// CHECK-NOARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_B0]]*, i32, i32, i8*, %[[STRUCT_S0:.*]] } 26// CHECK-ARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_B0]]*, i32, i32, i8*, i8*, i8*, %[[STRUCT_S0:.*]] } 27// CHECK: %[[STRUCT_S0]] = type { i8*, i8* } 28// CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*ls32l8"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i64 } { i64 0, i64 40, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8 29 30// CHECK-LABEL: define void @test0( 31// CHECK: call void @noescapeFunc0({{.*}}, {{.*}} nocapture {{.*}}) 32// CHECK: declare void @noescapeFunc0(i8*, {{.*}} nocapture) 33void test0(BlockTy b) { 34 noescapeFunc0(0, b); 35} 36 37// CHECK-LABEL: define void @test1( 38// CHECK: call void @noescapeFunc1({{.*}} nocapture {{.*}}) 39// CHECK: declare void @noescapeFunc1({{.*}} nocapture) 40void test1(int *i) { 41 noescapeFunc1(i); 42} 43 44// CHECK-LABEL: define void @test2( 45// CHECK: call void @noescapeFunc2({{.*}} nocapture {{.*}}) 46// CHECK: declare void @noescapeFunc2({{.*}} nocapture) 47void test2(id i) { 48 noescapeFunc2(i); 49} 50 51// CHECK-LABEL: define void @test3( 52// CHECK: call void @noescapeFunc3({{.*}} nocapture {{.*}}) 53// CHECK: declare void @noescapeFunc3({{.*}} nocapture) 54void test3(union U u) { 55 noescapeFunc3(u); 56} 57 58// CHECK: define internal void @"\01-[C0 m0:]"({{.*}}, {{.*}}, {{.*}} nocapture {{.*}}) 59 60// CHECK-LABEL: define void @test4( 61// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32*)*)(i8* {{.*}}, i8* {{.*}}, i32* nocapture {{.*}}) 62 63@interface C0 64-(void) m0:(int*)__attribute__((noescape)) p0; 65@end 66 67@implementation C0 68-(void) m0:(int*)__attribute__((noescape)) p0 { 69} 70@end 71 72void test4(C0 *c0, int *p) { 73 [c0 m0:p]; 74} 75 76// CHECK-LABEL: define void @test5( 77// CHECK: call void {{.*}}(i8* bitcast ({ i8**, i32, i32, i8*, {{.*}} }* @{{.*}} to i8*), i32* nocapture {{.*}}) 78// CHECK: call void {{.*}}(i8* {{.*}}, i32* nocapture {{.*}}) 79// CHECK: define internal void @{{.*}}(i8* {{.*}}, i32* nocapture {{.*}}) 80 81typedef void (^BlockTy2)(__attribute__((noescape)) int *); 82 83void test5(BlockTy2 b, int *p) { 84 ^(int *__attribute__((noescape)) p0){}(p); 85 b(p); 86} 87 88// If the block is non-escaping, set the BLOCK_IS_NOESCAPE and BLOCK_IS_GLOBAL 89// bits of field 'flags' and set the 'isa' field to 'NSConcreteGlobalBlock'. 90 91// CHECK: define void @test6(i8* %{{.*}}, i8* %[[B:.*]]) 92// CHECK: %{{.*}} = alloca i8*, align 8 93// CHECK: %[[B_ADDR:.*]] = alloca i8*, align 8 94// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 95// CHECK-NOARC: store i8* %[[B]], i8** %[[B_ADDR]], align 8 96// CHECK-ARC: store i8* null, i8** %[[B_ADDR]], align 8 97// CHECK-ARC: call void @llvm.objc.storeStrong(i8** %[[B_ADDR]], i8* %[[B]]) 98// CHECK: %[[BLOCK_ISA:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 0 99// CHECK: store i8* bitcast (i8** @_NSConcreteGlobalBlock to i8*), i8** %[[BLOCK_ISA]], align 8 100// CHECK: %[[BLOCK_FLAGS:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 1 101// CHECK: store i32 -796917760, i32* %[[BLOCK_FLAGS]], align 8 102// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 4 103// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i64 }* @[[BLOCK_DESCIPTOR_TMP_2]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8 104// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5 105// CHECK-NOARC: %[[V1:.*]] = load i8*, i8** %[[B_ADDR]], align 8 106// CHECK-NOARC: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8 107// CHECK-ARC: %[[V2:.*]] = load i8*, i8** %[[B_ADDR]], align 8 108// CHECK-ARC: %[[V3:.*]] = call i8* @llvm.objc.retain(i8* %[[V2]]) 109// CHECK-ARC: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED]], align 8 110// CHECK: call void @noescapeFunc0( 111// CHECK-ARC: call void @llvm.objc.storeStrong(i8** %[[BLOCK_CAPTURED]], i8* null) 112// CHECK-ARC: call void @llvm.objc.storeStrong(i8** %[[B_ADDR]], i8* null) 113 114// Non-escaping blocks don't need copy/dispose helper functions. 115 116// CHECK-NOT: define internal void @__copy_helper_block_ 117// CHECK-NOT: define internal void @__destroy_helper_block_ 118 119void func(id); 120 121void test6(id a, id b) { 122 noescapeFunc0(a, ^{ func(b); }); 123} 124 125// We don't need either the byref helper functions or the byref structs for 126// __block variables that are not captured by escaping blocks. 127 128// CHECK: define void @test7( 129// CHECK: alloca i8*, align 8 130// CHECK: %[[B0:.*]] = alloca i8*, align 8 131// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, align 8 132// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>* %[[BLOCK]], i32 0, i32 5 133// CHECK: store i8** %[[B0]], i8*** %[[BLOCK_CAPTURED]], align 8 134 135// CHECK-ARC-NOT: define internal void @__Block_byref_object_copy_ 136// CHECK-ARC-NOT: define internal void @__Block_byref_object_dispose_ 137 138void test7() { 139 id a; 140 __block id b0; 141 noescapeFunc0(a, ^{ (void)b0; }); 142} 143 144// __block variables captured by escaping blocks need byref helper functions. 145 146// CHECK: define void @test8( 147// CHECK: %[[A:.*]] = alloca i8*, align 8 148// CHECK: %[[B0:.*]] = alloca %[[STRUCT_BLOCK_BYREF_B0]], align 8 149// CHECK: alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 150// CHECK: %[[BLOCK1:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 151// CHECK: %[[BLOCK_CAPTURED7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK1]], i32 0, i32 5 152// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_B0]]* %[[B0]] to i8* 153// CHECK: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED7]], align 8 154 155// CHECK-ARC: define internal void @__Block_byref_object_copy_ 156// CHECK-ARC: define internal void @__Block_byref_object_dispose_ 157// CHECK: define linkonce_odr hidden void @__copy_helper_block_ 158// CHECK: define linkonce_odr hidden void @__destroy_helper_block_ 159 160struct S0 { 161 id a, b; 162}; 163 164void test8() { 165 id a; 166 __block struct S0 b0; 167 noescapeFunc0(a, ^{ (void)b0; }); 168 escapingFunc0(^{ (void)b0; }); 169} 170