summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp23
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/test/CodeGen/mangle-blocks.c6
-rw-r--r--clang/test/CodeGenObjC/local-static-block.m11
-rw-r--r--clang/test/CodeGenObjC/mangle-blocks.m6
5 files changed, 32 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 8d82898fda9..6cf7f71ba5f 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -725,12 +725,13 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
llvm::Constant *blockFn
= CodeGenFunction(CGM, true).GenerateBlockFunction(CurGD, blockInfo,
LocalDeclMap,
- isLambdaConv);
+ isLambdaConv,
+ blockInfo.CanBeGlobal);
blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
// If there is nothing to capture, we can emit this as a global block.
if (blockInfo.CanBeGlobal)
- return buildGlobalBlock(CGM, blockInfo, blockFn);
+ return CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression);
// Otherwise, we have to emit this as a local block.
@@ -1114,17 +1115,14 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
computeBlockInfo(*this, nullptr, blockInfo);
// Using that metadata, generate the actual block function.
- llvm::Constant *blockFn;
{
CodeGenFunction::DeclMapTy LocalDeclMap;
- blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(),
- blockInfo,
- LocalDeclMap,
- false);
+ CodeGenFunction(*this).GenerateBlockFunction(
+ GlobalDecl(), blockInfo, LocalDeclMap,
+ /*IsLambdaConversionToBlock*/ false, /*BuildGlobalBlock*/ true);
}
- blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
- return buildGlobalBlock(*this, blockInfo, blockFn);
+ return getAddrOfGlobalBlockIfEmitted(BE);
}
static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
@@ -1226,7 +1224,8 @@ llvm::Function *
CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &blockInfo,
const DeclMapTy &ldm,
- bool IsLambdaConversionToBlock) {
+ bool IsLambdaConversionToBlock,
+ bool BuildGlobalBlock) {
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
CurGD = GD;
@@ -1285,6 +1284,10 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
+ if (BuildGlobalBlock)
+ buildGlobalBlock(CGM, blockInfo,
+ llvm::ConstantExpr::getBitCast(fn, VoidPtrTy));
+
// Begin generating the function.
StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
blockDecl->getLocation(),
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 7dca3805973..d77cea48b02 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1586,7 +1586,8 @@ public:
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &Info,
const DeclMapTy &ldm,
- bool IsLambdaConversionToBlock);
+ bool IsLambdaConversionToBlock,
+ bool BuildGlobalBlock);
llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
diff --git a/clang/test/CodeGen/mangle-blocks.c b/clang/test/CodeGen/mangle-blocks.c
index e8de92d8b40..4ea5a550c8b 100644
--- a/clang/test/CodeGen/mangle-blocks.c
+++ b/clang/test/CodeGen/mangle-blocks.c
@@ -12,12 +12,12 @@ void (^mangle(void))(void) {
}
// CHECK: @__func__.__mangle_block_invoke_2 = private unnamed_addr constant [22 x i8] c"mangle_block_invoke_2\00", align 1
-// CHECK: @.str = private unnamed_addr constant {{.*}}, align 1
-// CHECK: @.str.1 = private unnamed_addr constant [7 x i8] c"mangle\00", align 1
+// CHECK: @.str{{.*}} = private unnamed_addr constant {{.*}}, align 1
+// CHECK: @.str[[STR1:.*]] = private unnamed_addr constant [7 x i8] c"mangle\00", align 1
// CHECK: define internal void @__mangle_block_invoke(i8* %.block_descriptor)
// CHECK: define internal void @__mangle_block_invoke_2(i8* %.block_descriptor){{.*}}{
-// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @__func__.__mangle_block_invoke_2, i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 9, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
+// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @__func__.__mangle_block_invoke_2, i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 9, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str[[STR1]], i32 0, i32 0))
// CHECK: }
diff --git a/clang/test/CodeGenObjC/local-static-block.m b/clang/test/CodeGenObjC/local-static-block.m
index 73c670f5c92..67ede63fc0a 100644
--- a/clang/test/CodeGenObjC/local-static-block.m
+++ b/clang/test/CodeGenObjC/local-static-block.m
@@ -46,6 +46,17 @@ void FUNC()
}
}
+void FUNC2() {
+ static void (^const block1)(int) = ^(int a){
+ if (a--)
+ block1(a);
+ };
+}
+
+// CHECK-LABEL-LP64: define void @FUNC2(
+// CHECK: define internal void @_block_invoke{{.*}}(
+// CHECK: call void %{{.*}}(i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor* }* @__block_literal_global{{.*}} to i8*), i32 %{{.*}})
+
void FUNC1()
{
static NSArray *(^ArrayRecurs)(NSArray *addresses, unsigned long level) = ^(NSArray *addresses, unsigned long level) {
diff --git a/clang/test/CodeGenObjC/mangle-blocks.m b/clang/test/CodeGenObjC/mangle-blocks.m
index 4cc32040332..73522cd41c6 100644
--- a/clang/test/CodeGenObjC/mangle-blocks.m
+++ b/clang/test/CodeGenObjC/mangle-blocks.m
@@ -18,11 +18,11 @@ void __assert_rtn(const char *, const char *, int, const char *);
@end
// CHECK: @"__func__.__14-[Test mangle]_block_invoke_2" = private unnamed_addr constant [30 x i8] c"-[Test mangle]_block_invoke_2\00", align 1
-// CHECK: @.str = private unnamed_addr constant {{.*}}, align 1
-// CHECK: @.str.1 = private unnamed_addr constant [7 x i8] c"mangle\00", align 1
+// CHECK: @.str{{.*}} = private unnamed_addr constant {{.*}}, align 1
+// CHECK: @.str[[STR1:.*]] = private unnamed_addr constant [7 x i8] c"mangle\00", align 1
// CHECK: define internal void @"__14-[Test mangle]_block_invoke"(i8* %.block_descriptor)
// CHECK: define internal void @"__14-[Test mangle]_block_invoke_2"(i8* %.block_descriptor){{.*}}{
-// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @"__func__.__14-[Test mangle]_block_invoke_2", i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 14, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
+// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @"__func__.__14-[Test mangle]_block_invoke_2", i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 14, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str[[STR1]], i32 0, i32 0))
// CHECK: }
OpenPOWER on IntegriCloud