[cfe-commits] r81602 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp test/CodeGen/blocks-aligned-byref-variable.c

Anders Carlsson andersca at mac.com
Fri Sep 11 19:44:18 PDT 2009


Author: andersca
Date: Fri Sep 11 21:44:18 2009
New Revision: 81602

URL: http://llvm.org/viewvc/llvm-project?rev=81602&view=rev
Log:
Add support for __block variables with alignment greater than __alignof(void *).

Added:
    cfe/trunk/test/CodeGen/blocks-aligned-byref-variable.c
Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Sep 11 21:44:18 2009
@@ -227,11 +227,9 @@
             NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF |
               // FIXME: Someone double check this.
               (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0);
-            const llvm::Type *Ty = Types[i+5];
             llvm::Value *Loc = LocalDeclMap[VD];
             Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
             Loc = Builder.CreateLoad(Loc, false);
-            Loc = Builder.CreateBitCast(Loc, Ty);
             Builder.CreateStore(Loc, Addr);
             ++helpersize;
             continue;

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Sep 11 21:44:18 2009
@@ -224,41 +224,76 @@
     return Info.first;
   
   QualType Ty = D->getType();
-  uint64_t Align = getContext().getDeclAlignInBytes(D);
-  (void) Align;
 
-  const llvm::Type *LTy = ConvertType(Ty);
-  bool needsCopyDispose = BlockRequiresCopying(Ty);
-  std::vector<const llvm::Type *> Types(needsCopyDispose*2+5);
-  const llvm::PointerType *PtrToInt8Ty
-    = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext));
+  std::vector<const llvm::Type *> Types;
   
+  const llvm::PointerType *Int8PtrTy
+    = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext));
+
   llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(VMContext);
   
-  Types[0] = PtrToInt8Ty;
-  Types[1] = llvm::PointerType::getUnqual(ByRefTypeHolder);
-  Types[2] = llvm::Type::getInt32Ty(VMContext);
-  Types[3] = llvm::Type::getInt32Ty(VMContext);
-  if (needsCopyDispose) {
-    Types[4] = PtrToInt8Ty;
-    Types[5] = PtrToInt8Ty;
-  }
-  // FIXME: Align this on at least an Align boundary, assert if we can't.
-  assert((Align <= unsigned(Target.getPointerAlign(0))/8)
-         && "Can't align more than pointer yet");
+  // void *__isa;
+  Types.push_back(Int8PtrTy);
   
-  unsigned FieldNumber = needsCopyDispose*2 + 4;
+  // void *__forwarding;
+  Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder));
   
-  Types[FieldNumber] = LTy;
+  // int32_t __flags;
+  Types.push_back(llvm::Type::getInt32Ty(VMContext));
+    
+  // int32_t __size;
+  Types.push_back(llvm::Type::getInt32Ty(VMContext));
+
+  bool HasCopyAndDispose = BlockRequiresCopying(Ty);
+  if (HasCopyAndDispose) {
+    /// void *__copy_helper;
+    Types.push_back(Int8PtrTy);
+    
+    /// void *__destroy_helper;
+    Types.push_back(Int8PtrTy);
+  }
+
+  bool Packed = false;
+  unsigned Align = getContext().getDeclAlignInBytes(D);
+  if (Align > Target.getPointerAlign(0) / 8) {
+    // 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);
+    
+    unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
+    assert(NumPaddingBytes > 0 && "Can't append any padding!");
+    
+    const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
+    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(ConvertType(Ty));
   
-  const llvm::Type *T = llvm::StructType::get(VMContext, Types, false);
+  const llvm::Type *T = llvm::StructType::get(VMContext, 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 = FieldNumber;
+  
+  Info.second = Types.size() - 1;
   
   return Info.first;
 }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Sep 11 21:44:18 2009
@@ -716,15 +716,10 @@
       if (!NonGCable)
         attr = getContext().getObjCGCAttrKind(E->getType());
       if (VD->hasAttr<BlocksAttr>()) {
-        bool needsCopyDispose = BlockRequiresCopying(VD->getType());
-        const llvm::Type *PtrStructTy = V->getType();
-        const llvm::Type *Ty = PtrStructTy;
-        Ty = llvm::PointerType::get(Ty, 0);
         V = Builder.CreateStructGEP(V, 1, "forwarding");
-        V = Builder.CreateBitCast(V, Ty);
         V = Builder.CreateLoad(V, false);
-        V = Builder.CreateBitCast(V, PtrStructTy);
-        V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x");
+        V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD),
+                                    VD->getNameAsString());
       }
       if (VD->getType()->isReferenceType())
         V = Builder.CreateLoad(V, "tmp");

Added: cfe/trunk/test/CodeGen/blocks-aligned-byref-variable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/blocks-aligned-byref-variable.c?rev=81602&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/blocks-aligned-byref-variable.c (added)
+++ cfe/trunk/test/CodeGen/blocks-aligned-byref-variable.c Fri Sep 11 21:44:18 2009
@@ -0,0 +1,11 @@
+// RUN: clang-cc -emit-llvm -o - 
+typedef int __attribute__((aligned(32)))  ai;
+
+void f() {
+  __block ai a = 10;
+
+  ^{
+    a = 20;
+  }();
+}
+





More information about the cfe-commits mailing list