mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-07 14:33:15 +00:00
Fix alignment issues in LLVM.
Adds static_asserts to ensure alignment of concatenated objects is correct, and fixes them where they are not. Also changes the definition of AlignOf to use constexpr, except on MSVC, to avoid enum comparison warnings from GCC. (There's not too much of this in llvm itself, most of the fun is in clang). This seems to make LLVM actually work without Bus Error on 32bit sparc. Differential Revision: http://reviews.llvm.org/D10271 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239872 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cc625c9f25
commit
4a80b4b0c0
@ -140,7 +140,8 @@ public:
|
|||||||
return T->getTypeID() == FunctionTyID;
|
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
|
/// CompositeType - Common super class of ArrayType, StructType, PointerType
|
||||||
/// and VectorType.
|
/// and VectorType.
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "llvm/ADT/iterator.h"
|
#include "llvm/ADT/iterator.h"
|
||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/IR/Value.h"
|
#include "llvm/IR/Value.h"
|
||||||
|
#include "llvm/Support/AlignOf.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -226,6 +227,11 @@ public:
|
|||||||
return isa<Instruction>(V) || isa<Constant>(V);
|
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> {
|
template<> struct simplify_type<User::op_iterator> {
|
||||||
typedef Value* SimpleType;
|
typedef Value* SimpleType;
|
||||||
|
@ -44,9 +44,18 @@ private:
|
|||||||
/// compile-time constant (e.g., for template instantiation).
|
/// compile-time constant (e.g., for template instantiation).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct AlignOf {
|
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 =
|
enum { Alignment =
|
||||||
static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) };
|
static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) };
|
||||||
|
#endif
|
||||||
enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
|
enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
|
||||||
enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
|
enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
|
||||||
enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
|
enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
|
||||||
@ -58,6 +67,10 @@ struct AlignOf {
|
|||||||
enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 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
|
/// alignOf - A templated function that returns the minimum alignment of
|
||||||
/// of a type. This provides no extra functionality beyond the AlignOf
|
/// of a type. This provides no extra functionality beyond the AlignOf
|
||||||
/// class besides some cosmetic cleanliness. Example usage:
|
/// class besides some cosmetic cleanliness. Example usage:
|
||||||
|
@ -181,6 +181,9 @@ public:
|
|||||||
AttrList[I].Profile(ID);
|
AttrList[I].Profile(ID);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
static_assert(AlignOf<AttributeSetNode>::Alignment >=
|
||||||
|
AlignOf<Attribute>::Alignment,
|
||||||
|
"Alignment sufficient for objects appended to AttributeSetNode");
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
/// \class
|
/// \class
|
||||||
@ -189,9 +192,11 @@ public:
|
|||||||
class AttributeSetImpl : public FoldingSetNode {
|
class AttributeSetImpl : public FoldingSetNode {
|
||||||
friend class AttributeSet;
|
friend class AttributeSet;
|
||||||
|
|
||||||
LLVMContext &Context;
|
public:
|
||||||
|
|
||||||
typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair;
|
typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LLVMContext &Context;
|
||||||
unsigned NumAttrs; ///< Number of entries in this set.
|
unsigned NumAttrs; ///< Number of entries in this set.
|
||||||
|
|
||||||
/// \brief Return a pointer to the IndexAttrPair for the specified slot.
|
/// \brief Return a pointer to the IndexAttrPair for the specified slot.
|
||||||
@ -206,6 +211,7 @@ public:
|
|||||||
AttributeSetImpl(LLVMContext &C,
|
AttributeSetImpl(LLVMContext &C,
|
||||||
ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
|
ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
|
||||||
: Context(C), NumAttrs(Attrs.size()) {
|
: Context(C), NumAttrs(Attrs.size()) {
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (Attrs.size() >= 2) {
|
if (Attrs.size() >= 2) {
|
||||||
for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
|
for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
|
||||||
@ -267,6 +273,9 @@ public:
|
|||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
};
|
};
|
||||||
|
static_assert(AlignOf<AttributeSetImpl>::Alignment >=
|
||||||
|
AlignOf<AttributeSetImpl::IndexAttrPair>::Alignment,
|
||||||
|
"Alignment sufficient for objects appended to AttributeSetImpl");
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
|
||||||
|
@ -381,20 +381,35 @@ StringRef MDString::getString() const {
|
|||||||
// MDNode implementation.
|
// 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 *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);
|
MDOperand *O = static_cast<MDOperand *>(Ptr);
|
||||||
for (MDOperand *E = O + NumOps; O != E; ++O)
|
for (MDOperand *E = O - NumOps; O != E; --O)
|
||||||
(void)new (O) MDOperand;
|
(void)new (O - 1) MDOperand;
|
||||||
return O;
|
return Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDNode::operator delete(void *Mem) {
|
void MDNode::operator delete(void *Mem) {
|
||||||
MDNode *N = static_cast<MDNode *>(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);
|
MDOperand *O = static_cast<MDOperand *>(Mem);
|
||||||
for (MDOperand *E = O - N->NumOperands; O != E; --O)
|
for (MDOperand *E = O - N->NumOperands; O != E; --O)
|
||||||
(O - 1)->~MDOperand();
|
(O - 1)->~MDOperand();
|
||||||
::operator delete(O);
|
::operator delete(reinterpret_cast<char *>(Mem) - OpSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
|
MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
|
||||||
|
@ -42,6 +42,12 @@ void User::replaceUsesOfWith(Value *From, Value *To) {
|
|||||||
|
|
||||||
void User::allocHungoffUses(unsigned N, bool IsPhi) {
|
void User::allocHungoffUses(unsigned N, bool IsPhi) {
|
||||||
assert(HasHungOffUses && "alloc must have hung off uses");
|
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
|
// Allocate the array of Uses, followed by a pointer (with bottom bit set) to
|
||||||
// the User.
|
// the User.
|
||||||
size_t size = N * sizeof(Use) + sizeof(Use::UserRef);
|
size_t size = N * sizeof(Use) + sizeof(Use::UserRef);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user