[cfe-commits] r155886 - in /cfe/trunk: lib/CodeGen/CGCXXABI.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CodeGenModule.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/mangle-ms.cpp test/CodeGenCXX/microsoft-abi-array-cookies.cpp

John McCall rjmccall at apple.com
Mon Apr 30 22:23:51 PDT 2012


Author: rjmccall
Date: Tue May  1 00:23:51 2012
New Revision: 155886

URL: http://llvm.org/viewvc/llvm-project?rev=155886&view=rev
Log:
Refactor the C++ ABI code a little bit to take advantage of
what I'm going to treat as basically universal properties of
array-cookie code.  Implement MS array cookies on top of that.
Based on a patch by Timur Iskhodzhanov!

Added:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGCXXABI.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=155886&r1=155885&r2=155886&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Tue May  1 00:23:51 2012
@@ -145,6 +145,13 @@
 }
 
 CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
+  if (!requiresArrayCookie(expr))
+    return CharUnits::Zero();
+  return getArrayCookieSizeImpl(expr->getAllocatedType());
+}
+
+CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
+  // BOGUS
   return CharUnits::Zero();
 }
 
@@ -158,16 +165,53 @@
   return 0;
 }
 
-void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
-                               const CXXDeleteExpr *expr, QualType ElementType,
-                               llvm::Value *&NumElements,
-                               llvm::Value *&AllocPtr, CharUnits &CookieSize) {
-  ErrorUnsupportedABI(CGF, "array cookie reading");
-
-  // This should be enough to avoid assertions.
-  NumElements = 0;
-  AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
-  CookieSize = CharUnits::Zero();
+bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
+                                   QualType elementType) {
+  // If the class's usual deallocation function takes two arguments,
+  // it needs a cookie.
+  if (expr->doesUsualArrayDeleteWantSize())
+    return true;
+
+  return elementType.isDestructedType();
+}
+
+bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
+  // If the class's usual deallocation function takes two arguments,
+  // it needs a cookie.
+  if (expr->doesUsualArrayDeleteWantSize())
+    return true;
+
+  return expr->getAllocatedType().isDestructedType();
+}
+
+void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr,
+                               const CXXDeleteExpr *expr, QualType eltTy,
+                               llvm::Value *&numElements,
+                               llvm::Value *&allocPtr, CharUnits &cookieSize) {
+  // Derive a char* in the same address space as the pointer.
+  unsigned AS = cast<llvm::PointerType>(ptr->getType())->getAddressSpace();
+  llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
+  ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy);
+
+  // If we don't need an array cookie, bail out early.
+  if (!requiresArrayCookie(expr, eltTy)) {
+    allocPtr = ptr;
+    numElements = 0;
+    cookieSize = CharUnits::Zero();
+    return;
+  }
+
+  cookieSize = getArrayCookieSizeImpl(eltTy);
+  allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr,
+                                                    -cookieSize.getQuantity());
+  numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize);
+}
+
+llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
+                                           llvm::Value *ptr,
+                                           CharUnits cookieSize) {
+  ErrorUnsupportedABI(CGF, "reading a new[] cookie");
+  return llvm::ConstantInt::get(CGF.SizeTy, 0);
 }
 
 void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=155886&r1=155885&r2=155886&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue May  1 00:23:51 2012
@@ -71,6 +71,9 @@
 
   ASTContext &getContext() const { return CGM.getContext(); }
 
+  virtual bool requiresArrayCookie(const CXXDeleteExpr *E, QualType eltType);
+  virtual bool requiresArrayCookie(const CXXNewExpr *E);
+
 public:
 
   virtual ~CGCXXABI();
@@ -209,7 +212,8 @@
   /// \param NewPtr - a char* which is the presumed-non-null
   ///   return value of the allocation function
   /// \param NumElements - the computed number of elements,
-  ///   potentially collapsed from the multidimensional array case
+  ///   potentially collapsed from the multidimensional array case;
+  ///   always a size_t
   /// \param ElementType - the base element allocated type,
   ///   i.e. the allocated type after stripping all array types
   virtual llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
@@ -236,6 +240,25 @@
                                QualType ElementType, llvm::Value *&NumElements,
                                llvm::Value *&AllocPtr, CharUnits &CookieSize);
 
