summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/DerivedTypes.h3
-rw-r--r--llvm/include/llvm/IR/User.h6
-rw-r--r--llvm/include/llvm/Support/AlignOf.h15
-rw-r--r--llvm/lib/IR/AttributeImpl.h13
-rw-r--r--llvm/lib/IR/Metadata.cpp25
-rw-r--r--llvm/lib/IR/User.cpp6
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);
OpenPOWER on IntegriCloud