[cfe-commits] r66159 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/CodeGen/CGDecl.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/blocks-unsupported.m

Mike Stump mrs at apple.com
Thu Mar 5 00:32:30 PST 2009


Author: mrs
Date: Thu Mar  5 02:32:30 2009
New Revision: 66159

URL: http://llvm.org/viewvc/llvm-project?rev=66159&view=rev
Log:
prep work for copy/destroy helpers for block literals.

Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.h
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenObjC/blocks-unsupported.m

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=66159&r1=66158&r2=66159&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Mar  5 02:32:30 2009
@@ -30,8 +30,8 @@
               llvm::cl::desc("temporary option to turn on __block precessing "
                              "even though the code isn't done yet"),
               llvm::cl::ValueDisallowed, llvm::cl::AllowInverse,
-              llvm::cl::ZeroOrMore);
-
+              llvm::cl::ZeroOrMore,
+              llvm::cl::init(false));
 
 llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) {
   const llvm::Type *UnsignedLongTy
@@ -53,13 +53,13 @@
   if (BlockHasCopyDispose) {
     // copy_func_helper_decl
     // FIXME: implement
-    C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+    C = llvm::Constant::getNullValue(PtrToInt8Ty);
     C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
     Elts.push_back(C);
 
     // destroy_func_decl
     // FIXME: implement
-    C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+    C = llvm::Constant::getNullValue(PtrToInt8Ty);
     C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
     Elts.push_back(C);
   }
@@ -80,7 +80,7 @@
   // same thing as CreateRuntimeFunction if there's already a variable with the
   // same name.
   NSConcreteGlobalBlock
-    = new llvm::GlobalVariable(PtrToInt8Ty, false, 
+    = new llvm::GlobalVariable(PtrToInt8Ty, false,
                                llvm::GlobalValue::ExternalLinkage,
                                0, "_NSConcreteGlobalBlock",
                                &getModule());
@@ -96,7 +96,7 @@
   // same thing as CreateRuntimeFunction if there's already a variable with the
   // same name.
   NSConcreteStackBlock
-    = new llvm::GlobalVariable(PtrToInt8Ty, false, 
+    = new llvm::GlobalVariable(PtrToInt8Ty, false,
                                llvm::GlobalValue::ExternalLinkage,
                                0, "_NSConcreteStackBlock",
                                &getModule());
@@ -104,18 +104,18 @@
   return NSConcreteStackBlock;
 }
 
-static void CollectBlockDeclRefInfo(const Stmt *S, 
+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)
     if (*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
@@ -144,8 +144,8 @@
   // CGF, then we can just check to see if CGF is 0.
   if (0 && CanBlockBeGlobal(Info))
     return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
-    
-  std::vector<llvm::Constant*> Elts;
+
+  std::vector<llvm::Constant*> Elts(5);
   llvm::Constant *C;
   llvm::Value *V;
 
@@ -153,34 +153,41 @@
     // C = BuildBlockStructInitlist();
     unsigned int flags = BLOCK_HAS_DESCRIPTOR;
 
+    // We run this first so that we set BlockHasCopyDispose from the entire
+    // block literal.
+    // __invoke
+    uint64_t subBlockSize, subBlockAlign;
+    llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
+    llvm::Function *Fn
+      = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
+                                                   subBlockAlign,
+                                                   subBlockDeclRefDecls,
+                                                   BlockHasCopyDispose);
+    Elts[3] = Fn;
+
+    if (!Enable__block && BlockHasCopyDispose)
+      ErrorUnsupported(BE, "block literal that requires copy/dispose");
+
     if (BlockHasCopyDispose)
       flags |= BLOCK_HAS_COPY_DISPOSE;
 
     // __isa
     C = CGM.getNSConcreteStackBlock();
     C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
-    Elts.push_back(C);
+    Elts[0] = C;
 
     // __flags
     const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
       CGM.getTypes().ConvertType(CGM.getContext().IntTy));
     C = llvm::ConstantInt::get(IntTy, flags);
-    Elts.push_back(C);
+    Elts[1] = C;
 
     // __reserved
     C = llvm::ConstantInt::get(IntTy, 0);
-    Elts.push_back(C);
-
-    // __invoke
-    uint64_t subBlockSize, subBlockAlign;
-    llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
-    llvm::Function *Fn
-      = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
-                                                   subBlockAlign, subBlockDeclRefDecls);
-    Elts.push_back(Fn);
+    Elts[2] = C;
 
     // __descriptor
-    Elts.push_back(BuildDescriptorBlockDecl(subBlockSize));
+    Elts[4] = BuildDescriptorBlockDecl(subBlockSize);
 
     if (subBlockDeclRefDecls.size() == 0) {
       // Optimize to being a global block.
@@ -198,7 +205,7 @@
       C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
       return C;
     }