+protected:
+  /// Returns the extra size required in order to store the array
+  /// cookie for the given type.  Assumes that an array cookie is
+  /// required.
+  virtual CharUnits getArrayCookieSizeImpl(QualType elementType);
+
+  /// Reads the array cookie for an allocation which is known to have one.
+  /// This is called by the standard implementation of ReadArrayCookie.
+  ///
+  /// \param ptr - a pointer to the allocation made for an array, as a char*
+  /// \param cookieSize - the computed cookie size of an array
+  /// Other parameters are as above.
+  /// \return a size_t
+  virtual llvm::Value *readArrayCookieImpl(CodeGenFunction &IGF,
+                                           llvm::Value *ptr,
+                                           CharUnits cookieSize);
+
+public:
+
   /*************************** Static local guards ****************************/
 
   /// Emits the guarded initializer and destructor setup for the given

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=155886&r1=155885&r2=155886&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue May  1 00:23:51 2012
@@ -138,6 +138,7 @@
     union {
       unsigned char PointerAlignInBytes;
       unsigned char PointerSizeInBytes;
+      unsigned char SizeSizeInBytes;     // sizeof(size_t)
     };
   };
 

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=155886&r1=155885&r2=155886&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue May  1 00:23:51 2012
@@ -48,10 +48,6 @@
     return PtrDiffTy;
   }
 
-  bool NeedsArrayCookie(const CXXNewExpr *expr);
-  bool NeedsArrayCookie(const CXXDeleteExpr *expr,
-                        QualType elementType);
-
 public:
   ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
     CGCXXABI(CGM), PtrDiffTy(0), IsARM(IsARM) { }
@@ -111,16 +107,15 @@
 
   void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
 
-  CharUnits GetArrayCookieSize(const CXXNewExpr *expr);
+  CharUnits getArrayCookieSizeImpl(QualType elementType);
   llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
                                      llvm::Value *NewPtr,
                                      llvm::Value *NumElements,
                                      const CXXNewExpr *expr,
                                      QualType ElementType);
-  void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
-                       const CXXDeleteExpr *expr,
-                       QualType ElementType, llvm::Value *&NumElements,
-                       llvm::Value *&AllocPtr, CharUnits &CookieSize);
+  llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
+                                   llvm::Value *allocPtr,
+                                   CharUnits cookieSize);
 
   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
                        llvm::GlobalVariable *DeclPtr, bool PerformInit);
@@ -148,16 +143,14 @@
 
   void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
 
-  CharUnits GetArrayCookieSize(const CXXNewExpr *expr);
+  CharUnits getArrayCookieSizeImpl(QualType elementType);
   llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
                                      llvm::Value *NewPtr,
                                      llvm::Value *NumElements,
                                      const CXXNewExpr *expr,
                                      QualType ElementType);
-  void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
-                       const CXXDeleteExpr *expr,
-                       QualType ElementType, llvm::Value *&NumElements,
-                       llvm::Value *&AllocPtr, CharUnits &CookieSize);
+  llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr,
+                                   CharUnits cookieSize);
 
 private:
   /// \brief Returns true if the given instance method is one of the
@@ -796,54 +789,11 @@
 
 /************************** Array allocation cookies **************************/
 
