[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