Index: llvm/trunk/include/llvm/IR/DerivedTypes.h =================================================================== --- llvm/trunk/include/llvm/IR/DerivedTypes.h +++ llvm/trunk/include/llvm/IR/DerivedTypes.h @@ -140,7 +140,8 @@ return T->getTypeID() == FunctionTyID; } }; - +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionType"); /// CompositeType - Common super class of ArrayType, StructType, PointerType /// and VectorType. Index: llvm/trunk/include/llvm/IR/User.h =================================================================== --- llvm/trunk/include/llvm/IR/User.h +++ llvm/trunk/include/llvm/IR/User.h @@ -22,6 +22,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Value.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -226,6 +227,11 @@ return isa(V) || isa(V); } }; +// Either Use objects, or a Use pointer can be prepended to User. +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment sufficient after objects prepended to User"); +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment sufficient after objects prepended to User"); template<> struct simplify_type { typedef Value* SimpleType; Index: llvm/trunk/include/llvm/Support/AlignOf.h =================================================================== --- llvm/trunk/include/llvm/Support/AlignOf.h +++ llvm/trunk/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 }; @@ -58,6 +67,10 @@ enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; }; +#ifndef _MSC_VER +template constexpr unsigned AlignOf::Alignment; +#endif + /// alignOf - A templated function that returns the minimum alignment of /// of a type. This provides no extra functionality beyond the AlignOf /// class besides some cosmetic cleanliness. Example usage: Index: llvm/trunk/lib/IR/AttributeImpl.h =================================================================== --- llvm/trunk/lib/IR/AttributeImpl.h +++ llvm/trunk/lib/IR/AttributeImpl.h @@ -181,6 +181,9 @@ AttrList[I].Profile(ID); } }; +static_assert(AlignOf::Alignment >= + AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeSetNode"); //===----------------------------------------------------------------------===// /// \class @@ -189,9 +192,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 +211,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 +273,9 @@ void dump() const; }; +static_assert(AlignOf::Alignment >= + AlignOf::Alignment, + "Alignment sufficient for objects appended to AttributeSetImpl"); } // end llvm namespace Index: llvm/trunk/lib/IR/Metadata.cpp =================================================================== --- llvm/trunk/lib/IR/Metadata.cpp +++ llvm/trunk/lib/IR/Metadata.cpp @@ -381,20 +381,35 @@ // 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, \ + "Alignment sufficient after objects prepended to " #CLASS); +#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) + OpSize = RoundUpToAlignment(OpSize, llvm::alignOf()); + void *Ptr = reinterpret_cast(::operator new(OpSize + Size)) + OpSize; MDOperand *O = static_cast(Ptr); - for (MDOperand *E = O + NumOps; O != E; ++O) - (void)new (O) MDOperand; - return O; + for (MDOperand *E = O - NumOps; O != E; --O) + (void)new (O - 1) MDOperand; + return Ptr; } void MDNode::operator delete(void *Mem) { MDNode *N = static_cast(Mem); + size_t OpSize = N->NumOperands * sizeof(MDOperand); + OpSize = RoundUpToAlignment(OpSize, llvm::alignOf()); + MDOperand *O = static_cast(Mem); for (MDOperand *E = O - N->NumOperands; O != E; --O) (O - 1)->~MDOperand(); - ::operator delete(O); + ::operator delete(reinterpret_cast(Mem) - OpSize); } MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, Index: llvm/trunk/lib/IR/User.cpp =================================================================== --- llvm/trunk/lib/IR/User.cpp +++ llvm/trunk/lib/IR/User.cpp @@ -42,6 +42,12 @@ void User::allocHungoffUses(unsigned N, bool IsPhi) { assert(HasHungOffUses && "alloc must have hung off uses"); + + static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment sufficient for hung-off-uses pieces"); + static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment sufficient for hung-off-uses pieces"); + // Allocate the array of Uses, followed by a pointer (with bottom bit set) to // the User. size_t size = N * sizeof(Use) + sizeof(Use::UserRef);