-bool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) {
-  // If the class's usual deallocation function takes two arguments,
-  // it needs a cookie.
-  if (expr->doesUsualArrayDeleteWantSize())
-    return true;
-
-  // Automatic Reference Counting:
-  //   We need an array cookie for pointers with strong or weak lifetime.
-  QualType AllocatedType = expr->getAllocatedType();
-  if (getContext().getLangOpts().ObjCAutoRefCount &&
-      AllocatedType->isObjCLifetimeType()) {
-    switch (AllocatedType.getObjCLifetime()) {
-    case Qualifiers::OCL_None:
-    case Qualifiers::OCL_ExplicitNone:
-    case Qualifiers::OCL_Autoreleasing:
-      return false;
-      
-    case Qualifiers::OCL_Strong:
-    case Qualifiers::OCL_Weak:
-      return true;
-    }
-  }
-
-  // Otherwise, if the class has a non-trivial destructor, it always
-  // needs a cookie.
-  const CXXRecordDecl *record =
-    AllocatedType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
-  return (record && !record->hasTrivialDestructor());
-}
-
-bool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr,
-                                     QualType elementType) {
-  // If the class's usual deallocation function takes two arguments,
-  // it needs a cookie.
-  if (expr->doesUsualArrayDeleteWantSize())
-    return true;
-
-  return elementType.isDestructedType();
-}
-
-CharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
-  if (!NeedsArrayCookie(expr))
-    return CharUnits::Zero();
-  
-  // Padding is the maximum of sizeof(size_t) and alignof(elementType)
-  ASTContext &Ctx = getContext();
-  return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
-                  Ctx.getTypeAlignInChars(expr->getAllocatedType()));
+CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
+  // The array cookie is a size_t; pad that up to the element alignment.
+  // The cookie is actually right-justified in that space.
+  return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes),
+                  CGM.getContext().getTypeAlignInChars(elementType));
 }
 
 llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
@@ -851,7 +801,7 @@
                                                   llvm::Value *NumElements,
                                                   const CXXNewExpr *expr,
                                                   QualType ElementType) {
-  assert(NeedsArrayCookie(expr));
+  assert(requiresArrayCookie(expr));
 
   unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
 
@@ -862,6 +812,7 @@
   // The size of the cookie.
   CharUnits CookieSize =
     std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType));
+  assert(CookieSize == getArrayCookieSizeImpl(ElementType));
 
   // Compute an offset to the cookie.
   llvm::Value *CookiePtr = NewPtr;
@@ -882,53 +833,25 @@
                                                 CookieSize.getQuantity());  
 }
 
-void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
-                                    llvm::Value *Ptr,
-                                    const CXXDeleteExpr *expr,
-                                    QualType ElementType,
-                                    llvm::Value *&NumElements,
-                                    llvm::Value *&AllocPtr,
-                                    CharUnits &CookieSize) {
-  // Derive a char* in the same address space as the pointer.
-  unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
-  llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);
-
-  // If we don't need an array cookie, bail out early.
-  if (!NeedsArrayCookie(expr, ElementType)) {
-    AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
-    NumElements = 0;
-    CookieSize = CharUnits::Zero();
-    return;
-  }
-
-  QualType SizeTy = getContext().getSizeType();
-  CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
-  llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
-  
-  CookieSize
-    = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType));
-
-  CharUnits NumElementsOffset = CookieSize - SizeSize;
-
-  // Compute the allocated pointer.
-  AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
-  AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
-                                                    -CookieSize.getQuantity());
-
-  llvm::Value *NumElementsPtr = AllocPtr;
-  if (!NumElementsOffset.isZero())
-    NumElementsPtr =
-      CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr,
-                                             NumElementsOffset.getQuantity());
-  NumElementsPtr = 
-    CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
-  NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
-}
-
-CharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
-  if (!NeedsArrayCookie(expr))
-    return CharUnits::Zero();
+llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
+                                                llvm::Value *allocPtr,
+                                                CharUnits cookieSize) {
+  // The element size is right-justified in the cookie.
+  llvm::Value *numElementsPtr = allocPtr;
+  CharUnits numElementsOffset =
+    cookieSize - CharUnits::fromQuantity(CGF.SizeSizeInBytes);
+  if (!numElementsOffset.isZero())
+    numElementsPtr =
+      CGF.Builder.CreateConstInBoundsGEP1_64(numElementsPtr,
+                                             numElementsOffset.getQuantity());
+
+  unsigned AS = cast<llvm::PointerType>(allocPtr->getType())->getAddressSpace();
+  numElementsPtr = 
+    CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS));
+  return CGF.Builder.CreateLoad(numElementsPtr);
+}
 
+CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
   // On ARM, the cookie is always:
   //   struct array_cookie {
   //     std::size_t element_size; // element_size != 0
@@ -936,7 +859,7 @@
   //   };
   // TODO: what should we do if the allocated type actually wants
   // greater alignment?
-  return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2;
+  return CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes);
 }
 
 llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