-      
+
     std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
     for (int i=0; i<5; ++i)
       Types[i] = Elts[i]->getType();
@@ -222,7 +229,7 @@
 
     for (unsigned i=0; i<5; ++i)
       Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
-    
+
     for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
       {
         // FIXME: Push const down.
@@ -254,7 +261,6 @@
                                                 false, false);
         }
         if (BDRE->isByRef()) {
-          // FIXME: __block in nested literals
           E = new (getContext())
             UnaryOperator(E, UnaryOperator::AddrOf,
                           getContext().getPointerType(E->getType()),
@@ -272,9 +278,9 @@
             // be done during Block_copy for us, and we can postpone the work
             // until then.
             uint64_t offset = BlockDecls[BDRE->getDecl()];
-            
+
             llvm::Value *BlockLiteral = LoadBlockStruct();
-            
+
             Loc = Builder.CreateGEP(BlockLiteral,
                                     llvm::ConstantInt::get(llvm::Type::Int64Ty,
                                                            offset),
@@ -296,7 +302,7 @@
         // the struct matches the previously computed offset in BlockDecls.
       }
   }
-  
+
   QualType BPT = BE->getType();
   return Builder.CreateBitCast(V, ConvertType(BPT));
 }
@@ -461,7 +467,7 @@
     ErrorUnsupported(E, "__block variable in block literal");
   else if (E->getType()->isBlockPointerType())
     ErrorUnsupported(E, "block pointer in block literal");
-  else if (E->getDecl()->getAttr<ObjCNSObjectAttr>() || 
+  else if (E->getDecl()->getAttr<ObjCNSObjectAttr>() ||
            getContext().isObjCNSObjectType(E->getType()))
     ErrorUnsupported(E, "__attribute__((NSObject)) variable in block "
                      "literal");
@@ -470,6 +476,9 @@
 
   // 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);
   }
@@ -532,18 +541,21 @@
   CodeGenFunction::BlockInfo Info(0, n);
   uint64_t subBlockSize, subBlockAlign;
   llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
+  bool subBlockHasCopyDispose;
   llvm::Function *Fn
     = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
                                                  subBlockAlign,
-                                                 subBlockDeclRefDecls);
+                                                 subBlockDeclRefDecls,
+                                                 subBlockHasCopyDispose);
   assert(subBlockSize == BlockLiteralSize
          && "no imports allowed for global block");
+  assert(!subBlockHasCopyDispose && "no imports allowed for global block");
 
   // isa
   LiteralFields[0] = getNSConcreteGlobalBlock();
 
   // Flags
-  LiteralFields[1] = 
+  LiteralFields[1] =
     llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
 
   // Reserved
@@ -571,11 +583,13 @@
   return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
 }
 
-llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
-                                                       const BlockInfo& Info,
-                                                       uint64_t &Size,
-                                                       uint64_t &Align,
-                         llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls) {
+llvm::Function *
+CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
+                                       const BlockInfo& Info,
+                                       uint64_t &Size,
+                                       uint64_t &Align,
+                       llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls,
+                                       bool &subBlockHasCopyDispose) {
   const FunctionProtoType *FTy =
     cast<FunctionProtoType>(BExpr->getFunctionType());
 
@@ -620,7 +634,7 @@
   Size = BlockOffset;
   Align = BlockAlign;
   subBlockDeclRefDecls = BlockDeclRefDecls;
-
+  subBlockHasCopyDispose |= BlockHasCopyDispose;
   return Fn;
 }
 
@@ -642,7 +656,7 @@
   // Ensure proper alignment, even if it means we have to have a gap
   BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align);
   BlockAlign = std::max(Align, BlockAlign);
-      
+
   uint64_t Pad = BlockOffset - OldOffset;
   if (Pad) {
     llvm::ArrayType::get(llvm::Type::Int8Ty, Pad);
@@ -687,7 +701,7 @@
     ArgTys.push_back(PtrToInt8Ty);
     ArgTys.push_back(llvm::Type::Int32Ty);
     FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
-    CGM.BlockObjectDispose  
+    CGM.BlockObjectDispose
       = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
   }
   return CGM.BlockObjectDispose;
@@ -702,3 +716,5 @@
   N = llvm::ConstantInt::get(llvm::Type::Int32Ty, BLOCK_FIELD_IS_BYREF);
   Builder.CreateCall2(F, V, N);
 }
