mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
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. llvm-svn: 173531
This commit is contained in:
parent
5762592b49
commit
c19c7066c2
@ -890,50 +890,46 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
|
CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
|
||||||
// On ARM, the cookie is always:
|
// ARM says that the cookie is always:
|
||||||
// struct array_cookie {
|
// struct array_cookie {
|
||||||
// std::size_t element_size; // element_size != 0
|
// std::size_t element_size; // element_size != 0
|
||||||
// std::size_t element_count;
|
// std::size_t element_count;
|
||||||
// };
|
// };
|
||||||
// TODO: what should we do if the allocated type actually wants
|
// But the base ABI doesn't give anything an alignment greater than
|
||||||
// greater alignment?
|
// 8, so we can dismiss this as typical ABI-author blindness to
|
||||||
return CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes);
|
// 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 *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
||||||
llvm::Value *NewPtr,
|
llvm::Value *newPtr,
|
||||||
llvm::Value *NumElements,
|
llvm::Value *numElements,
|
||||||
const CXXNewExpr *expr,
|
const CXXNewExpr *expr,
|
||||||
QualType ElementType) {
|
QualType elementType) {
|
||||||
assert(requiresArrayCookie(expr));
|
assert(requiresArrayCookie(expr));
|
||||||
|
|
||||||
// NewPtr is a char*.
|
// NewPtr is a char*, but we generalize to arbitrary addrspaces.
|
||||||
|
unsigned AS = newPtr->getType()->getPointerAddressSpace();
|
||||||
unsigned AS = NewPtr->getType()->getPointerAddressSpace();
|
|
||||||
|
|
||||||
ASTContext &Ctx = getContext();
|
|
||||||
CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType());
|
|
||||||
llvm::IntegerType *SizeTy =
|
|
||||||
cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType()));
|
|
||||||
|
|
||||||
// The cookie is always at the start of the buffer.
|
// 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.
|
// The first element is the element size.
|
||||||
CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS));
|
cookie = CGF.Builder.CreateBitCast(cookie, CGF.SizeTy->getPointerTo(AS));
|
||||||
llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy,
|
llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
|
||||||
Ctx.getTypeSizeInChars(ElementType).getQuantity());
|
getContext().getTypeSizeInChars(elementType).getQuantity());
|
||||||
CGF.Builder.CreateStore(ElementSize, CookiePtr);
|
CGF.Builder.CreateStore(elementSize, cookie);
|
||||||
|
|
||||||
// The second element is the element count.
|
// The second element is the element count.
|
||||||
CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1);
|
cookie = CGF.Builder.CreateConstInBoundsGEP1_32(cookie, 1);
|
||||||
CGF.Builder.CreateStore(NumElements, CookiePtr);
|
CGF.Builder.CreateStore(numElements, cookie);
|
||||||
|
|
||||||
// Finally, compute a pointer to the actual data buffer by skipping
|
// Finally, compute a pointer to the actual data buffer by skipping
|
||||||
// over the cookie completely.
|
// over the cookie completely.
|
||||||
CharUnits CookieSize = 2 * SizeSize;
|
CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
|
||||||
return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
|
return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
|
||||||
CookieSize.getQuantity());
|
cookieSize.getQuantity());
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
|
llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
|
||||||
|
@ -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: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
|
||||||
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
|
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
|
||||||
// CHECK: ret [[C]]* undef
|
// CHECK: ret [[C]]* undef
|
||||||
|
Loading…
Reference in New Issue
Block a user