diff options
author | Anders Carlsson <andersca@mac.com> | 2009-03-01 01:09:12 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-03-01 01:09:12 +0000 |
commit | 4de9fce48e42cc7ec1345c0fd21b3dbc5b9114c8 (patch) | |
tree | 68a066a7e73557f3fcaeccc391e86b95da64fc4c | |
parent | 6f877cd1743b12a09b4e5f32cc94552c19df7e42 (diff) |
Do some blocks cleanup and simplification. Fix a crash, and add a test case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65746 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 46 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 8 | ||||
-rw-r--r-- | test/CodeGen/blocks.c | 2 |
4 files changed, 50 insertions, 16 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 696f889b63..93e1b57fc9 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -107,13 +107,43 @@ llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { return NSConcreteStackBlock; } +static void CollectBlockDeclRefInfo(const Stmt *S, + CodeGenFunction::BlockInfo &Info) { + for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); + I != E; ++I) + CollectBlockDeclRefInfo(*I, Info); + + if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) { + // FIXME: Handle enums. + if (isa<FunctionDecl>(DE->getDecl())) + return; + + if (DE->isByRef()) + Info.ByRefDeclRefs.push_back(DE); + else + Info.ByCopyDeclRefs.push_back(DE); + } +} + +/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block +/// can be declared as a global variable instead of on the stack. +static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) +{ + return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty(); +} + // FIXME: Push most into CGM, passing down a few bits, like current // function name. llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { - bool insideFunction = false; - bool BlockRefDeclList = false; - bool BlockByrefDeclList = false; + std::string Name = CurFn->getName(); + CodeGenFunction::BlockInfo Info(0, Name.c_str()); + CollectBlockDeclRefInfo(BE->getBody(), Info); + + // Check if the block can be global. + if (CanBlockBeGlobal(Info)) + return CGM.GetAddrOfGlobalBlock(BE, Name.c_str()); + std::vector<llvm::Constant*> Elts; llvm::Constant *C; llvm::Value *V; @@ -127,11 +157,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // __isa C = CGM.getNSConcreteStackBlock(); - if (!insideFunction || - (!BlockRefDeclList && !BlockByrefDeclList)) { - C = CGM.getNSConcreteGlobalBlock(); - flags |= BLOCK_IS_GLOBAL; - } const llvm::PointerType *PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); @@ -148,11 +173,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Elts.push_back(C); // __invoke - const char *Name = ""; - if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurFuncDecl)) - if (ND->getIdentifier()) - Name = ND->getNameAsCString(); - BlockInfo Info(0, Name); uint64_t subBlockSize, subBlockAlign; llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls; llvm::Function *Fn diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 93bc53f7b8..565549c91f 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -450,9 +450,13 @@ public: return CGM.GetAddrOfConstantCFString(S); } case Expr::BlockExprClass: { - BlockExpr *B = cast<BlockExpr>(E); - if (!B->hasBlockDeclRefExprs()) - return cast<llvm::Constant>(CGF->BuildBlockLiteralTmp(B)); + std::string FunctionName; + if (CGF) + FunctionName = CGF->CurFn->getName(); + else + FunctionName = "global"; + + return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str()); } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 6e43572382..bf9c4e5ba5 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -275,6 +275,14 @@ public: /// Name - the name of the function this block was created for, if any const char *Name; + /// ByCopyDeclRefs - Variables from parent scopes that have been imported + /// into this block. + llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs; + + // ByRefDeclRefs - __block variables from parent scopes that have been + // imported into this block. + llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs; + BlockInfo(const llvm::Type *blt, const char *n) : BlockLiteralTy(blt), Name(n) {} }; diff --git a/test/CodeGen/blocks.c b/test/CodeGen/blocks.c new file mode 100644 index 0000000000..d3d4cefacc --- /dev/null +++ b/test/CodeGen/blocks.c @@ -0,0 +1,2 @@ +// RUN: clang %s -emit-llvm -o %t -fblocks +void (^f)(void) = ^{}; |