1// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -o - %s | FileCheck -check-prefix CHECK %s 2// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -O1 -o - %s | FileCheck -check-prefix CHECK-O1 %s 3// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck -check-prefix CHECK-NOEXCP %s 4 5// CHECK: [[A:.*]] = type { i64, [10 x i8*] } 6// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } 7// CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 } 8// CHECK: %[[STRUCT_TRIVIAL_INTERNAL:.*]] = type { i32 } 9 10// CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00" 11 12// rdar://13045269 13// If a __block variable requires extended layout information *and* 14// a copy/dispose helper, be sure to adjust the offsets used in copy/dispose. 15namespace test0 { 16 struct A { 17 unsigned long count; 18 id data[10]; 19 }; 20 21 void foo() { 22 __block A v; 23 ^{ (void)v; }; 24 } 25 // CHECK-LABEL: define{{.*}} void @_ZN5test03fooEv() 26 // CHECK: [[V:%.*]] = alloca [[BYREF_A:%.*]], align 8 27 // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 4 28 // CHECK-NEXT: store i8* bitcast (void (i8*, i8*)* [[COPY_HELPER:@.*]] to i8*), i8** [[T0]] 29 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 5 30 // CHECK-NEXT: store i8* bitcast (void (i8*)* [[DISPOSE_HELPER:@.*]] to i8*), i8** [[T0]] 31 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 6 32 // CHECK-NEXT: store i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[LAYOUT0]], i32 0, i32 0), i8** [[T0]] 33 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7 34 // CHECK-NEXT: call void @_ZN5test01AC1Ev([[A]]* {{[^,]*}} [[T0]]) 35 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7 36 // CHECK: bitcast [[BYREF_A]]* [[V]] to i8* 37 // CHECK: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8* 38 // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) 39 // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* {{[^,]*}} [[T0]]) 40 // CHECK-NEXT: ret void 41 42 // CHECK: define internal void [[COPY_HELPER]]( 43 // CHECK: [[T0:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]* 44 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[T0]], i32 0, i32 7 45 // CHECK-NEXT: load 46 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]* 47 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[T2]], i32 0, i32 7 48 // CHECK-NEXT: call void @_ZN5test01AC1ERKS0_([[A]]* {{[^,]*}} [[T1]], [[A]]* nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[T3]]) 49 // CHECK-NEXT: ret void 50 51 // CHECK: define internal void [[DISPOSE_HELPER]]( 52 // CHECK: [[T0:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]* 53 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[T0]], i32 0, i32 7 54 // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* {{[^,]*}} [[T1]]) 55 // CHECK-NEXT: ret void 56} 57 58// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ 59// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ 60// CHECK-LABEL-O1: define linkonce_odr hidden void @__copy_helper_block_ 61// CHECK-LABEL-O1: define linkonce_odr hidden void @__destroy_helper_block_ 62 63namespace test1 { 64 65// Check that copy/dispose helper functions are exception safe. 66 67// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E( 68// CHECK: %[[BLOCK_SOURCE:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* 69// CHECK: %[[BLOCK_DEST:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* 70 71// CHECK: %[[V9:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 5 72// CHECK: %[[V10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 5 73// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V9]], align 8 74// CHECK: store i8* null, i8** %[[V10]], align 8 75// CHECK: call void @llvm.objc.storeStrong(i8** %[[V10]], i8* %[[BLOCKCOPY_SRC2]]) 76 77// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 6 78// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 6 79// CHECK: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 8 80// CHECK: %[[V6:.*]] = bitcast i8** %[[V5]] to i8* 81// CHECK: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8) 82 83// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 7 84// CHECK: %[[V8:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 7 85// CHECK: call void @llvm.objc.copyWeak(i8** %[[V8]], i8** %[[V7]]) 86 87// CHECK: %[[V11:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 8 88// CHECK: %[[V12:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 8 89// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V12]], %[[STRUCT_TEST1_S0]]* nonnull align 4 dereferenceable(4) %[[V11]]) 90// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]] 91 92// CHECK: [[INVOKE_CONT]]: 93// CHECK: %[[V13:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 9 94// CHECK: %[[V14:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 9 95// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V14]], %[[STRUCT_TEST1_S0]]* nonnull align 4 dereferenceable(4) %[[V13]]) 96// CHECK: to label %[[INVOKE_CONT4:.*]] unwind label %[[LPAD3:.*]] 97 98// CHECK: [[INVOKE_CONT4]]: 99// CHECK: ret void 100 101// CHECK: [[LPAD]]: 102// CHECK: br label %[[EHCLEANUP:.*]] 103 104// CHECK: [[LPAD3]]: 105// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V12]]) 106// CHECK: to label %[[INVOKE_CONT5:.*]] unwind label %[[TERMINATE_LPAD:.*]] 107 108// CHECK: [[INVOKE_CONT5]]: 109// CHECK: br label %[[EHCLEANUP]] 110 111// CHECK: [[EHCLEANUP]]: 112// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V8]]) 113// CHECK: %[[V21:.*]] = load i8*, i8** %[[V5]], align 8 114// CHECK: call void @_Block_object_dispose(i8* %[[V21]], i32 8) 115// CHECK: call void @llvm.objc.storeStrong(i8** %[[V10]], i8* null) 116// CHECK: br label %[[EH_RESUME:.*]] 117 118// CHECK: [[EH_RESUME]]: 119// CHECK: resume { i8*, i32 } 120 121// CHECK: [[TERMINATE_LPAD]]: 122// CHECK: call void @__clang_call_terminate( 123 124// CHECK-O1-LABEL: define linkonce_odr hidden void @__copy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E( 125// CHECK-O1: call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release 126// CHECK-NOEXCP: define linkonce_odr hidden void @__copy_helper_block_8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E( 127 128// CHECK: define linkonce_odr hidden void @__destroy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E( 129// CHECK: %[[BLOCK:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* 130// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 5 131// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 6 132// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 7 133// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 8 134// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 9 135// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V6]]) 136// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]] 137 138// CHECK: [[INVOKE_CONT]]: 139// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V5]]) 140// CHECK: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD1:.*]] 141 142// CHECK: [[INVOKE_CONT2]]: 143// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V3]]) 144// CHECK: %[[V7:.*]] = load i8*, i8** %[[V2]], align 8 145// CHECK: call void @_Block_object_dispose(i8* %[[V7]], i32 8) 146// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null) 147// CHECK: ret void 148 149// CHECK: [[LPAD]]: 150// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V5]]) 151// CHECK: to label %[[INVOKE_CONT3:.*]] unwind label %[[TERMINATE_LPAD:.*]] 152 153// CHECK: [[LPAD1]] 154// CHECK: br label %[[EHCLEANUP:.*]] 155 156// CHECK: [[INVOKE_CONT3]]: 157// CHECK: br label %[[EHCLEANUP]] 158 159// CHECK: [[EHCLEANUP]]: 160// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V3]]) 161// CHECK: %[[V14:.*]] = load i8*, i8** %[[V2]], align 8 162// CHECK: call void @_Block_object_dispose(i8* %[[V14]], i32 8) 163// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null) 164// CHECK: br label %[[EH_RESUME:.*]] 165 166// CHECK: [[EH_RESUME]]: 167// CHECK: resume { i8*, i32 } 168 169// CHECK: [[TERMINATE_LPAD]]: 170// CHECK: call void @__clang_call_terminate( 171 172// CHECK-O1-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E( 173// CHECK-O1: call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release 174// CHECK-O1: call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release 175// CHECK-NOEXCP: define linkonce_odr hidden void @__destroy_helper_block_8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E( 176 177namespace { 178struct TrivialInternal { 179 int a; 180}; 181} 182 183struct S0 { 184 S0(); 185 S0(const S0 &); 186 ~S0(); 187 int f0; 188}; 189 190id getObj(); 191 192void foo1() { 193 __block id t0 = getObj(); 194 __weak id t1 = getObj(); 195 id t2 = getObj(); 196 S0 t3, t4; 197 // Capturing a non-external type doesn't cause the copy/dispose helpers to be 198 // internal unless the captured type has a non-trivial copy constructor or 199 // destructor. 200 TrivialInternal t5; 201 ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; (void)t5; }; 202} 203} 204 205// Test that calls to @llvm.objc.retainBlock aren't emitted in some cases. 206 207typedef void (^BlockTy)(); 208void foo1(id); 209 210namespace test_block_retain { 211 212// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain14initializationEP11objc_object( 213// CHECK-NOT: @llvm.objc.retainBlock( 214 void initialization(id a) { 215 BlockTy b0 = ^{ foo1(a); }; 216 BlockTy b1 = (^{ foo1(a); }); 217 b0(); 218 b1(); 219 } 220 221// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain20initializationStaticEP11objc_object( 222// CHECK: @llvm.objc.retainBlock( 223 void initializationStatic(id a) { 224 static BlockTy b0 = ^{ foo1(a); }; 225 b0(); 226 } 227 228// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain15initialization2EP11objc_object 229// CHECK: %[[B0:.*]] = alloca void ()*, align 8 230// CHECK: %[[B1:.*]] = alloca void ()*, align 8 231// CHECK: load void ()*, void ()** %[[B0]], align 8 232// CHECK-NOT: @llvm.objc.retainBlock 233// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8 234// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8* 235// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]]) 236// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()* 237// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8 238 void initialization2(id a) { 239 BlockTy b0 = ^{ foo1(a); }; 240 b0(); 241 BlockTy b1 = b0; // can't optimize this yet. 242 b1(); 243 } 244 245// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain10assignmentEP11objc_object( 246// CHECK-NOT: @llvm.objc.retainBlock( 247 void assignment(id a) { 248 BlockTy b0; 249 (b0) = ^{ foo1(a); }; 250 b0(); 251 b0 = (^{ foo1(a); }); 252 b0(); 253 } 254 255// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain16assignmentStaticEP11objc_object( 256// CHECK: @llvm.objc.retainBlock( 257 void assignmentStatic(id a) { 258 static BlockTy b0; 259 b0 = ^{ foo1(a); }; 260 b0(); 261 } 262 263// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain21assignmentConditionalEP11objc_objectb( 264// CHECK: @llvm.objc.retainBlock( 265 void assignmentConditional(id a, bool c) { 266 BlockTy b0; 267 if (c) 268 // can't optimize this since 'b0' is declared in the outer scope. 269 b0 = ^{ foo1(a); }; 270 b0(); 271 } 272 273// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain11assignment2EP11objc_object( 274// CHECK: %[[B0:.*]] = alloca void ()*, align 8 275// CHECK: %[[B1:.*]] = alloca void ()*, align 8 276// CHECK-NOT: @llvm.objc.retainBlock 277// CHECK: store void ()* null, void ()** %[[B1]], align 8 278// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8 279// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8* 280// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]] 281// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()* 282// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8 283 void assignment2(id a) { 284 BlockTy b0 = ^{ foo1(a); }; 285 b0(); 286 BlockTy b1; 287 b1 = b0; // can't optimize this yet. 288 b1(); 289 } 290 291// We cannot remove the call to @llvm.objc.retainBlock if the variable is of type id. 292 293// CHECK: define{{.*}} void @_ZN17test_block_retain21initializationObjCPtrEP11objc_object( 294// CHECK: alloca i8*, align 8 295// CHECK: %[[B0:.*]] = alloca i8*, align 8 296// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 297// CHECK: %[[V3:.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]] to void ()* 298// CHECK: %[[V4:.*]] = bitcast void ()* %[[V3]] to i8* 299// CHECK: %[[V5:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V4]]) 300// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to void ()* 301// CHECK: %[[V7:.*]] = bitcast void ()* %[[V6]] to i8* 302// CHECK: store i8* %[[V7]], i8** %[[B0]], align 8 303 void initializationObjCPtr(id a) { 304 id b0 = ^{ foo1(a); }; 305 ((BlockTy)b0)(); 306 } 307 308// CHECK: define{{.*}} void @_ZN17test_block_retain17assignmentObjCPtrEP11objc_object( 309// CHECK: %[[B0:.*]] = alloca void ()*, align 8 310// CHECK: %[[B1:.*]] = alloca i8*, align 8 311// CHECK: %[[V4:.*]] = load void ()*, void ()** %[[B0]], align 8 312// CHECK: %[[V5:.*]] = bitcast void ()* %[[V4]] to i8* 313// CHECK: %[[V6:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V5]]) 314// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to void ()* 315// CHECK: %[[V8:.*]] = bitcast void ()* %[[V7]] to i8* 316// CHECK: store i8* %[[V8]], i8** %[[B1]], align 8 317 void assignmentObjCPtr(id a) { 318 BlockTy b0 = ^{ foo1(a); }; 319 id b1; 320 b1 = b0; 321 ((BlockTy)b1)(); 322 } 323} 324 325// Check that the block capture is released after the full expression. 326 327// CHECK-LABEL: define void @_ZN13test_rval_ref4testEP11objc_object( 328// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 329// 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 330// CHECK: %[[V1:.*]] = call i8* @llvm.objc.retain( 331// CHECK: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8 332// CHECK: invoke void @_ZN13test_rval_ref17callTemplateBlockEOU15__autoreleasingU13block_pointerFvvE( 333 334// CHECK: call void @llvm.objc.storeStrong(i8** %[[BLOCK_CAPTURED]], i8* null) 335 336namespace test_rval_ref { 337 void callTemplateBlock(BlockTy &&func); 338 339 void test(id str) { 340 return callTemplateBlock(^void() { 341 foo1(str); 342 }); 343 } 344} 345