diff options
-rw-r--r-- | llvm/include/llvm/IR/DerivedTypes.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/IR/User.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/Support/AlignOf.h | 15 | ||||
-rw-r--r-- | llvm/lib/IR/AttributeImpl.h | 13 | ||||
-rw-r--r-- | llvm/lib/IR/Metadata.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/IR/User.cpp | 6 |
6 files changed, 59 insertions, 9 deletions
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h index 38f1af0d70d..4a94499b4cf 100644 --- a/llvm/include/llvm/IR/DerivedTypes.h +++ b/llvm/include/llvm/IR/DerivedTypes.h @@ -140,7 +140,8 @@ public: return T->getTypeID() == FunctionTyID; } }; - +static_assert(AlignOf<FunctionType>::Alignment >= AlignOf<Type *>::Alignment, + "Alignment sufficient for objects appended to FunctionType"); /// CompositeType - Common super class of ArrayType, StructType, PointerType /// and VectorType. diff --git a/llvm/include/llvm/IR/User.h b/llvm/include/llvm/IR/User.h index 87be88da591..9aaad2dcf8c 100644 --- a/llvm/include/llvm/IR/User.h +++ b/llvm/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 @@ public: return isa<Instruction>(V) || isa<Constant>(V); } }; +// Either Use objects, or a Use pointer can be prepended to User. +static_assert(AlignOf<Use>::Alignment >= AlignOf<User>::Alignment, + "Alignment sufficient after objects prepended to User"); +static_assert(AlignOf<Use *>::Alignment >= AlignOf<User>::Alignment, + "Alignment sufficient after objects prepended to User"); template<> struct simplify_type<User::op_iterator> { typedef Value* SimpleType; diff --git a/llvm/include/llvm/Support/AlignOf.h b/llvm/include/llvm/Support/AlignOf.h index 574b514aef3..07da02d063c 100644 --- a/llvm/include/llvm/Support/AlignOf.h +++ b/llvm/include/llvm/Support/AlignOf.h @@ -44,9 +44,18 @@ private: /// compile-time constant (e.g., for template instantiation). template <typename T> struct AlignOf { +#ifndef _MSC_VER + // Avoid warnings from GCC like: + // comparison between 'enum llvm::AlignOf<X>::<anonymous>' and 'enum + // llvm::AlignOf<Y>::<anonymous>' [-Wenum-compare] + // by using constexpr instead of enum. + // (except on MSVC, since it doesn't support constexpr yet). + static constexpr unsigned Alignment = + static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)); +#else enum { Alignment = static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - 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 @@ struct AlignOf { enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; }; +#ifndef _MSC_VER +template <typename T> constexpr unsigned AlignOf<T>::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: diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h index dbd7d63a892..88a68a4e005 100644 --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -181,6 +181,9 @@ public: AttrList[I].Profile(ID); } }; +static_assert(AlignOf<AttributeSetNode>::Alignment >= + AlignOf<Attribute>::Alignment, + "Alignment sufficient for objects appended to AttributeSetNode"); //===----------------------------------------------------------------------===// /// \class @@ -189,9 +192,11 @@ public: class AttributeSetImpl : public FoldingSetNode { friend class AttributeSet; - LLVMContext &Context; - +public: typedef std::pair<unsigned, AttributeSetNode*> 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 @@ public: AttributeSetImpl(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs) : Context(C), NumAttrs(Attrs.size()) { + #ifndef NDEBUG if (Attrs.size() >= 2) { for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1, @@ -267,6 +273,9 @@ public: void dump() const; }; +static_assert(AlignOf<AttributeSetImpl>::Alignment >= + AlignOf<AttributeSetImpl::IndexAttrPair>::Alignment, + "Alignment sufficient for objects appended to AttributeSetImpl"); } // end llvm namespace diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 75b4046ef44..de1587d28a0 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -381,20 +381,35 @@ StringRef MDString::getString() const { // 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<uint64_t>::Alignment >= \ + llvm::AlignOf<CLASS>::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<uint64_t>()); + void *Ptr = reinterpret_cast<char *>(::operator new(OpSize + Size)) + OpSize; MDOperand *O = static_cast<MDOperand *>(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<MDNode *>(Mem); + size_t OpSize = N->NumOperands * sizeof(MDOperand); + OpSize = RoundUpToAlignment(OpSize, llvm::alignOf<uint64_t>()); + MDOperand *O = static_cast<MDOperand *>(Mem); for (MDOperand *E = O - N->NumOperands; O != E; --O) (O - 1)->~MDOperand(); - ::operator delete(O); + ::operator delete(reinterpret_cast<char *>(Mem) - OpSize); } MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp index c6e4e89bb34..ab25670d389 100644 --- a/llvm/lib/IR/User.cpp +++ b/llvm/lib/IR/User.cpp @@ -42,6 +42,12 @@ void User::replaceUsesOfWith(Value *From, Value *To) { void User::allocHungoffUses(unsigned N, bool IsPhi) { assert(HasHungOffUses && "alloc must have hung off uses"); + + static_assert(AlignOf<Use>::Alignment >= AlignOf<Use::UserRef>::Alignment, + "Alignment sufficient for hung-off-uses pieces"); + static_assert(AlignOf<Use::UserRef>::Alignment >= AlignOf<BasicBlock *>::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); |