[cfe-commits] r65487 - in /cfe/trunk/lib/CodeGen: CGBlocks.cpp CGExprConstant.cpp CGExprScalar.cpp CodeGenFunction.cpp CodeGenFunction.h

Mike Stump mrs at apple.com
Wed Feb 25 15:33:14 PST 2009


Author: mrs
Date: Wed Feb 25 17:33:13 2009
New Revision: 65487

URL: http://llvm.org/viewvc/llvm-project?rev=65487&view=rev
Log:
CodeGen support for copied BlockDeclRefExprs.

Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Wed Feb 25 17:33:13 2009
@@ -109,13 +109,14 @@
 
 // FIXME: Push most into CGM, passing down a few bits, like current
 // function name.
-llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
+llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
   bool insideFunction = false;
   bool BlockRefDeclList = false;
   bool BlockByrefDeclList = false;
 
   std::vector<llvm::Constant*> Elts;
   llvm::Constant *C;
+  llvm::Value *V;
 
   {
     // C = BuildBlockStructInitlist();
@@ -152,32 +153,77 @@
       if (ND->getIdentifier())
         Name = ND->getNameAsCString();
     BlockInfo Info(0, Name);
-    uint64_t subBlockSize;
+    uint64_t subBlockSize, subBlockAlign;
+    llvm::SmallVector<ValueDecl *, 8> subBlockDeclRefDecls;
     llvm::Function *Fn
-      = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize);
+      = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
+                                                   subBlockAlign, subBlockDeclRefDecls);
     Elts.push_back(Fn);
 
     // __descriptor
     Elts.push_back(BuildDescriptorBlockDecl(subBlockSize));
 
-    // FIXME: Add block_original_ref_decl_list and block_byref_decl_list.
+    // FIXME: Also check to make sure there are no byref variables
+    if (subBlockDeclRefDecls.size() == 0) {
+      C = llvm::ConstantStruct::get(Elts);
+
+      char Name[32];
+      sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
+      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;
+    }
+      
+    std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
+    for (int i=0; i<5; ++i)
+      Types[i] = Elts[i]->getType();
+
+    for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
+      Types[i+5] = ConvertType(subBlockDeclRefDecls[i]->getType());
+
+    llvm::Type *Ty = llvm::StructType::get(Types, true);
+
+    llvm::AllocaInst *A = CreateTempAlloca(Ty);
+    A->setAlignment(subBlockAlign);
+    V = A;
+
+    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)
+      {
+        ValueDecl *VD = subBlockDeclRefDecls[i];
+
+        if (VD->getIdentifier() == 0)
+            continue;
+        SourceLocation Loc = VD->getLocation();
+        DeclRefExpr D(VD, VD->getType(), Loc);
+        llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
+        RValue r = EmitAnyExpr(&D, Addr, false);
+        if (r.isScalar())
+          Builder.CreateStore(r.getScalarVal(), Addr);
+        else if (r.isComplex())
+          // FIXME: implement
+          ErrorUnsupported(BE, "complex in block literal");
+        else if (r.isAggregate())
+          ; // Already created into the destination
+        else
+          assert (0 && "bad block variable");
+        // FIXME: Ensure that the offset created by the backend for
+        // the struct matches the previously computed offset in BlockDecls.
+      }
+
+    // FIXME: Add block_byref_decl_list.
   }
   
-  C = llvm::ConstantStruct::get(Elts);
-
-  char Name[32];
-  sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
-  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;
+  return Builder.CreateBitCast(V, ConvertType(BPT));
 }
 
 
-
-
 const llvm::Type *CodeGenModule::getBlockDescriptorType() {
   if (BlockDescriptorType)
     return BlockDescriptorType;
@@ -365,9 +411,12 @@
   llvm::Constant *LiteralFields[5];
 
   CodeGenFunction::BlockInfo Info(0, n);
-  uint64_t subBlockSize;
+  uint64_t subBlockSize, subBlockAlign;
+  llvm::SmallVector<ValueDecl *, 8> subBlockDeclRefDecls;
   llvm::Function *Fn
-    = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize);
+    = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize,
+                                                   subBlockAlign,
+                                                   subBlockDeclRefDecls);
   assert(subBlockSize == BlockLiteralSize
          && "no imports allowed for global block");
 
@@ -404,7 +453,9 @@
 
 llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr,
                                                        const BlockInfo& Info,
-                                                       uint64_t &Size) {
+                                                       uint64_t &Size,
+                                                       uint64_t &Align,
+                                                       llvm::SmallVector<ValueDecl *, 8> &subBlockDeclRefDecls) {
   const FunctionTypeProto *FTy =
     cast<FunctionTypeProto>(Expr->getFunctionType());
 
@@ -442,7 +493,13 @@
   EmitStmt(Expr->getBody());
   FinishFunction(cast<CompoundStmt>(Expr->getBody())->getRBracLoc());
 
+  // The runtime needs a minimum alignment of a void *.
+  uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
+  BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign);
+
   Size = BlockOffset;
