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.
#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 {
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;
/// 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 };
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:
AttrList[I].Profile(ID);
}
};
+static_assert(AlignOf<AttributeSetNode>::Alignment >=
+ AlignOf<Attribute>::Alignment,
+ "Alignment sufficient for objects appended to AttributeSetNode");
//===----------------------------------------------------------------------===//
/// \class
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.
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,
void dump() const;
};
+static_assert(AlignOf<AttributeSetImpl>::Alignment >=
+ AlignOf<AttributeSetImpl::IndexAttrPair>::Alignment,
+ "Alignment sufficient for objects appended to AttributeSetImpl");
} // end llvm namespace
// 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,
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);