forked from OSchip/llvm-project
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! llvm-svn: 155886
This commit is contained in:
parent
0eacda5f69
commit
b91cd6687c
|
@ -145,6 +145,13 @@ void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
|
|||
}
|
||||
|
||||
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 @@ llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|||
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,
|
||||
|
|
|
@ -71,6 +71,9 @@ protected:
|
|||
|
||||
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 @@ public:
|
|||
/// \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 @@ public:
|
|||
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
|
||||
|
|
|
@ -138,6 +138,7 @@ namespace CodeGen {
|
|||
union {
|
||||
unsigned char PointerAlignInBytes;
|
||||
unsigned char PointerSizeInBytes;
|
||||
unsigned char SizeSizeInBytes; // sizeof(size_t)
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -48,10 +48,6 @@ protected:
|
|||
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 @@ public:
|
|||
|
||||
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 @@ public:
|
|||
|
||||
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 @@ void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
|
|||
|
||||
/************************** 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 *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|||
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 @@ llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|||
// 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 @@ llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|||
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);
|
||||
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());
|
||||
|
||||
// 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);
|
||||
unsigned AS = cast<llvm::PointerType>(allocPtr->getType())->getAddressSpace();
|
||||
numElementsPtr =
|
||||
CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS));
|
||||
return CGF.Builder.CreateLoad(numElementsPtr);
|
||||
}
|
||||
|
||||
CharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
|
||||
if (!NeedsArrayCookie(expr))
|
||||
return CharUnits::Zero();
|
||||
|
||||
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 @@ CharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
|
|||
// };
|
||||
// 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 *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|||
llvm::Value *NumElements,
|
||||
const CXXNewExpr *expr,
|
||||
QualType ElementType) {
|
||||
assert(NeedsArrayCookie(expr));
|
||||
assert(requiresArrayCookie(expr));
|
||||
|
||||
// NewPtr is a char*.
|
||||
|
||||
|
@ -975,44 +898,18 @@ llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
|
|||
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);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
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 **************************/
|
||||
|
|
|
@ -78,17 +78,77 @@ public:
|
|||
// 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);
|
||||
}
|
||||
|
|
|
@ -113,7 +113,6 @@ void operator_new_delete() {
|
|||
char *array = new char[42];
|
||||
// CHECK: @"\01??_U@YAPAXI@Z"
|
||||
|
||||
// FIXME: enable once PR12333 is fixed
|
||||
// delete [] array;
|
||||
// Should be: @"\01??_V@YAXPAX@Z"
|
||||
delete [] array;
|
||||
// CHECK: @"\01??_V@YAXPAX@Z"
|
||||
}
|
||||
|
|
|
@ -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@YAPAXI@Z"(i32 42)
|
||||
ClassWithoutDtor *array = new ClassWithoutDtor[42];
|
||||
|
||||
// CHECK: call void @"\01??_V@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@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@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
|
||||
}
|
Loading…
Reference in New Issue