brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · e1dbc0e Raw
167 lines · plain
1// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-NOARC %s2// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -fobjc-arc -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-ARC %s3 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/dispose18// helper functions.19 20// When the block is non-escaping, copy/dispose helpers aren't generated, so the21// block layout string must include information about __strong captures.22 23// CHECK-NOARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { ptr, ptr, i32, i32, ptr, %[[STRUCT_S0:.*]] }24// CHECK-ARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { ptr, ptr, i32, i32, ptr, ptr, ptr, %[[STRUCT_S0:.*]] }25// CHECK: %[[STRUCT_S0]] = type { ptr, ptr }26// CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*ls32l8"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, ptr, i64 } { i64 0, i64 40, ptr @{{.*}}, i64 256 }, align 827 28// CHECK-LABEL: define{{.*}} void @test0(29// CHECK: call void @noescapeFunc0({{.*}}, {{.*}} captures(none) {{.*}})30// CHECK: declare void @noescapeFunc0(ptr noundef, {{.*}} noundef captures(none))31void test0(BlockTy b) {32  noescapeFunc0(0, b);33}34 35// CHECK-LABEL: define{{.*}} void @test1(36// CHECK: call void @noescapeFunc1({{.*}} captures(none) {{.*}})37// CHECK: declare void @noescapeFunc1({{.*}} noundef captures(none))38void test1(int *i) {39  noescapeFunc1(i);40}41 42// CHECK-LABEL: define{{.*}} void @test2(43// CHECK: call void @noescapeFunc2({{.*}} captures(none) {{.*}})44// CHECK: declare void @noescapeFunc2({{.*}} noundef captures(none))45void test2(id i) {46  noescapeFunc2(i);47}48 49// CHECK-LABEL: define{{.*}} void @test3(50// CHECK: call void @noescapeFunc3({{.*}} captures(none) {{.*}})51// CHECK: declare void @noescapeFunc3({{.*}} captures(none))52void test3(union U u) {53  noescapeFunc3(u);54}55 56// CHECK: define internal void @"\01-[C0 m0:]"({{.*}}, {{.*}}, {{.*}} captures(none) {{.*}})57 58// CHECK-LABEL: define{{.*}} void @test4(59// CHECK: call void @objc_msgSend(ptr {{.*}}, ptr {{.*}}, ptr noundef captures(none) {{.*}})60 61@interface C062-(void) m0:(int*)__attribute__((noescape)) p0;63@end64 65@implementation C066-(void) m0:(int*)__attribute__((noescape)) p0 {67}68@end69 70void test4(C0 *c0, int *p) {71  [c0 m0:p];72}73 74// CHECK-LABEL: define{{.*}} void @test5(75// CHECK: call void {{.*}}(ptr noundef @{{.*}}, ptr noundef captures(none) {{.*}})76// CHECK: call void {{.*}}(ptr {{.*}}, ptr noundef captures(none) {{.*}})77// CHECK: define internal void @{{.*}}(ptr {{.*}}, ptr noundef captures(none) {{.*}})78 79typedef void (^BlockTy2)(__attribute__((noescape)) int *);80 81void test5(BlockTy2 b, int *p) {82  ^(int *__attribute__((noescape)) p0){}(p);83  b(p);84}85 86// If the block is non-escaping, set the BLOCK_IS_NOESCAPE and BLOCK_IS_GLOBAL87// bits of field 'flags' and set the 'isa' field to 'NSConcreteGlobalBlock'.88 89// CHECK: define{{.*}} void @test6(ptr noundef %{{.*}}, ptr noundef %[[B:.*]])90// CHECK: %{{.*}} = alloca ptr, align 891// CHECK: %[[B_ADDR:.*]] = alloca ptr, align 892// CHECK: %[[BLOCK:.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 893// CHECK-NOARC: store ptr %[[B]], ptr %[[B_ADDR]], align 894// CHECK-ARC: store ptr null, ptr %[[B_ADDR]], align 895// CHECK-ARC: call void @llvm.objc.storeStrong(ptr %[[B_ADDR]], ptr %[[B]])96// CHECK: %[[BLOCK_ISA:.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %[[BLOCK]], i32 0, i32 097// CHECK: store ptr @_NSConcreteGlobalBlock, ptr %[[BLOCK_ISA]], align 898// CHECK: %[[BLOCK_FLAGS:.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %[[BLOCK]], i32 0, i32 199// CHECK: store i32 -796917760, ptr %[[BLOCK_FLAGS]], align 8100// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %[[BLOCK]], i32 0, i32 4101// CHECK: store ptr @[[BLOCK_DESCIPTOR_TMP_2]], ptr %[[BLOCK_DESCRIPTOR]], align 8102// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %[[BLOCK]], i32 0, i32 5103// CHECK-NOARC: %[[V1:.*]] = load ptr, ptr %[[B_ADDR]], align 8104// CHECK-NOARC: store ptr %[[V1]], ptr %[[BLOCK_CAPTURED]], align 8105// CHECK-ARC: %[[V2:.*]] = load ptr, ptr %[[B_ADDR]], align 8106// CHECK-ARC: %[[V3:.*]] = call ptr @llvm.objc.retain(ptr %[[V2]])107// CHECK-ARC: store ptr %[[V3]], ptr %[[BLOCK_CAPTURED]], align 8108// CHECK: call void @noescapeFunc0(109// CHECK-ARC: call void @llvm.objc.storeStrong(ptr %[[BLOCK_CAPTURED]], ptr null)110// CHECK-ARC: call void @llvm.objc.storeStrong(ptr %[[B_ADDR]], ptr null)111 112// Non-escaping blocks don't need copy/dispose helper functions.113 114// CHECK-NOT: define internal void @__copy_helper_block_115// CHECK-NOT: define internal void @__destroy_helper_block_116 117void func(id);118 119void test6(id a, id b) {120  noescapeFunc0(a, ^{ func(b); });121}122 123// We don't need either the byref helper functions or the byref structs for124// __block variables that are not captured by escaping blocks.125 126// CHECK: define{{.*}} void @test7(127// CHECK: alloca ptr, align 8128// CHECK: %[[B0:.*]] = alloca ptr, align 8129// CHECK: %[[BLOCK:.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8130// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %[[BLOCK]], i32 0, i32 5131// CHECK: store ptr %[[B0]], ptr %[[BLOCK_CAPTURED]], align 8132 133// CHECK-ARC-NOT: define internal void @__Block_byref_object_copy_134// CHECK-ARC-NOT: define internal void @__Block_byref_object_dispose_135 136void test7(void) {137  id a;138  __block id b0;139  noescapeFunc0(a, ^{ (void)b0; });140}141 142// __block variables captured by escaping blocks need byref helper functions.143 144// CHECK: define{{.*}} void @test8(145// CHECK: %[[A:.*]] = alloca ptr, align 8146// CHECK: %[[B0:.*]] = alloca %[[STRUCT_BLOCK_BYREF_B0]], align 8147// CHECK: alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8148// CHECK: %[[BLOCK1:.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8149// CHECK: %[[BLOCK_CAPTURED7:.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr %[[BLOCK1]], i32 0, i32 5150// CHECK: store ptr %[[B0]], ptr %[[BLOCK_CAPTURED7]], align 8151 152// CHECK-ARC: define internal void @__Block_byref_object_copy_153// CHECK-ARC: define internal void @__Block_byref_object_dispose_154// CHECK: define linkonce_odr hidden void @__copy_helper_block_155// CHECK: define linkonce_odr hidden void @__destroy_helper_block_156 157struct S0 {158  id a, b;159};160 161void test8(void) {162  id a;163  __block struct S0 b0;164  noescapeFunc0(a, ^{ (void)b0; });165  escapingFunc0(^{ (void)b0; });166}167