@@ -944,7 +867,7 @@
                                               llvm::Value *NumElements,
                                               const CXXNewExpr *expr,
                                               QualType ElementType) {
-  assert(NeedsArrayCookie(expr));
+  assert(requiresArrayCookie(expr));
 
   // NewPtr is a char*.
 
@@ -975,44 +898,18 @@
                                                 CookieSize.getQuantity());
 }
 
-void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
-                                llvm::Value *Ptr,
-                                const CXXDeleteExpr *expr,
-                                QualType ElementType,
-                                llvm::Value *&NumElements,
-                                llvm::Value *&AllocPtr,
-                                CharUnits &CookieSize) {
-  // Derive a char* in the same address space as the pointer.
-  unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
-  llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);
-
-  // If we don't need an array cookie, bail out early.
-  if (!NeedsArrayCookie(expr, ElementType)) {
-    AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
-    NumElements = 0;
-    CookieSize = CharUnits::Zero();
-    return;
-  }
-
-  QualType SizeTy = getContext().getSizeType();
-  CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
-  llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
-  
-  // The cookie size is always 2 * sizeof(size_t).
-  CookieSize = 2 * SizeSize;
-
-  // The allocated pointer is the input ptr, minus that amount.
-  AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
-  AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
-                                               -CookieSize.getQuantity());
-
-  // The number of elements is at offset sizeof(size_t) relative to that.
-  llvm::Value *NumElementsPtr
-    = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
-                                             SizeSize.getQuantity());
-  NumElementsPtr = 
-    CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
-  NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
+llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
+                                            llvm::Value *allocPtr,
+                                            CharUnits cookieSize) {
+  // The number of elements is at offset sizeof(size_t) relative to
+  // the allocated pointer.
+  llvm::Value *numElementsPtr
+    = CGF.Builder.CreateConstInBoundsGEP1_64(allocPtr, CGF.SizeSizeInBytes);
+
+  unsigned AS = cast<llvm::PointerType>(allocPtr->getType())->getAddressSpace();
+  numElementsPtr = 
+    CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS));
+  return CGF.Builder.CreateLoad(numElementsPtr);
 }
 
 /*********************** Static local initialization **************************/

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=155886&r1=155885&r2=155886&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue May  1 00:23:51 2012
@@ -78,17 +78,77 @@
   //     delete[] p;
   //   }
   // Whereas it prints "104" and "104" if you give A a destructor.
-  void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
-                       const CXXDeleteExpr *expr,
-                       QualType ElementType, llvm::Value *&NumElements,
-                       llvm::Value *&AllocPtr, CharUnits &CookieSize) {
-    CGF.CGM.ErrorUnsupported(expr, "don't know how to handle array cookies "
-                                   "in the Microsoft C++ ABI");
-  }
+
+  bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
+  bool requiresArrayCookie(const CXXNewExpr *expr);
+  CharUnits getArrayCookieSizeImpl(QualType type);
+  llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+                                     llvm::Value *NewPtr,
+                                     llvm::Value *NumElements,
+                                     const CXXNewExpr *expr,
+                                     QualType ElementType);
+  llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
+                                   llvm::Value *allocPtr,
+                                   CharUnits cookieSize);
 };
 
 }
 
+bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
+                                   QualType elementType) {
+  // Microsoft seems to completely ignore the possibility of a
+  // two-argument usual deallocation function.
+  return elementType.isDestructedType();
+}
+
+bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
+  // Microsoft seems to completely ignore the possibility of a
+  // two-argument usual deallocation function.
+  return expr->getAllocatedType().isDestructedType();
+}
+
+CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
+  // The array cookie is always a size_t; we then pad that out to the
+  // alignment of the element type.
+  ASTContext &Ctx = getContext();
+  return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
+                  Ctx.getTypeAlignInChars(type));
+}
+
+llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
+                                                  llvm::Value *allocPtr,
+                                                  CharUnits cookieSize) {
+  unsigned AS = cast<llvm::PointerType>(allocPtr->getType())->getAddressSpace();
+  llvm::Value *numElementsPtr =
+    CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
+  return CGF.Builder.CreateLoad(numElementsPtr);
+}
+
+llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+                                                    llvm::Value *newPtr,
+                                                    llvm::Value *numElements,
+                                                    const CXXNewExpr *expr,
+                                                    QualType elementType) {
+  assert(requiresArrayCookie(expr));
+
+  // The size of the cookie.
+  CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
+
+  // Compute an offset to the cookie.
+  llvm::Value *cookiePtr = newPtr;
+
+  // Write the number of elements into the appropriate slot.
+  unsigned AS = cast<llvm::PointerType>(newPtr->getType())->getAddressSpace();
+  llvm::Value *numElementsPtr
+    = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
+  CGF.Builder.CreateStore(numElements, numElementsPtr);
+
+  // Finally, compute a pointer to the actual data buffer by skipping
+  // over the cookie completely.
+  return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
+                                                cookieSize.getQuantity());
+}
+
 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
   return new MicrosoftCXXABI(CGM);
 }

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms.cpp?rev=155886&r1=155885&r2=155886&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms.cpp Tue May  1 00:23:51 2012
@@ -113,7 +113,6 @@
   char *array = new char[42];
 // CHECK: @"\01??_U at YAPAXI@Z"
 
-  // FIXME: enable once PR12333 is fixed
-  // delete [] array;
-// Should be: @"\01??_V at YAXPAX@Z"
+  delete [] array;
+// CHECK: @"\01??_V at YAXPAX@Z"
 }

Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp?rev=155886&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp Tue May  1 00:23:51 2012
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+struct ClassWithoutDtor {
+  char x;
+};
+
+void check_array_no_cookies() {
+// CHECK: define void @"\01?check_array_no_cookies@@YAXXZ"() nounwind
+
+// CHECK: call noalias i8* @"\01??_U at YAPAXI@Z"(i32 42)
+  ClassWithoutDtor *array = new ClassWithoutDtor[42];
+
+// CHECK: call void @"\01??_V at YAXPAX@Z"(
+  delete [] array;
+
+}
+
+struct ClassWithDtor {
+  char x;
+  ~ClassWithDtor() {}
+};
+
+void check_array_cookies_simple() {
+// CHECK: define {{.*}} @"\01?check_array_cookies_simple@@YAXXZ"()
+
+  ClassWithDtor *array = new ClassWithDtor[42];
+// CHECK: [[ALLOCATED:%.*]] = call noalias i8* @"\01??_U at YAPAXI@Z"(i32 46)
+// 46 = 42 + size of cookie (4)
+// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
+// CHECK: store i32 42, i32* [[COOKIE]]
+// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8* [[ALLOCATED]], i{{[0-9]+}} 4
+// CHECK: bitcast i8* [[ARRAY]] to %struct.ClassWithDtor*
+
+  delete [] array;
+// CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast %struct.ClassWithDtor* %3 to i8*
+// CHECK: getelementptr inbounds i8* [[ARRAY_AS_CHAR]], i{{[0-9]+}} -4
+}
+
+struct __attribute__((aligned(8))) ClassWithAlignment {
+  // FIXME: replace __attribute__((aligned(8))) with __declspec(align(8)) once
+  // http://llvm.org/bugs/show_bug.cgi?id=12631 is fixed.
+  int *x, *y;
+  ~ClassWithAlignment() {}
+};
+
+void check_array_cookies_aligned() {
+// CHECK: define {{.*}} @"\01?check_array_cookies_aligned@@YAXXZ"()
+  ClassWithAlignment *array = new ClassWithAlignment[42];
+// CHECK: [[ALLOCATED:%.*]] = call noalias i8* @"\01??_U at YAPAXI@Z"(i32 344)
+//   344 = 42*8 + size of cookie (8, due to aligment)
+// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
+// CHECK: store i32 42, i32* [[COOKIE]]
+// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8* [[ALLOCATED]], i{{[0-9]+}} 8
+// CHECK: bitcast i8* [[ARRAY]] to %struct.ClassWithAlignment*
+
+  delete [] array;
+// CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast %struct.ClassWithAlignment* %3 to i8*
+// CHECK: getelementptr inbounds i8* [[ARRAY_AS_CHAR]], i{{[0-9]+}} -8
+}





More information about the cfe-commits mailing list