[cfe-commits] r173531 - ARM says that the array cookie should always be eight bytes.

John McCall rjmccall at apple.com
Fri Jan 25 15:36:19 PST 2013


Author: rjmccall
Date: Fri Jan 25 17:36:19 2013
New Revision: 173531

URL: http://llvm.org/viewvc/llvm-project?rev=173531&view=rev
Log:
ARM says that the array cookie should always be eight bytes.
ARM is not thinking about over-aligned structures.
Overrule ARM in both our generic-ARM and iOS ABI implementations.

Modified:
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/arm.cpp

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=173531&r1=173530&r2=173531&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Jan 25 17:36:19 2013
@@ -890,50 +890,46 @@ llvm::Value *ItaniumCXXABI::readArrayCoo
 }
 
 CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
-  // On ARM, the cookie is always:
+  // ARM says that the cookie is always:
   //   struct array_cookie {
   //     std::size_t element_size; // element_size != 0
   //     std::size_t element_count;
   //   };
-  // TODO: what should we do if the allocated type actually wants
-  // greater alignment?
-  return CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes);
+  // But the base ABI doesn't give anything an alignment greater than
+  // 8, so we can dismiss this as typical ABI-author blindness to
+  // actual language complexity and round up to the element alignment.
+  return std::max(CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes),
+                  CGM.getContext().getTypeAlignInChars(elementType));
 }
 
 llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
-                                              llvm::Value *NewPtr,
-                                              llvm::Value *NumElements,
+                                              llvm::Value *newPtr,
+                                              llvm::Value *numElements,
                                               const CXXNewExpr *expr,
-                                              QualType ElementType) {
+                                              QualType elementType) {
   assert(requiresArrayCookie(expr));
 
-  // NewPtr is a char*.
-
-  unsigned AS = NewPtr->getType()->getPointerAddressSpace();
-
-  ASTContext &Ctx = getContext();
-  CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType());
-  llvm::IntegerType *SizeTy =
-    cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType()));
+  // NewPtr is a char*, but we generalize to arbitrary addrspaces.
+  unsigned AS = newPtr->getType()->getPointerAddressSpace();
 
   // The cookie is always at the start of the buffer.
-  llvm::Value *CookiePtr = NewPtr;
+  llvm::Value *cookie = newPtr;
 
   // The first element is the element size.
-  CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS));
-  llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy,
-                          Ctx.getTypeSizeInChars(ElementType).getQuantity());
-  CGF.Builder.CreateStore(ElementSize, CookiePtr);
+  cookie = CGF.Builder.CreateBitCast(cookie, CGF.SizeTy->getPointerTo(AS));
+  llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
+                 getContext().getTypeSizeInChars(elementType).getQuantity());
+  CGF.Builder.CreateStore(elementSize, cookie);
 
   // The second element is the element count.
-  CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1);
-  CGF.Builder.CreateStore(NumElements, CookiePtr);
+  cookie = CGF.Builder.CreateConstInBoundsGEP1_32(cookie, 1);
+  CGF.Builder.CreateStore(numElements, cookie);
 
   // Finally, compute a pointer to the actual data buffer by skipping
   // over the cookie completely.
-  CharUnits CookieSize = 2 * SizeSize;
-  return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
-                                                CookieSize.getQuantity());
+  CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
+  return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
+                                                cookieSize.getQuantity());
 }
 
 llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,

Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=173531&r1=173530&r2=173531&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/arm.cpp Fri Jan 25 17:36:19 2013
@@ -357,6 +357,58 @@ namespace test8 {
   }
 }
 
+//   rdar://12836470
+// Use a larger-than-mandated array cookie when allocating an
+// array whose type is overaligned.
+namespace test9 {
+  class __attribute__((aligned(16))) A {
+    float data[4];
+  public:
+    A();
+    ~A();
+  };
+
+  A *testNew(unsigned n) {
+    return new A[n];
+  }
+// CHECK:    define [[TEST9:%.*]]* @_ZN5test97testNewEj(i32
+// CHECK:      [[N_VAR:%.*]] = alloca i32, align 4
+// CHECK:      [[N:%.*]] = load i32* [[N_VAR]], align 4
+// CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 16)
+// CHECK-NEXT: [[O0:%.*]] = extractvalue { i32, i1 } [[T0]], 1
+// CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 0
+// CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 16)
+// CHECK-NEXT: [[O1:%.*]] = extractvalue { i32, i1 } [[T2]], 1
+// CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]]
+// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
+// CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]]
+// CHECK-NEXT: [[ALLOC:%.*]] = call noalias i8* @_Znam(i32 [[T4]])
+// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[ALLOC]] to i32*
+// CHECK-NEXT: store i32 16, i32* [[T0]]
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32* [[T0]], i32 1
+// CHECK-NEXT: store i32 [[N]], i32* [[T1]]
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8* [[ALLOC]], i64 16
+// CHECK-NEXT: bitcast i8* [[T0]] to [[TEST9]]*
+//   Array allocation follows.
+
+  void testDelete(A *array) {
+    delete[] array;
+  }
+// CHECK:    define void @_ZN5test910testDeleteEPNS_1AE(
+// CHECK:      [[BEGIN:%.*]] = load [[TEST9]]**
+// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], null
+// CHECK-NEXT: br i1 [[T0]],
+// CHECK:      [[T0:%.*]] = bitcast [[TEST9]]* [[BEGIN]] to i8*
+// CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8* [[T0]], i64 -16
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8* [[ALLOC]], i64 4
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32*
+// CHECK-NEXT: [[N:%.*]] = load i32* [[T1]]
+// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[TEST9]]* [[BEGIN]], i32 [[N]]
+// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], [[END]]
+// CHECK-NEXT: br i1 [[T0]],
+//   Array deallocation follows.
+}
+
   // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
   // CHECK:   call [[C]]* @_ZN5test21CD1Ev(
   // CHECK:   ret [[C]]* undef





More information about the cfe-commits mailing list