[cfe-commits] r128608 - in /cfe/trunk/lib/CodeGen: CGBlocks.cpp CGDecl.cpp CodeGenFunction.h

John McCall rjmccall at apple.com
Wed Mar 30 18:59:53 PDT 2011


Author: rjmccall
Date: Wed Mar 30 20:59:53 2011
New Revision: 128608

URL: http://llvm.org/viewvc/llvm-project?rev=128608&view=rev
Log:
Move all the significant __block code into CGBlocks.cpp.  No functionality
change.


Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGDecl.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=128608&r1=128607&r2=128608&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Wed Mar 30 20:59:53 2011
@@ -1384,6 +1384,186 @@
   return Entry;
 }
 
+unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
+  assert(ByRefValueInfo.count(VD) && "Did not find value!");
+  
+  return ByRefValueInfo.find(VD)->second.second;
+}
+
+llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
+                                                     const VarDecl *V) {
+  llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
+  Loc = Builder.CreateLoad(Loc);
+  Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
+                                V->getNameAsString());
+  return Loc;
+}
+
+/// BuildByRefType - This routine changes a __block variable declared as T x
+///   into:
+///
+///      struct {
+///        void *__isa;
+///        void *__forwarding;
+///        int32_t __flags;
+///        int32_t __size;
+///        void *__copy_helper;       // only if needed
+///        void *__destroy_helper;    // only if needed
+///        char padding[X];           // only if needed
+///        T x;
+///      } x
+///
+const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) {
+  std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D];
+  if (Info.first)
+    return Info.first;
+  
+  QualType Ty = D->getType();
+
+  std::vector<const llvm::Type *> Types;
+  
+  llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext());
+  
+  // void *__isa;
+  Types.push_back(Int8PtrTy);
+  
+  // void *__forwarding;
+  Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder));
+  
+  // int32_t __flags;
+  Types.push_back(Int32Ty);
+    
+  // int32_t __size;
+  Types.push_back(Int32Ty);
+
+  bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty);
+  if (HasCopyAndDispose) {
+    /// void *__copy_helper;
+    Types.push_back(Int8PtrTy);
+    
+    /// void *__destroy_helper;
+    Types.push_back(Int8PtrTy);
+  }
+
+  bool Packed = false;
+  CharUnits Align = getContext().getDeclAlign(D);
+  if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) {
+    // We have to insert padding.
+    
+    // The struct above has 2 32-bit integers.
+    unsigned CurrentOffsetInBytes = 4 * 2;
+    
+    // And either 2 or 4 pointers.
+    CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) *
+      CGM.getTargetData().getTypeAllocSize(Int8PtrTy);
+    
+    // Align the offset.
+    unsigned AlignedOffsetInBytes = 
+      llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity());
+    
+    unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
+    if (NumPaddingBytes > 0) {
+      const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext());
+      // FIXME: We need a sema error for alignment larger than the minimum of
+      // the maximal stack alignmint and the alignment of malloc on the system.
+      if (NumPaddingBytes > 1)
+        Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
+    
+      Types.push_back(Ty);
+
+      // We want a packed struct.
+      Packed = true;
+    }
+  }
+
+  // T x;
+  Types.push_back(ConvertTypeForMem(Ty));
+  
+  const llvm::Type *T = llvm::StructType::get(getLLVMContext(), Types, Packed);
+  
+  cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T);
+  CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), 
+                              ByRefTypeHolder.get());
+  
+  Info.first = ByRefTypeHolder.get();
+  
+  Info.second = Types.size() - 1;
+  
+  return Info.first;
+}
+
+/// Initialize the structural components of a __block variable, i.e.
+/// everything but the actual object.
+void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
+  llvm::Value *V;
+
+  BlockFieldFlags fieldFlags;
+  bool fieldNeedsCopyDispose = false;
+
+  const VarDecl &D = *emission.Variable;
+  QualType type = D.getType();
+
+  if (type->isBlockPointerType()) {
+    fieldFlags |= BLOCK_FIELD_IS_BLOCK;
+    fieldNeedsCopyDispose = true;
+  } else if (getContext().isObjCNSObjectType(type) || 
+             type->isObjCObjectPointerType()) {
+    fieldFlags |= BLOCK_FIELD_IS_OBJECT;
+    fieldNeedsCopyDispose = true;
+  } else if (getLangOptions().CPlusPlus) {
+    if (getContext().getBlockVarCopyInits(&D))
+      fieldNeedsCopyDispose = true;
+    else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
+      fieldNeedsCopyDispose = !record->hasTrivialDestructor();
+  }
+
+  llvm::Value *addr = emission.Address;
+
+  // FIXME: Someone double check this.
+  if (type.isObjCGCWeak())
+    fieldFlags |= BLOCK_FIELD_IS_WEAK;
+
+  // Initialize the 'isa', which is just 0 or 1.
+  int isa = 0;
+  if (fieldFlags & BLOCK_FIELD_IS_WEAK)
+    isa = 1;
+  V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
+  Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
+
+  // Store the address of the variable into its own forwarding pointer.
+  Builder.CreateStore(addr,
+                      Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
+
+  // Blocks ABI:
+  //   c) the flags field is set to either 0 if no helper functions are
+  //      needed or BLOCK_HAS_COPY_DISPOSE if they are,
+  BlockFlags flags;
+  if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
+  Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+                      Builder.CreateStructGEP(addr, 2, "byref.flags"));
+
+  const llvm::Type *V1;
+  V1 = cast<llvm::PointerType>(addr->getType())->getElementType();
+  V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
+  Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
+
+  if (fieldNeedsCopyDispose) {
+    CharUnits alignment = emission.Alignment;
+
+    llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
+    Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags,
+                                                 alignment.getQuantity(), &D),
+                        copy_helper);
+
+    llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
+    Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(),
+                                                    fieldFlags,
+                                                    alignment.getQuantity(),
+                                                    &D),
+                        destroy_helper);
+  }
+}
+
 void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
   llvm::Value *F = CGM.getBlockObjectDispose();
   llvm::Value *N;
