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!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155886 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index befebbe..8561ae3 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -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");
+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;
 
-  // This should be enough to avoid assertions.
-  NumElements = 0;
-  AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
-  CookieSize = CharUnits::Zero();
+  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,