#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
-#include <vector>
+#include "llvm/ADT/SmallVector.h"
#include <string>
namespace llvm {
class Type;
class StructType;
class StructLayout;
+class GlobalVariable;
+
+/// Enum used to categorize the alignment types stored by TargetAlignElem
+enum AlignTypeEnum {
+ INTEGER_ALIGN = 'i', ///< Integer type alignment
+ VECTOR_ALIGN = 'v', ///< Vector type alignment
+ FLOAT_ALIGN = 'f', ///< Floating point type alignment
+ AGGREGATE_ALIGN = 'a' ///< Aggregate alignment
+};
+/// Target alignment element.
+///
+/// Stores the alignment data associated with a given alignment type (pointer,
+/// integer, packed/vector, float) and type bit width.
+///
+/// @note The unusual order of elements in the structure attempts to reduce
+/// padding and make the structure slightly more cache friendly.
+struct TargetAlignElem {
+ AlignTypeEnum AlignType : 8; //< Alignment type (AlignTypeEnum)
+ unsigned char ABIAlign; //< ABI alignment for this type/bitw
+ unsigned char PrefAlign; //< Pref. alignment for this type/bitw
+ uint32_t TypeBitWidth; //< Type bit width
+
+ /// Initializer
+ static TargetAlignElem get(AlignTypeEnum align_type, unsigned char abi_align,
+ unsigned char pref_align, uint32_t bit_width);
+ /// Equality predicate
+ bool operator==(const TargetAlignElem &rhs) const;
+ /// output stream operator
+ std::ostream &dump(std::ostream &os) const;
+};
class TargetData : public ImmutablePass {
- bool LittleEndian; // Defaults to false
- unsigned char BoolAlignment; // Defaults to 1 byte
- unsigned char ByteAlignment; // Defaults to 1 byte
- unsigned char ShortAlignment; // Defaults to 2 bytes
- unsigned char IntAlignment; // Defaults to 4 bytes
- unsigned char LongAlignment; // Defaults to 8 bytes
- unsigned char FloatAlignment; // Defaults to 4 bytes
- unsigned char DoubleAlignment; // Defaults to 8 bytes
- unsigned char PointerSize; // Defaults to 8 bytes
- unsigned char PointerAlignment; // Defaults to 8 bytes
+private:
+ bool LittleEndian; ///< Defaults to false
+ unsigned char PointerMemSize; ///< Pointer size in bytes
+ unsigned char PointerABIAlign; ///< Pointer ABI alignment
+ unsigned char PointerPrefAlign; ///< Pointer preferred alignment
+
+ //! Where the primitive type alignment data is stored.
+ /*!
+ @sa init().
+ @note Could support multiple size pointer alignments, e.g., 32-bit pointers
+ vs. 64-bit pointers by extending TargetAlignment, but for now, we don't.
+ */
+ SmallVector<TargetAlignElem, 16> Alignments;
+ //! Alignment iterator shorthand
+ typedef SmallVector<TargetAlignElem, 16>::iterator align_iterator;
+ //! Constant alignment iterator shorthand
+ typedef SmallVector<TargetAlignElem, 16>::const_iterator align_const_iterator;
+ //! Invalid alignment.
+ /*!
+ This member is a signal that a requested alignment type and bit width were
+ not found in the SmallVector.
+ */
+ static const TargetAlignElem InvalidAlignmentElem;
+
+ //! Set/initialize target alignments
+ void setAlignment(AlignTypeEnum align_type, unsigned char abi_align,
+ unsigned char pref_align, uint32_t bit_width);
+ unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
+ bool ABIAlign) const;
+ //! Internal helper method that returns requested alignment for type.
+ unsigned char getAlignment(const Type *Ty, bool abi_or_pref) const;
+
+ /// Valid alignment predicate.
+ ///
+ /// Predicate that tests a TargetAlignElem reference returned by get() against
+ /// InvalidAlignmentElem.
+ inline bool validAlignment(const TargetAlignElem &align) const {
+ return (&align != &InvalidAlignmentElem);
+ }
public:
- TargetData(const std::string &TargetName = "",
- bool LittleEndian = false,
- unsigned char PtrSize = 8,
- unsigned char PtrAl = 8, unsigned char DoubleAl = 8,
- unsigned char FloatAl = 4, unsigned char LongAl = 8,
- unsigned char IntAl = 4, unsigned char ShortAl = 2,
- unsigned char ByteAl = 1, unsigned char BoolAl = 1);
-
- // Copy constructor
- TargetData (const TargetData *TD) :
- ImmutablePass(),
- LittleEndian(TD->isLittleEndian()),
- BoolAlignment(TD->getBoolAlignment()),
- ByteAlignment(TD->getByteAlignment()),
- ShortAlignment(TD->getShortAlignment()),
- IntAlignment(TD->getIntAlignment()),
- LongAlignment(TD->getLongAlignment()),
- FloatAlignment(TD->getFloatAlignment()),
- DoubleAlignment(TD->getDoubleAlignment()),
- PointerSize(TD->getPointerSize()),
- PointerAlignment(TD->getPointerAlignment()) {
+ /// Default ctor.
+ ///
+ /// @note This has to exist, because this is a pass, but it should never be
+ /// used.
+ TargetData() {
+ assert(0 && "ERROR: Bad TargetData ctor used. "
+ "Tool did not specify a TargetData to use?");
+ abort();
+ }
+
+ /// Constructs a TargetData from a specification string. See init().
+ TargetData(const std::string &TargetDescription) {
+ init(TargetDescription);
}
- TargetData(const std::string &ToolName, const Module *M);
+ /// Initialize target data from properties stored in the module.
+ TargetData(const Module *M);
+
+ TargetData(const TargetData &TD) :
+ ImmutablePass(),
+ LittleEndian(TD.isLittleEndian()),
+ PointerMemSize(TD.PointerMemSize),
+ PointerABIAlign(TD.PointerABIAlign),
+ PointerPrefAlign(TD.PointerPrefAlign),
+ Alignments(TD.Alignments)
+ { }
+
~TargetData(); // Not virtual, do not subclass this class
+ //! Parse a target data layout string and initialize TargetData alignments.
+ void init(const std::string &TargetDescription);
+
/// Target endianness...
bool isLittleEndian() const { return LittleEndian; }
bool isBigEndian() const { return !LittleEndian; }
- /// Target alignment constraints
- unsigned char getBoolAlignment() const { return BoolAlignment; }
- unsigned char getByteAlignment() const { return ByteAlignment; }
- unsigned char getShortAlignment() const { return ShortAlignment; }
- unsigned char getIntAlignment() const { return IntAlignment; }
- unsigned char getLongAlignment() const { return LongAlignment; }
- unsigned char getFloatAlignment() const { return FloatAlignment; }
- unsigned char getDoubleAlignment() const { return DoubleAlignment; }
- unsigned char getPointerAlignment() const { return PointerAlignment; }
- unsigned char getPointerSize() const { return PointerSize; }
- unsigned char getPointerSizeInBits() const { return 8*PointerSize; }
+ /// getStringRepresentation - Return the string representation of the
+ /// TargetData. This representation is in the same format accepted by the
+ /// string constructor above.
+ std::string getStringRepresentation() const;
+ /// Target pointer alignment
+ unsigned char getPointerABIAlignment() const { return PointerABIAlign; }
+ /// Return target's alignment for stack-based pointers
+ unsigned char getPointerPrefAlignment() const { return PointerPrefAlign; }
+ /// Target pointer size
+ unsigned char getPointerSize() const { return PointerMemSize; }
+ /// Target pointer size, in bits
+ unsigned char getPointerSizeInBits() const { return 8*PointerMemSize; }
/// getTypeSize - Return the number of bytes necessary to hold the specified
/// type.
- ///
uint64_t getTypeSize(const Type *Ty) const;
- /// getTypeAlignment - Return the minimum required alignment for the specified
- /// type.
- ///
- unsigned char getTypeAlignment(const Type *Ty) const;
+ /// getTypeSizeInBits - Return the number of bits necessary to hold the
+ /// specified type.
+ uint64_t getTypeSizeInBits(const Type* Ty) const;
+
+ /// getABITypeAlignment - Return the minimum ABI-required alignment for the
+ /// specified type.
+ unsigned char getABITypeAlignment(const Type *Ty) const;
+
+ /// getPrefTypeAlignment - Return the preferred stack/global alignment for
+ /// the specified type.
+ unsigned char getPrefTypeAlignment(const Type *Ty) const;
- /// getTypeAlignmentShift - Return the minimum required alignment for the
+ /// getPreferredTypeAlignmentShift - Return the preferred alignment for the
/// specified type, returned as log2 of the value (a shift amount).
///
- unsigned char getTypeAlignmentShift(const Type *Ty) const;
+ unsigned char getPreferredTypeAlignmentShift(const Type *Ty) const;
/// getIntPtrType - Return an unsigned integer type that is the same size or
/// greater to the host pointer size.
///
const Type *getIntPtrType() const;
- /// getIndexOffset - return the offset from the beginning of the type for the
+ /// getIndexedOffset - return the offset from the beginning of the type for the
/// specified indices. This is used to implement getelementptr.
///
uint64_t getIndexedOffset(const Type *Ty,
- const std::vector<Value*> &Indices) const;
-
+ Value* const* Indices, unsigned NumIndices) const;
+
/// getStructLayout - Return a StructLayout object, indicating the alignment
/// of the struct, its size, and the offsets of its fields. Note that this
/// information is lazily cached.
/// removed, this method must be called whenever a StructType is removed to
/// avoid a dangling pointer in this cache.
void InvalidateStructLayoutInfo(const StructType *Ty) const;
+
+ /// getPreferredAlignmentLog - Return the preferred alignment of the
+ /// specified global, returned in log form. This includes an explicitly
+ /// requested alignment (if the global has one).
+ unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const;
};
/// StructLayout - used to lazily calculate structure layout information for a
/// target machine, based on the TargetData structure.
///
class StructLayout {
-public:
- std::vector<uint64_t> MemberOffsets;
uint64_t StructSize;
unsigned StructAlignment;
+ unsigned NumElements;
+ uint64_t MemberOffsets[1]; // variable sized array!
+public:
+ uint64_t getSizeInBytes() const {
+ return StructSize;
+ }
+
+ unsigned getAlignment() const {
+ return StructAlignment;
+ }
+
/// getElementContainingOffset - Given a valid offset into the structure,
/// return the structure index that contains it.
///
unsigned getElementContainingOffset(uint64_t Offset) const;
+ uint64_t getElementOffset(unsigned Idx) const {
+ assert(Idx < NumElements && "Invalid element idx!");
+ return MemberOffsets[Idx];
+ }
+
private:
friend class TargetData; // Only TargetData can create this class
StructLayout(const StructType *ST, const TargetData &TD);