aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGBlocks.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2018-07-20 17:10:32 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2018-07-20 17:10:32 +0000
commitdbfa453e4138bb977644929c69d1c71e5e8b4bee (patch)
treefd0755e09eefe0ed813945492b2886441d6e8334 /clang/lib/CodeGen/CGBlocks.cpp
parentc358e51e9b9d42be542ae577d10b851e9358cd39 (diff)
downloadllvm-dbfa453e4138bb977644929c69d1c71e5e8b4bee.zip
llvm-dbfa453e4138bb977644929c69d1c71e5e8b4bee.tar.gz
llvm-dbfa453e4138bb977644929c69d1c71e5e8b4bee.tar.bz2
[CodeGen][ObjC] Make copying and disposing of a non-escaping block
no-ops. A non-escaping block on the stack will never be called after its lifetime ends, so it doesn't have to be copied to the heap. To prevent a non-escaping block from being copied to the heap, this patch sets field 'isa' of the block object to NSConcreteGlobalBlock and sets the BLOCK_IS_GLOBAL bit of field 'flags', which causes the runtime to treat the block as if it were a global block (calling _Block_copy on the block just returns the original block and calling _Block_release is a no-op). Also, a new flag bit 'BLOCK_IS_NOESCAPE' is added, which allows the runtime or tools to distinguish between true global blocks and non-escaping blocks. rdar://problem/39352313 Differential Revision: https://reviews.llvm.org/D49303 llvm-svn: 337580
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.cpp')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp16
1 files changed, 12 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 926683d..352a02d 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -104,7 +104,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
// Optional copy/dispose helpers.
- if (blockInfo.NeedsCopyDispose) {
+ if (blockInfo.needsCopyDisposeHelpers()) {
// copy_func_helper_decl
elements.add(buildCopyHelper(CGM, blockInfo));
@@ -159,6 +159,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
/// These are the flags (with corresponding bit number) that the
/// compiler is actually supposed to know about.
+ /// 23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping
/// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
/// descriptor provides copy and dispose helper functions
/// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
@@ -778,8 +779,13 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
llvm::Constant *descriptor;
BlockFlags flags;
if (!IsOpenCL) {
- isa = llvm::ConstantExpr::getBitCast(CGM.getNSConcreteStackBlock(),
- VoidPtrTy);
+ // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock
+ // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping
+ // block just returns the original block and releasing it is a no-op.
+ llvm::Constant *blockISA = blockInfo.getBlockDecl()->doesNotEscape()
+ ? CGM.getNSConcreteGlobalBlock()
+ : CGM.getNSConcreteStackBlock();
+ isa = llvm::ConstantExpr::getBitCast(blockISA, VoidPtrTy);
// Build the block descriptor.
descriptor = buildBlockDescriptor(CGM, blockInfo);
@@ -788,12 +794,14 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
flags = BLOCK_HAS_SIGNATURE;
if (blockInfo.HasCapturedVariableLayout)
flags |= BLOCK_HAS_EXTENDED_LAYOUT;
- if (blockInfo.NeedsCopyDispose)
+ if (blockInfo.needsCopyDisposeHelpers())
flags |= BLOCK_HAS_COPY_DISPOSE;
if (blockInfo.HasCXXObject)
flags |= BLOCK_HAS_CXX_OBJ;
if (blockInfo.UsesStret)
flags |= BLOCK_USE_STRET;
+ if (blockInfo.getBlockDecl()->doesNotEscape())
+ flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
}
auto projectField =