}
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();
}
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;
+
+ 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);
+}
- // This should be enough to avoid assertions.
- NumElements = 0;
- AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
- CookieSize = CharUnits::Zero();
+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,
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) { }
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);
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
/************************** 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,
llvm::Value *NumElements,
const CXXNewExpr *expr,
QualType ElementType) {
- assert(NeedsArrayCookie(expr));
+ assert(requiresArrayCookie(expr));
unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
// 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;
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);
-
- // 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);
+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());
+
+ 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
// };
// 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,
llvm::Value *NumElements,
const CXXNewExpr *expr,
QualType ElementType) {
- assert(NeedsArrayCookie(expr));
+ assert(requiresArrayCookie(expr));
// NewPtr is a char*.
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);
-
- // 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);
+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);
+
+ 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 **************************/
// 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);
}