+
+ASTContext &BlockFunction::getContext() const { return CGM.getContext(); }

Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=66159&r1=66158&r2=66159&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.h Thu Mar  5 02:32:30 2009
@@ -110,6 +110,7 @@
 
 class BlockFunction : public BlockBase {
   CodeGenModule &CGM;
+  ASTContext &getContext() const;
 
 public:
   const llvm::Type *PtrToInt8Ty;
@@ -160,6 +161,14 @@
 
   llvm::Value *getBlockObjectDispose();
   void BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr);
+
+  bool BlockRequiresCopying(QualType Ty) {
+    if (Ty->isBlockPointerType())
+      return true;
+    if (getContext().isObjCNSObjectType(Ty))
+      return true;
+    return false;
+  }
 };
 
 }  // end namespace CodeGen

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=66159&r1=66158&r2=66159&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Mar  5 02:32:30 2009
@@ -338,6 +338,9 @@
     int flag = 0;
     int flags = 0;
 
+    // The block literal will need a copy/destroy helper.
+    BlockHasCopyDispose = true;
+
     if (Ty->isBlockPointerType()) {
       flag |= BLOCK_FIELD_IS_BLOCK;
       flags |= BLOCK_HAS_COPY_DISPOSE;
@@ -360,11 +363,15 @@
     V = llvm::ConstantInt::get(llvm::Type::Int32Ty, flags);
     Builder.CreateStore(V, flags_field);
 
-    const llvm::Type *V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
-    V = llvm::ConstantInt::get(llvm::Type::Int32Ty, CGM.getTargetData().getTypeStoreSizeInBits(V1) / 8);
+    const llvm::Type *V1;
+    V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
+    V = llvm::ConstantInt::get(llvm::Type::Int32Ty,
+                               (CGM.getTargetData().getTypeStoreSizeInBits(V1)
+                                / 8));
     Builder.CreateStore(V, size_field);
 
     if (flags & BLOCK_HAS_COPY_DISPOSE) {
+      BlockHasCopyDispose = true;
       llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
       llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=66159&r1=66158&r2=66159&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Mar  5 02:32:30 2009
@@ -271,8 +271,8 @@
   llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr,
                                         const BlockInfo& Info,
                                         uint64_t &Size, uint64_t &Align,
-                                        llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls);
-
+                      llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls,
+                                        bool &subBlockHasCopyDispose);
 
   llvm::Value *LoadBlockStruct();
 
@@ -288,6 +288,7 @@
   uint64_t BlockOffset;
   /// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
   uint64_t BlockAlign;
+
   /// getBlockOffset - Allocate an offset for the ValueDecl from a
   /// BlockDeclRefExpr in a block literal (BlockExpr).
   uint64_t getBlockOffset(const BlockDeclRefExpr *E);
@@ -298,13 +299,6 @@
   llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
 
   const llvm::Type *BuildByRefType(QualType Ty, uint64_t Align);
-  bool BlockRequiresCopying(QualType Ty) {
-    if (Ty->isBlockPointerType())
-      return true;
-    if (getContext().isObjCNSObjectType(Ty))
-      return true;
-    return false;
-  }
 
   void GenerateCode(const FunctionDecl *FD,
                     llvm::Function *Fn);

Modified: cfe/trunk/test/CodeGenObjC/blocks-unsupported.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks-unsupported.m?rev=66159&r1=66158&r2=66159&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenObjC/blocks-unsupported.m (original)
+++ cfe/trunk/test/CodeGenObjC/blocks-unsupported.m Thu Mar  5 02:32:30 2009
@@ -5,30 +5,28 @@
 
 void t1()
 {
-	__block int a;
-	^{ a = 10; }(); // expected-error {{cannot compile this __block variable in block literal yet}}
-	
-	void (^block)(void);
-    ^{ (void)block; }(); // expected-error {{}}
-
-    struct Foo *__attribute__ ((NSObject)) foo;
-    ^{ (void)foo; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}}
-    
-    typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef;
-    CGColorRef color;
-    ^{ (void)color; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}}
-    
-    id a1;
-    ^{ (void)a1; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-    
-    Foo *a2;
-    ^{ (void)a2; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-    
-    id<P> a3;
-    ^{ (void)a3; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-
-    Foo<P> *a4;
-    ^{ (void)a4; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-    
-    
+  __block int a;
+  ^{ a = 10; }(); // expected-error {{cannot compile this __block variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  void (^block)(void);
+  ^{ (void)block; }(); // expected-error {{cannot compile this block pointer in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  struct Foo *__attribute__ ((NSObject)) foo;
+  ^{ (void)foo; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef;
+  CGColorRef color;
+  ^{ (void)color; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  id a1;
+  ^{ (void)a1; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  Foo *a2;
+  ^{ (void)a2; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  id<P> a3;
+  ^{ (void)a3; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+  Foo<P> *a4;
+  ^{ (void)a4; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
 }





More information about the cfe-commits mailing list