Prep work to always preallocate BlockDeclRefExprs so that we can
generate the debug information for the first parameter to the block
invoke functions.  WIP.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84737 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 8e020c8..692a7a6 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -80,22 +80,48 @@
     if (*I)
       CollectBlockDeclRefInfo(*I, Info);
 
+  // We want to ensure we walk down into block literals so we can find
+  // all nested BlockDeclRefExprs.
+  if (const BlockExpr *BE = dyn_cast<BlockExpr>(S))
+    CollectBlockDeclRefInfo(BE->getBody(), 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);
+    Info.DeclRefs.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();
+  return Info.DeclRefs.empty();
+}
+
+/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
+/// ensure we can generate the debug information for the parameter for the block
+/// invoke function.
+static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info,
+                                     CodeGenFunction *CGF) {
+  // Always allocate self, as it is often handy in the debugger, even if there
+  // is no codegen in the block that uses it.  This is also useful to always do
+  // this as if we didn't, we'd have to figure out all code that uses a self
+  // pointer, including implicit uses.
+  if (const ObjCMethodDecl *OMD
+      = dyn_cast_or_null<ObjCMethodDecl>(CGF->CurFuncDecl)) {
+    ImplicitParamDecl *SelfDecl = OMD->getSelfDecl();
+    BlockDeclRefExpr *BDRE = new (CGF->getContext())
+      BlockDeclRefExpr(SelfDecl,
+                       SelfDecl->getType(), SourceLocation(), false);
+    CGF->AllocateBlockDecl(BDRE);
+  }
+
+  // FIXME: Also always forward the this pointer in C++ as well.
+
+  for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
+    CGF->AllocateBlockDecl(Info.DeclRefs[i]);
 }
 
 // FIXME: Push most into CGM, passing down a few bits, like current function
@@ -159,7 +185,8 @@
 
     if (subBlockDeclRefDecls.size() == 0) {
       // __descriptor
-      Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, 0, 0);
+      Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize,
+                                         0, 0);
 
       // Optimize to being a global block.
       Elts[0] = CGM.getNSConcreteGlobalBlock();
@@ -269,7 +296,7 @@
             llvm::Value *BlockLiteral = LoadBlockStruct();
 
             Loc = Builder.CreateGEP(BlockLiteral,
-                                    llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+                       llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
                                                            offset),
                                     "block.literal");
             Ty = llvm::PointerType::get(Ty, 0);
@@ -447,24 +474,32 @@
   return EmitCall(FnInfo, Func, Args);
 }
 
-llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
   const ValueDecl *VD = E->getDecl();
-  
   uint64_t &offset = BlockDecls[VD];
 
-
   // See if we have already allocated an offset for this variable.
-  if (offset == 0) {
-    // Don't run the expensive check, unless we have to.
-    if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
-      BlockHasCopyDispose = true;
-    // if not, allocate one now.
-    offset = getBlockOffset(E);
-  }
+  if (offset)
+    return offset;
+
+  // Don't run the expensive check, unless we have to.
+  if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
+    BlockHasCopyDispose = true;
+
+  // if not, allocate one now.
+  offset = getBlockOffset(E);
+
+  return offset;
+}
+
+llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+  const ValueDecl *VD = E->getDecl();
+  uint64_t offset = AllocateBlockDecl(E);
+  
 
   llvm::Value *BlockLiteral = LoadBlockStruct();
   llvm::Value *V = Builder.CreateGEP(BlockLiteral,
-                                  llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+                       llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
                                                          offset),
                                      "block.literal");
   if (E->isByRef()) {
@@ -633,12 +668,19 @@
 
   FunctionArgList Args;
 
+  CurFuncDecl = OuterFuncDecl;
+
   const BlockDecl *BD = BExpr->getBlockDecl();
 
-  IdentifierInfo *II
-    = &CGM.getContext().Idents.get(".block_descriptor");
+  IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
 
-  QualType ParmTy = getContext().getBlockParmType();
+  // Allocate all BlockDeclRefDecls, so we can calculate the the
+  // right ParmTy below.
+  // FIXME: Resolve testsuite problems, then enable.
+  if (0)
+    AllocateAllBlockDeclRefs(Info, this);
+
+  QualType ParmTy = getContext().getBlockParmType(BlockDeclRefDecls);
   // FIXME: This leaks
   ImplicitParamDecl *SelfDecl =
     ImplicitParamDecl::Create(getContext(), 0,
@@ -708,22 +750,6 @@
 
   FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc());
 
-  // And now finish off the type for the parameter, since now we know 
-  // BlockDeclRefDecls is complete.
-  getContext().completeBlockParmType(ParmTy, BlockDeclRefDecls);
-
-#define REV2
-#ifdef REV2
-  TagDecl *TD = ParmTy->getPointeeType()->getAs<RecordType>()->getDecl();
-  CGM.UpdateCompletedType(TD);
-#else
-  TagDecl *TD = ParmTy->getPointeeType()->getAs<RecordType>()->getDecl();
-  TagDecl::redecl_iterator rdi = TD->redecls_begin();
-  ++rdi;
-  TD = *rdi;
-  CGM.UpdateCompletedType(TD);
-#endif
-
   // The runtime needs a minimum alignment of a void *.
   uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
   BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign);
@@ -781,11 +807,13 @@
   FunctionArgList Args;
   // FIXME: This leaks
   ImplicitParamDecl *Dst =
-    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+    ImplicitParamDecl::Create(getContext(), 0,
+                              SourceLocation(), 0,
                               getContext().getPointerType(getContext().VoidTy));
   Args.push_back(std::make_pair(Dst, Dst->getType()));
   ImplicitParamDecl *Src =
-    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+    ImplicitParamDecl::Create(getContext(), 0,
+                              SourceLocation(), 0,
                               getContext().getPointerType(getContext().VoidTy));
   Args.push_back(std::make_pair(Src, Src->getType()));
 
@@ -866,7 +894,8 @@
   FunctionArgList Args;
   // FIXME: This leaks
   ImplicitParamDecl *Src =
-    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+    ImplicitParamDecl::Create(getContext(), 0,
+                              SourceLocation(), 0,
                               getContext().getPointerType(getContext().VoidTy));
 
   Args.push_back(std::make_pair(Src, Src->getType()));
@@ -945,13 +974,15 @@
   FunctionArgList Args;
   // FIXME: This leaks
   ImplicitParamDecl *Dst =
-    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+    ImplicitParamDecl::Create(getContext(), 0,
+                              SourceLocation(), 0,
                               getContext().getPointerType(getContext().VoidTy));
   Args.push_back(std::make_pair(Dst, Dst->getType()));
 
   // FIXME: This leaks
   ImplicitParamDecl *Src =
-    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+    ImplicitParamDecl::Create(getContext(), 0,
+                              SourceLocation(), 0,
                               getContext().getPointerType(getContext().VoidTy));
   Args.push_back(std::make_pair(Src, Src->getType()));
 
@@ -1014,7 +1045,8 @@
   FunctionArgList Args;
   // FIXME: This leaks
   ImplicitParamDecl *Src =
-    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+    ImplicitParamDecl::Create(getContext(), 0,
+                              SourceLocation(), 0,
                               getContext().getPointerType(getContext().VoidTy));
 
   Args.push_back(std::make_pair(Src, Src->getType()));