More codegen for blocks.  The type of block literals should be better.
The size calculation is improved.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64994 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index ee698d6..d573236 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -260,6 +260,7 @@
   APValue VisitAddrLabelExpr(AddrLabelExpr *E)
       { return APValue(E, 0); }
   APValue VisitCallExpr(CallExpr *E);
+  APValue VisitBlockExpr(BlockExpr *E) { return APValue(E, 0); }
   APValue VisitConditionalOperator(ConditionalOperator *E);
 };
 } // end anonymous namespace
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 4a94096..9a130d7 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -46,8 +46,13 @@
   Elts.push_back(C);
 
   // Size
-  int sz = CGM.getTargetData()
-    .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
+  int sz;
+  if (!BlockHasCopyDispose)
+    sz = CGM.getTargetData()
+      .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
+  else
+    sz = CGM.getTargetData()
+      .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8;
   C = llvm::ConstantInt::get(UnsignedLongTy, sz);
   Elts.push_back(C);
 
@@ -107,6 +112,8 @@
   return NSConcreteStackBlock;
 }
 
+// FIXME: Push most into CGM, passing down a few bits, like current
+// function name.
 llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
   // FIXME: Push up
   bool BlockHasCopyDispose = false;
@@ -146,7 +153,7 @@
     C = llvm::ConstantInt::get(IntTy, 0);
     Elts.push_back(C);
 
-    // __FuncPtr
+    // __invoke
     const char *Name = "";
     if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurFuncDecl))
       if (ND->getIdentifier())
@@ -168,6 +175,8 @@
   C = new llvm::GlobalVariable(C->getType(), true,
                                llvm::GlobalValue::InternalLinkage,
                                C, Name, &CGM.getModule());
+  QualType BPT = BE->getType();
+  C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
   return C;
 }
 
@@ -210,11 +219,11 @@
     getTypes().ConvertType(getContext().IntTy));
 
   // struct __block_literal_generic {
-  //   void *isa;
-  //   int flags;
-  //   int reserved;
-  //   void (*invoke)(void *);
-  //   struct __block_descriptor *descriptor;
+  //   void *__isa;
+  //   int __flags;
+  //   int __reserved;
+  //   void (*__invoke)(void *);
+  //   struct __block_descriptor *__descriptor;
   // };
   GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy,
                                                   IntTy,
@@ -229,6 +238,44 @@
   return GenericBlockLiteralType;
 }
 
+const llvm::Type *
+CodeGenModule::getGenericExtendedBlockLiteralType() {
+  if (GenericExtendedBlockLiteralType)
+    return GenericExtendedBlockLiteralType;
+
+  const llvm::Type *Int8PtrTy =
+    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+
+  const llvm::Type *BlockDescPtrTy =
+    llvm::PointerType::getUnqual(getBlockDescriptorType());
+
+  const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
+    getTypes().ConvertType(getContext().IntTy));
+
+  // struct __block_literal_generic {
+  //   void *__isa;
+  //   int __flags;
+  //   int __reserved;
+  //   void (*__invoke)(void *);
+  //   struct __block_descriptor *__descriptor;
+  //   void *__copy_func_helper_decl;
+  //   void *__destroy_func_decl;
+  // };
+  GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy,
+                                                          IntTy,
+                                                          IntTy,
+                                                          Int8PtrTy,
+                                                          BlockDescPtrTy,
+                                                          Int8PtrTy,
+                                                          Int8PtrTy,
+                                                          NULL);
+
+  getModule().addTypeName("struct.__block_literal_extended_generic",
+                          GenericExtendedBlockLiteralType);
+
+  return GenericExtendedBlockLiteralType;
+}
+
 /// getBlockFunctionType - Given a BlockPointerType, will return the
 /// function type for the block, including the first block literal argument.
 static QualType getBlockFunctionType(ASTContext &Ctx,
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 15dab8f..651a283 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -614,6 +614,9 @@
       std::string S(Literal->getStrData(), Literal->getByteLength());
       return CGM.GetAddrOfConstantCFString(S);
     }
+    case Expr::BlockExprClass: {
+      return CGF->BuildBlockLiteralTmp(cast<BlockExpr>(E));
+    }
     }
 
     return 0;
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 4b185f6..eb13457 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1364,10 +1364,7 @@
 
 Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) {
   llvm::Constant *C = CGF.BuildBlockLiteralTmp(BE);
-
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
-  return llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
+  return C;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 24453cc..b7d3aa9 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -145,6 +145,7 @@
   
   const llvm::Type *BlockDescriptorType;
   const llvm::Type *GenericBlockLiteralType;
+  const llvm::Type *GenericExtendedBlockLiteralType;
   struct {
     int GlobalUniqueCount;
   } Block;
@@ -166,6 +167,7 @@
   const llvm::Type *getBlockDescriptorType();
 
   const llvm::Type *getGenericBlockLiteralType();
+  const llvm::Type *getGenericExtendedBlockLiteralType();
 
   /// getObjCRuntime() - Return a reference to the configured
   /// Objective-C runtime.