+  Align = BlockAlign;
+  subBlockDeclRefDecls = BlockDeclRefDecls;
 
   return Fn;
 }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Feb 25 17:33:13 2009
@@ -452,7 +452,7 @@
     case Expr::BlockExprClass: {
       BlockExpr *B = cast<BlockExpr>(E);
       if (!B->hasBlockDeclRefExprs())
-        return CGF->BuildBlockLiteralTmp(B);
+        return cast<llvm::Constant>(CGF->BuildBlockLiteralTmp(B));
     }
     }
 

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed Feb 25 17:33:13 2009
@@ -607,11 +607,7 @@
     return VisitExpr(E);
   }
 
-  // FIXME: We have most of the easy codegen for the helper, but we need to
-  // ensure we don't need copy/dispose, and we need to add the variables into
-  // the block literal still.
-  CGF.ErrorUnsupported(E, "scalar expression");
-
+  // FIXME: ensure we don't need copy/dispose.
   uint64_t &offset = CGF.BlockDecls[E->getDecl()];
 
   const llvm::Type *Ty;
@@ -1389,8 +1385,8 @@
 }
 
 Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) {
-  llvm::Constant *C = CGF.BuildBlockLiteralTmp(BE);
-  return C;
+  llvm::Value *V = CGF.BuildBlockLiteralTmp(BE);
+  return V;
 }
 
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Feb 25 17:33:13 2009
@@ -38,6 +38,7 @@
   else
     BlockOffset = CGM.getTargetData()
       .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8;
+  BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
 }
 
 ASTContext &CodeGenFunction::getContext() const {

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Feb 25 17:33:13 2009
@@ -264,7 +264,7 @@
   //                                  Block Bits
   //===--------------------------------------------------------------------===//
 
-  llvm::Constant *BuildBlockLiteralTmp(const BlockExpr *);
+  llvm::Value *BuildBlockLiteralTmp(const BlockExpr *);
   llvm::Constant *BuildDescriptorBlockDecl(uint64_t Size);
 
   /// BlockInfo - Information to generate a block literal.
@@ -281,7 +281,8 @@
 
   llvm::Function *GenerateBlockFunction(const BlockExpr *Expr,
                                         const BlockInfo& Info,
-                                        uint64_t &Size);
+                                        uint64_t &Size, uint64_t &Align,
+                                        llvm::SmallVector<ValueDecl *, 8> &subBlockDeclRefDecls);
 
   ImplicitParamDecl *BlockStructDecl;
 
@@ -292,22 +293,41 @@
   /// BlockHasCopyDispose - True iff the block uses copy/dispose.
   bool BlockHasCopyDispose;
 
+  /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
+  /// in a block literal.  Decls without names are used for padding.
+  llvm::SmallVector<ValueDecl *, 8> BlockDeclRefDecls;
+
+  /// BlockOffset - The offset in bytes for the next allocation of an
+  /// imported block variable.
   uint64_t BlockOffset;
-  /// getBlockOffset - Offset for next allocated variable use in a BlockExpr.
-  uint64_t getBlockOffset(uint64_t Size, uint64_t Align) {
-    assert (((Align >> 3) > 0) && "alignment must be 1 byte or more");
-    assert (((Align & 7) == 0)
-            && "alignment must be on at least byte boundaries");
+  /// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
+  uint64_t BlockAlign;
+  /// getBlockOffset - Offset for next allocated variable used in a BlockExpr.
+  uint64_t getBlockOffset(ValueDecl *D) {
+    uint64_t Size = getContext().getTypeSize(D->getType()) / 8;
+    uint64_t Align = getContext().getDeclAlignInBytes(D);
+
+    assert ((Align > 0) && "alignment must be 1 byte or more");
+
+    uint64_t OldOffset = BlockOffset;
+
     // Ensure proper alignment, even if it means we have to have a gap
-    BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align/8);
+    BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align);
+    BlockAlign = std::max(Align, BlockAlign);
       
+    uint64_t Pad = BlockOffset - OldOffset;
+    llvm::ArrayType::get(llvm::Type::Int8Ty, Pad);
+    QualType PadTy = getContext().getConstantArrayType(getContext().CharTy,
+                                                       llvm::APInt(32, Pad),
+                                                       ArrayType::Normal, 0);
+    ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(),
+                                         0, QualType(PadTy), VarDecl::None, SourceLocation());
+    BlockDeclRefDecls.push_back(PadDecl);
+    BlockDeclRefDecls.push_back(D);
+
     BlockOffset += Size;
     return BlockOffset-Size;
   }
-  uint64_t getBlockOffset(ValueDecl *D) {
-    uint64_t Size = getContext().getTypeSize(D->getType()) / 8;
-    return getBlockOffset(Size, getContext().getDeclAlignInBytes(D)*8);
-  }
   std::map<Decl*, uint64_t> BlockDecls;
 
   void GenerateCode(const FunctionDecl *FD,





More information about the cfe-commits mailing list