diff options
Diffstat (limited to 'test/CodeGen/blocks.c')
| -rw-r--r-- | test/CodeGen/blocks.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/test/CodeGen/blocks.c b/test/CodeGen/blocks.c index 911c63e41d347..6b355b898ed08 100644 --- a/test/CodeGen/blocks.c +++ b/test/CodeGen/blocks.c @@ -1,4 +1,10 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - -fblocks | FileCheck %s + +// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i32, i32 } + +// CHECK: @{{.*}} = internal constant { i32, i32, i8*, i8*, i8*, i8* } { i32 0, i32 24, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_4_20r to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_4_20r to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 4 +// CHECK: @[[BLOCK_DESCRIPTOR_TMP21:.*]] = internal constant { i32, i32, i8*, i8*, i8*, i8* } { i32 0, i32 24, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_4_20r to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_4_20r to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 4 + void (^f)(void) = ^{}; // rdar://6768379 @@ -27,6 +33,32 @@ void (^test1)(void) = ^(void) { ^ { i = 1; }(); }; +// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_4_20r(i8*, i8*) unnamed_addr +// CHECK: %[[_ADDR:.*]] = alloca i8*, align 4 +// CHECK-NEXT: %[[_ADDR1:.*]] = alloca i8*, align 4 +// CHECK-NEXT: store i8* %0, i8** %[[_ADDR]], align 4 +// CHECK-NEXT: store i8* %1, i8** %[[_ADDR1]], align 4 +// CHECK-NEXT: %[[V2:.*]] = load i8*, i8** %[[_ADDR1]], align 4 +// CHECK-NEXT: %[[BLOCK_SOURCE:.*]] = bitcast i8* %[[V2]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* +// CHECK-NEXT: %[[V3:.*]] = load i8*, i8** %[[_ADDR]], align 4 +// CHECK-NEXT: %[[BLOCK_DEST:.*]] = bitcast i8* %[[V3]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* +// CHECK-NEXT: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK_SOURCE]], i32 0, i32 5 +// CHECK-NEXT: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK_DEST]], i32 0, i32 5 +// CHECK-NEXT: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 4 +// CHECK-NEXT: %[[V6:.*]] = bitcast i8** %[[V5]] to i8* +// CHECK-NEXT: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8) +// CHECK-NEXT: ret void + +// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_4_20r(i8*) unnamed_addr +// CHECK: %[[_ADDR:.*]] = alloca i8*, align 4 +// CHECK-NEXT: store i8* %0, i8** %[[_ADDR]], align 4 +// CHECK-NEXT: %[[V1:.*]] = load i8*, i8** %[[_ADDR]], align 4 +// CHECK-NEXT: %[[BLOCK:.*]] = bitcast i8* %[[V1]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* +// CHECK-NEXT: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK-NEXT: %[[V3:.*]] = load i8*, i8** %[[V2]], align 4 +// CHECK-NEXT: call void @_Block_object_dispose(i8* %[[V3]], i32 8) +// CHECK-NEXT: ret void + typedef double ftype(double); // It's not clear that we *should* support this syntax, but until that decision // is made, we should support it properly and not crash. @@ -85,30 +117,8 @@ void testConstCaptureInCopyAndDestroyHelpers() { __block int i; (^ { i = x; })(); } -// CHECK-LABEL: testConstCaptureInCopyAndDestroyHelpers_block_invoke - -// CHECK: @__copy_helper_block -// CHECK: alloca -// CHECK-NEXT: alloca -// CHECK-NEXT: store -// CHECK-NEXT: store -// CHECK-NEXT: load -// CHECK-NEXT: bitcast -// CHECK-NEXT: load -// CHECK-NEXT: bitcast -// CHECK-NEXT: getelementptr -// CHECK-NEXT: getelementptr -// CHECK-NEXT: load -// CHECK-NEXT: bitcast -// CHECK-NEXT: call void @_Block_object_assign -// CHECK-NEXT: ret +// CHECK-LABEL: define void @testConstCaptureInCopyAndDestroyHelpers( +// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %{{.*}}, i32 0, i32 4 +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i32, i32, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR_TMP21]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 4 -// CHECK: @__destroy_helper_block -// CHECK: alloca -// CHECK-NEXT: store -// CHECK-NEXT: load -// CHECK-NEXT: bitcast -// CHECK-NEXT: getelementptr -// CHECK-NEXT: load -// CHECK-NEXT: call void @_Block_object_dispose -// CHECK-NEXT: ret +// CHECK-LABEL: define internal void @__testConstCaptureInCopyAndDestroyHelpers_block_invoke |