@@ -1391,3 +1571,26 @@
   N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask());
   Builder.CreateCall2(F, V, N);
 }
+
+namespace {
+  struct CallBlockRelease : EHScopeStack::Cleanup {
+    llvm::Value *Addr;
+    CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
+
+    void Emit(CodeGenFunction &CGF, bool IsForEH) {
+      CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
+    }
+  };
+}
+
+/// Enter a cleanup to destroy a __block variable.  Note that this
+/// cleanup should be a no-op if the variable hasn't left the stack
+/// yet; if a cleanup is required for the variable itself, that needs
+/// to be done externally.
+void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
+  // We don't enter this cleanup if we're in pure-GC mode.
+  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
+    return;
+
+  EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
+}

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=128608&r1=128607&r2=128608&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Wed Mar 30 20:59:53 2011
@@ -14,7 +14,6 @@
 #include "CGDebugInfo.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
-#include "CGBlocks.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/Decl.h"
@@ -302,114 +301,6 @@
   }
 }
 
-unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
-  assert(ByRefValueInfo.count(VD) && "Did not find value!");
-  
-  return ByRefValueInfo.find(VD)->second.second;
-}
-
-llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
-                                                     const VarDecl *V) {
-  llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
-  Loc = Builder.CreateLoad(Loc);
-  Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
-                                V->getNameAsString());
-  return Loc;
-}
-
-/// BuildByRefType - This routine changes a __block variable declared as T x
-///   into:
-///
-///      struct {
-///        void *__isa;
-///        void *__forwarding;
-///        int32_t __flags;
-///        int32_t __size;
-///        void *__copy_helper;       // only if needed
-///        void *__destroy_helper;    // only if needed
-///        char padding[X];           // only if needed
-///        T x;
-///      } x
-///
-const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) {
-  std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D];
-  if (Info.first)
-    return Info.first;
-  
-  QualType Ty = D->getType();
-
-  std::vector<const llvm::Type *> Types;
-  
-  llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext());
-  
-  // void *__isa;
-  Types.push_back(Int8PtrTy);
-  
-  // void *__forwarding;
-  Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder));
-  
-  // int32_t __flags;
-  Types.push_back(Int32Ty);
-    
-  // int32_t __size;
-  Types.push_back(Int32Ty);
-
-  bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty);
-  if (HasCopyAndDispose) {
-    /// void *__copy_helper;
-    Types.push_back(Int8PtrTy);
-    
-    /// void *__destroy_helper;
-    Types.push_back(Int8PtrTy);
-  }
-
-  bool Packed = false;
-  CharUnits Align = getContext().getDeclAlign(D);
-  if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) {
-    // We have to insert padding.
-    
-    // The struct above has 2 32-bit integers.
-    unsigned CurrentOffsetInBytes = 4 * 2;
-    
-    // And either 2 or 4 pointers.
-    CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) *
-      CGM.getTargetData().getTypeAllocSize(Int8PtrTy);
-    
-    // Align the offset.
-    unsigned AlignedOffsetInBytes = 
-      llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity());
-    
-    unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
-    if (NumPaddingBytes > 0) {
-      const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext());
-      // FIXME: We need a sema error for alignment larger than the minimum of
-      // the maximal stack alignmint and the alignment of malloc on the system.
-      if (NumPaddingBytes > 1)
-        Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
-    
-      Types.push_back(Ty);
-
-      // We want a packed struct.
-      Packed = true;
-    }
-  }
-
-  // T x;
-  Types.push_back(ConvertTypeForMem(Ty));
-  
-  const llvm::Type *T = llvm::StructType::get(getLLVMContext(), Types, Packed);
-  
-  cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T);
-  CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), 
-                              ByRefTypeHolder.get());
-  
-  Info.first = ByRefTypeHolder.get();
-  
-  Info.second = Types.size() - 1;
-  
-  return Info.first;
-}
-
 namespace {
   struct CallArrayDtor : EHScopeStack::Cleanup {
     CallArrayDtor(const CXXDestructorDecl *Dtor, 
@@ -505,15 +396,6 @@
       CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args);
     }
   };
