]> granicus.if.org Git - clang/commitdiff
Do some blocks cleanup and simplification. Fix a crash, and add a test case.
authorAnders Carlsson <andersca@mac.com>
Sun, 1 Mar 2009 01:09:12 +0000 (01:09 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 1 Mar 2009 01:09:12 +0000 (01:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65746 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBlocks.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGen/blocks.c [new file with mode: 0644]

index 696f889b63436f667acb4b60a2b61eb894b30b21..93e1b57fc989232ea56ff1e22c8d6454c2e46568 100644 (file)
@@ -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
index 93bc53f7b8d73fca450c6dff9dd228c5d9c368df..565549c91fad47a6c6d2d1ab041d0791ddf1cbc0 100644 (file)
@@ -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());
     }
     }
 
index 6e43572382976e8867dc7faededa2d49b28c3e07..bf9c4e5ba5cb26c281f4dc53bbe5a13f54a19638 100644 (file)
@@ -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 (file)
index 0000000..d3d4cef
--- /dev/null
@@ -0,0 +1,2 @@
+// RUN: clang %s -emit-llvm -o %t -fblocks
+void (^f)(void) = ^{};