From: Anders Carlsson Date: Sun, 1 Mar 2009 01:09:12 +0000 (+0000) Subject: Do some blocks cleanup and simplification. Fix a crash, and add a test case. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4de9fce48e42cc7ec1345c0fd21b3dbc5b9114c8;p=clang 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 --- 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(S)) { + // FIXME: Handle enums. + if (isa(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 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(CurFuncDecl)) - if (ND->getIdentifier()) - Name = ND->getNameAsCString(); - BlockInfo Info(0, Name); uint64_t subBlockSize, subBlockAlign; llvm::SmallVector 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(E); - if (!B->hasBlockDeclRefExprs()) - return cast(CGF->BuildBlockLiteralTmp(B)); + std::string FunctionName; + if (CGF) + FunctionName = CGF->CurFn->getName(); + else + FunctionName = "global"; + + return CGM.GetAddrOfGlobalBlock(cast(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 ByCopyDeclRefs; + + // ByRefDeclRefs - __block variables from parent scopes that have been + // imported into this block. + llvm::SmallVector 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) = ^{};