-
-  struct CallBlockRelease : EHScopeStack::Cleanup {
-    llvm::Value *Addr;
-    CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
-
-    void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
-    }
-  };
 }
 
 
@@ -803,75 +685,14 @@
     EnsureInsertPoint();
   }
 
-  CharUnits alignment = emission.Alignment;
-
-  if (emission.IsByRef) {
-    llvm::Value *V;
-
-    BlockFieldFlags fieldFlags;
-    bool fieldNeedsCopyDispose = false;
-
-    if (type->isBlockPointerType()) {
-      fieldFlags |= BLOCK_FIELD_IS_BLOCK;
-      fieldNeedsCopyDispose = true;
-    } else if (getContext().isObjCNSObjectType(type) || 
-               type->isObjCObjectPointerType()) {
-      fieldFlags |= BLOCK_FIELD_IS_OBJECT;
-      fieldNeedsCopyDispose = true;
-    } else if (getLangOptions().CPlusPlus) {
-      if (getContext().getBlockVarCopyInits(&D))
-        fieldNeedsCopyDispose = true;
-      else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
-        fieldNeedsCopyDispose = !record->hasTrivialDestructor();
-    }
-
-    llvm::Value *addr = emission.Address;
-
-    // FIXME: Someone double check this.
-    if (type.isObjCGCWeak())
-      fieldFlags |= BLOCK_FIELD_IS_WEAK;
-
-    // Initialize the 'isa', which is just 0 or 1.
-    int isa = 0;
-    if (fieldFlags & BLOCK_FIELD_IS_WEAK)
-      isa = 1;
-    V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
-    Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
-
-    // Store the address of the variable into its own forwarding pointer.
-    Builder.CreateStore(addr,
-                        Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
-
-    // Blocks ABI:
-    //   c) the flags field is set to either 0 if no helper functions are
-    //      needed or BLOCK_HAS_COPY_DISPOSE if they are,
-    BlockFlags flags;
-    if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
-    Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
-                        Builder.CreateStructGEP(addr, 2, "byref.flags"));
-
-    const llvm::Type *V1;
-    V1 = cast<llvm::PointerType>(addr->getType())->getElementType();
-    V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
-    Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
-
-    if (fieldNeedsCopyDispose) {
-      llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
-      Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags,
-                                                   alignment.getQuantity(), &D),
-                          copy_helper);
-
-      llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
-      Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(),
-                                                      fieldFlags,
-                                                      alignment.getQuantity(),
-                                                      &D),
-                          destroy_helper);
-    }
-  }
+  // Initialize the structure of a __block variable.
+  if (emission.IsByRef)
+    emitByrefStructureInit(emission);
 
   if (!Init) return;
 
+  CharUnits alignment = emission.Alignment;
+
   // Check whether this is a byref variable that's potentially
   // captured and moved by its own initializer.  If so, we'll need to
   // emit the initializer first, then copy into the variable.
@@ -1020,9 +841,8 @@
 
   // If this is a block variable, call _Block_object_destroy
   // (on the unforwarded address).
-  if (emission.IsByRef &&
-      CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
-    EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
+  if (emission.IsByRef)
+    enterByrefCleanup(emission);
 }
 
 /// Emit an alloca (or GlobalValue depending on target)

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=128608&r1=128607&r2=128608&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Mar 30 20:59:53 2011
@@ -1116,6 +1116,11 @@
 
   void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags);
 
+  class AutoVarEmission;
+
+  void emitByrefStructureInit(const AutoVarEmission &emission);
+  void enterByrefCleanup(const AutoVarEmission &emission);
+
   llvm::Value *LoadBlockStruct() {
     assert(BlockPointer && "no block pointer set!");
     return BlockPointer;





More information about the cfe-commits mailing list