Index: include/llvm/IR/DerivedTypes.h =================================================================== --- include/llvm/IR/DerivedTypes.h +++ include/llvm/IR/DerivedTypes.h @@ -140,7 +140,9 @@ return T->getTypeID() == FunctionTyID; } }; - +// Assert objects tacked on the end of FunctionType won't be misaligned +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + ""); /// CompositeType - Common super class of ArrayType, StructType, PointerType /// and VectorType. Index: include/llvm/Support/AlignOf.h =================================================================== --- include/llvm/Support/AlignOf.h +++ include/llvm/Support/AlignOf.h @@ -44,9 +44,18 @@ /// compile-time constant (e.g., for template instantiation). template struct AlignOf { +#ifndef _MSC_VER + // Avoid warnings from GCC like: + // comparison between 'enum llvm::AlignOf::' and 'enum + // llvm::AlignOf::' [-Wenum-compare] + // by using constexpr instead of enum. + // (except on MSVC, since it doesn't support constexpr yet). + static constexpr unsigned Alignment = + static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)); +#else enum { Alignment = static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)) }; - +#endif enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; Index: lib/IR/AttributeImpl.h =================================================================== --- lib/IR/AttributeImpl.h +++ lib/IR/AttributeImpl.h @@ -181,6 +181,10 @@ AttrList[I].Profile(ID); } }; +// Assert objects tacked on the end of AttributeSetNode won't be misaligned +static_assert(AlignOf::Alignment >= + AlignOf::Alignment, + ""); //===----------------------------------------------------------------------===// /// \class @@ -189,9 +193,11 @@ class AttributeSetImpl : public FoldingSetNode { friend class AttributeSet; - LLVMContext &Context; - +public: typedef std::pair IndexAttrPair; + +private: + LLVMContext &Context; unsigned NumAttrs; ///< Number of entries in this set. /// \brief Return a pointer to the IndexAttrPair for the specified slot. @@ -206,6 +212,7 @@ AttributeSetImpl(LLVMContext &C, ArrayRef > Attrs) : Context(C), NumAttrs(Attrs.size()) { + #ifndef NDEBUG if (Attrs.size() >= 2) { for (const std::pair *i = Attrs.begin() + 1, @@ -267,6 +274,10 @@ void dump() const; }; +// Assert objects tacked on the end of AttributeSetImpl won't be misaligned +static_assert(AlignOf::Alignment >= + AlignOf::Alignment, + ""); } // end llvm namespace Index: lib/IR/Metadata.cpp =================================================================== --- lib/IR/Metadata.cpp +++ lib/IR/Metadata.cpp @@ -381,8 +381,22 @@ // MDNode implementation. // +// Assert that the MDNode types will not be unaligned by the objects +// prepended to them. +#define HANDLE_MDNODE_LEAF(CLASS) \ + static_assert(llvm::AlignOf::Alignment >= \ + llvm::AlignOf::Alignment, \ + ""); +#include "llvm/IR/Metadata.def" + void *MDNode::operator new(size_t Size, unsigned NumOps) { - void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand)); + size_t OpSize = NumOps * sizeof(MDOperand); + // uint64_t is the most aligned type we need support (ensured by static_assert + // above) + size_t AlignOffset = OffsetToAlignment(OpSize, llvm::alignOf()); + void *Ptr = + reinterpret_cast(::operator new(OpSize + AlignOffset + Size)) + + AlignOffset; MDOperand *O = static_cast(Ptr); for (MDOperand *E = O + NumOps; O != E; ++O) (void)new (O) MDOperand; @@ -391,10 +405,14 @@ void MDNode::operator delete(void *Mem) { MDNode *N = static_cast(Mem); - MDOperand *O = static_cast(Mem); + size_t OpSize = N->NumOperands * sizeof(MDOperand); + size_t AlignOffset = OffsetToAlignment(OpSize, llvm::alignOf()); + + MDOperand *O = + reinterpret_cast(reinterpret_cast(Mem)); for (MDOperand *E = O - N->NumOperands; O != E; --O) (O - 1)->~MDOperand(); - ::operator delete(O); + ::operator delete(reinterpret_cast(O) - AlignOffset); } MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,