#define LLVM_IR_ATTRIBUTES_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <bitset>
#include <cassert>
#include <map>
#include <string>
class AttributeSetImpl;
class AttributeSetNode;
class Constant;
+template<typename T> struct DenseMapInfo;
+class Function;
class LLVMContext;
class Type;
enum AttrKind {
// IR-Level Attributes
None, ///< No attributes have been set
- AddressSafety, ///< Address safety checking is on.
- Alignment, ///< Alignment of parameter (5 bits)
- ///< stored as log2 of alignment with +1 bias
- ///< 0 means unaligned (different from align(1))
- AlwaysInline, ///< inline=always
- ByVal, ///< Pass structure by value
- InlineHint, ///< Source said inlining was desirable
- InReg, ///< Force argument to be passed in register
- MinSize, ///< Function must be optimized for size first
- Naked, ///< Naked function
- Nest, ///< Nested function static chain
- NoAlias, ///< Considered to not alias after call
- NoCapture, ///< Function creates no aliases of pointer
- NoDuplicate, ///< Call cannot be duplicated
- NoImplicitFloat, ///< Disable implicit floating point insts
- NoInline, ///< inline=never
- NonLazyBind, ///< Function is called early and/or
- ///< often, so lazy binding isn't worthwhile
- NoRedZone, ///< Disable redzone
- NoReturn, ///< Mark the function as not returning
- NoUnwind, ///< Function doesn't unwind stack
- OptimizeForSize, ///< opt_size
- ReadNone, ///< Function does not access memory
- ReadOnly, ///< Function only reads from memory
- ReturnsTwice, ///< Function can return twice
- SExt, ///< Sign extended before/after call
- StackAlignment, ///< Alignment of stack for function (3 bits)
- ///< stored as log2 of alignment with +1 bias 0
- ///< means unaligned (different from
- ///< alignstack=(1))
- StackProtect, ///< Stack protection.
- StackProtectReq, ///< Stack protection required.
- StackProtectStrong, ///< Strong Stack protection.
- StructRet, ///< Hidden pointer to structure to return
- UWTable, ///< Function must be in a unwind table
- ZExt, ///< Zero extended before/after call
-
- EndAttrKinds, ///< Sentinal value useful for loops
-
- AttrKindEmptyKey, ///< Empty key value for DenseMapInfo
- AttrKindTombstoneKey ///< Tombstone key value for DenseMapInfo
+ #define GET_ATTR_ENUM
+ #include "llvm/IR/Attributes.inc"
+ EndAttrKinds ///< Sentinal value useful for loops
};
+
private:
AttributeImpl *pImpl;
Attribute(AttributeImpl *A) : pImpl(A) {}
+
public:
- Attribute() : pImpl(0) {}
+ Attribute() : pImpl(nullptr) {}
//===--------------------------------------------------------------------===//
// Attribute Construction
/// alignment set.
static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align);
static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align);
+ static Attribute getWithDereferenceableBytes(LLVMContext &Context,
+ uint64_t Bytes);
+ static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context,
+ uint64_t Bytes);
//===--------------------------------------------------------------------===//
// Attribute Accessors
/// \brief Return true if the attribute is an Attribute::AttrKind type.
bool isEnumAttribute() const;
- /// \brief Return true if the attribute is an alignment attribute.
- bool isAlignAttribute() const;
+ /// \brief Return true if the attribute is an integer attribute.
+ bool isIntAttribute() const;
/// \brief Return true if the attribute is a string (target-dependent)
/// attribute.
/// alignment value.
unsigned getStackAlignment() const;
+ /// \brief Returns the number of dereferenceable bytes from the
+ /// dereferenceable attribute.
+ uint64_t getDereferenceableBytes() const;
+
+ /// \brief Returns the number of dereferenceable_or_null bytes from the
+ /// dereferenceable_or_null attribute.
+ uint64_t getDereferenceableOrNullBytes() const;
+
/// \brief The Attribute is converted to a string of equivalent mnemonic. This
/// is, presumably, for writing out the mnemonics for the assembly writer.
- std::string getAsString() const;
+ std::string getAsString(bool InAttrGrp = false) const;
/// \brief Equality and non-equality operators.
bool operator==(Attribute A) const { return pImpl == A.pImpl; }
/// index `1'.
class AttributeSet {
public:
- enum AttrIndex {
+ enum AttrIndex : unsigned {
ReturnIndex = 0U,
FunctionIndex = ~0U
};
+
private:
friend class AttrBuilder;
friend class AttributeSetImpl;
+ template <typename Ty> friend struct DenseMapInfo;
/// \brief The attributes that we are managing. This can be null to represent
/// the empty attributes list.
AttributeSetImpl *pImpl;
/// \brief The attributes for the specified index are returned.
- AttributeSetNode *getAttributes(unsigned Idx) const;
+ AttributeSetNode *getAttributes(unsigned Index) const;
/// \brief Create an AttributeSet with the specified parameters in it.
static AttributeSet get(LLVMContext &C,
ArrayRef<std::pair<unsigned,
AttributeSetNode*> > Attrs);
-
explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {}
+
public:
- AttributeSet() : pImpl(0) {}
- AttributeSet(const AttributeSet &P) : pImpl(P.pImpl) {}
- const AttributeSet &operator=(const AttributeSet &RHS) {
- pImpl = RHS.pImpl;
- return *this;
- }
+ AttributeSet() : pImpl(nullptr) {}
//===--------------------------------------------------------------------===//
// AttributeSet Construction and Mutation
/// \brief Return an AttributeSet with the specified parameters in it.
static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs);
- static AttributeSet get(LLVMContext &C, unsigned Idx,
+ static AttributeSet get(LLVMContext &C, unsigned Index,
ArrayRef<Attribute::AttrKind> Kind);
- static AttributeSet get(LLVMContext &C, unsigned Idx, AttrBuilder &B);
+ static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B);
- /// \brief Add an attribute to the attribute set at the given index. Since
+ /// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C, unsigned Idx,
+ AttributeSet addAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Attr) const;
- /// \brief Add attributes to the attribute set at the given index. Since
+ /// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttributes(LLVMContext &C, unsigned Idx,
+ AttributeSet addAttribute(LLVMContext &C, unsigned Index,
+ StringRef Kind) const;
+ AttributeSet addAttribute(LLVMContext &C, unsigned Index,
+ StringRef Kind, StringRef Value) const;
+
+ /// Add an attribute to the attribute set at the given indices. Because
+ /// attribute sets are immutable, this returns a new set.
+ AttributeSet addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
+ Attribute A) const;
+
+ /// \brief Add attributes to the attribute set at the given index. Because
+ /// attribute sets are immutable, this returns a new set.
+ AttributeSet addAttributes(LLVMContext &C, unsigned Index,
AttributeSet Attrs) const;
/// \brief Remove the specified attribute at the specified index from this
- /// attribute list. Since attribute lists are immutable, this returns the new
- /// list.
- AttributeSet removeAttribute(LLVMContext &C, unsigned Idx,
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Attr) const;
/// \brief Remove the specified attributes at the specified index from this
- /// attribute list. Since attribute lists are immutable, this returns the new
- /// list.
- AttributeSet removeAttributes(LLVMContext &C, unsigned Idx,
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
AttributeSet Attrs) const;
+ /// \brief Remove the specified attributes at the specified index from this
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &Attrs) const;
+
+ /// \brief Add the dereferenceable attribute to the attribute set at the given
+ /// index. Because attribute sets are immutable, this returns a new set.
+ AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
+
+ /// \brief Add the dereferenceable_or_null attribute to the attribute set at
+ /// the given index. Because attribute sets are immutable, this returns a new
+ /// set.
+ AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
+
//===--------------------------------------------------------------------===//
// AttributeSet Accessors
//===--------------------------------------------------------------------===//
+ /// \brief Retrieve the LLVM context.
+ LLVMContext &getContext() const;
+
/// \brief The attributes for the specified index are returned.
- AttributeSet getParamAttributes(unsigned Idx) const;
+ AttributeSet getParamAttributes(unsigned Index) const;
/// \brief The attributes for the ret value are returned.
AttributeSet getRetAttributes() const;
/// \brief Return true if the attribute exists at the given index.
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;
+ /// \brief Return true if the attribute exists at the given index.
+ bool hasAttribute(unsigned Index, StringRef Kind) const;
+
/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
/// parameter or for the return value.
bool hasAttrSomewhere(Attribute::AttrKind Attr) const;
+ /// \brief Return the attribute object that exists at the given index.
+ Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const;
+
+ /// \brief Return the attribute object that exists at the given index.
+ Attribute getAttribute(unsigned Index, StringRef Kind) const;
+
/// \brief Return the alignment for the specified function parameter.
- unsigned getParamAlignment(unsigned Idx) const;
+ unsigned getParamAlignment(unsigned Index) const;
/// \brief Get the stack alignment.
unsigned getStackAlignment(unsigned Index) const;
+ /// \brief Get the number of dereferenceable bytes (or zero if unknown).
+ uint64_t getDereferenceableBytes(unsigned Index) const;
+
+ /// \brief Get the number of dereferenceable_or_null bytes (or zero if
+ /// unknown).
+ uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
+
/// \brief Return the attributes at the index as a string.
- std::string getAsString(unsigned Index) const;
+ std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
typedef ArrayRef<Attribute>::iterator iterator;
- iterator begin(unsigned Idx) const;
- iterator end(unsigned Idx) const;
+ iterator begin(unsigned Slot) const;
+ iterator end(unsigned Slot) const;
/// operator==/!= - Provide equality predicates.
bool operator==(const AttributeSet &RHS) const {
unsigned getNumSlots() const;
/// \brief Return the index for the given slot.
- uint64_t getSlotIndex(unsigned Slot) const;
+ unsigned getSlotIndex(unsigned Slot) const;
/// \brief Return the attributes at the given slot.
AttributeSet getSlotAttributes(unsigned Slot) const;
//===----------------------------------------------------------------------===//
/// \class
-/// \brief Provide DenseMapInfo for Attribute::AttrKinds. This is used by
-/// AttrBuilder.
-template<> struct DenseMapInfo<Attribute::AttrKind> {
- static inline Attribute::AttrKind getEmptyKey() {
- return Attribute::AttrKindEmptyKey;
- }
- static inline Attribute::AttrKind getTombstoneKey() {
- return Attribute::AttrKindTombstoneKey;
+/// \brief Provide DenseMapInfo for AttributeSet.
+template<> struct DenseMapInfo<AttributeSet> {
+ static inline AttributeSet getEmptyKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
+ return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
}
- static unsigned getHashValue(const Attribute::AttrKind &Val) {
- return Val * 37U;
+ static inline AttributeSet getTombstoneKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-2);
+ Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
+ return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
}
- static bool isEqual(const Attribute::AttrKind &LHS,
- const Attribute::AttrKind &RHS) {
- return LHS == RHS;
+ static unsigned getHashValue(AttributeSet AS) {
+ return (unsigned((uintptr_t)AS.pImpl) >> 4) ^
+ (unsigned((uintptr_t)AS.pImpl) >> 9);
}
+ static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
};
//===----------------------------------------------------------------------===//
/// value, however, is not. So this can be used as a quick way to test for
/// equality, presence of attributes, etc.
class AttrBuilder {
- DenseSet<Attribute::AttrKind> Attrs;
+ std::bitset<Attribute::EndAttrKinds> Attrs;
std::map<std::string, std::string> TargetDepAttrs;
uint64_t Alignment;
uint64_t StackAlignment;
+ uint64_t DerefBytes;
+ uint64_t DerefOrNullBytes;
+
public:
- AttrBuilder() : Alignment(0), StackAlignment(0) {}
- explicit AttrBuilder(uint64_t Val) : Alignment(0), StackAlignment(0) {
+ AttrBuilder()
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {}
+ explicit AttrBuilder(uint64_t Val)
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {
addRawValue(Val);
}
- AttrBuilder(const Attribute &A) : Alignment(0), StackAlignment(0) {
+ AttrBuilder(const Attribute &A)
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {
addAttribute(A);
}
AttrBuilder(AttributeSet AS, unsigned Idx);
- AttrBuilder(const AttrBuilder &B)
- : Attrs(B.Attrs),
- TargetDepAttrs(B.TargetDepAttrs.begin(), B.TargetDepAttrs.end()),
- Alignment(B.Alignment), StackAlignment(B.StackAlignment) {}
void clear();
AttrBuilder &addAttribute(Attribute A);
/// \brief Add the target-dependent attribute to the builder.
- AttrBuilder &addAttribute(StringRef A, StringRef V);
+ AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef());
/// \brief Remove an attribute from the builder.
AttrBuilder &removeAttribute(Attribute::AttrKind Val);
/// \brief Add the attributes from the builder.
AttrBuilder &merge(const AttrBuilder &B);
+ /// \brief Remove the attributes from the builder.
+ AttrBuilder &remove(const AttrBuilder &B);
+
+ /// \brief Return true if the builder has any attribute that's in the
+ /// specified builder.
+ bool overlaps(const AttrBuilder &B) const;
+
/// \brief Return true if the builder has the specified attribute.
- bool contains(Attribute::AttrKind A) const;
+ bool contains(Attribute::AttrKind A) const {
+ assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
+ return Attrs[A];
+ }
/// \brief Return true if the builder has the specified target-dependent
/// attribute.
/// \brief Retrieve the stack alignment attribute, if it exists.
uint64_t getStackAlignment() const { return StackAlignment; }
+ /// \brief Retrieve the number of dereferenceable bytes, if the
+ /// dereferenceable attribute exists (zero is returned otherwise).
+ uint64_t getDereferenceableBytes() const { return DerefBytes; }
+
+ /// \brief Retrieve the number of dereferenceable_or_null bytes, if the
+ /// dereferenceable_or_null attribute exists (zero is returned otherwise).
+ uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
+
/// \brief This turns an int alignment (which must be a power of 2) into the
/// form used internally in Attribute.
AttrBuilder &addAlignmentAttr(unsigned Align);
/// the form used internally in Attribute.
AttrBuilder &addStackAlignmentAttr(unsigned Align);
- // Iterators for target-independent attributes.
- typedef DenseSet<Attribute::AttrKind>::iterator iterator;
- typedef DenseSet<Attribute::AttrKind>::const_iterator const_iterator;
+ /// \brief This turns the number of dereferenceable bytes into the form used
+ /// internally in Attribute.
+ AttrBuilder &addDereferenceableAttr(uint64_t Bytes);
- iterator begin() { return Attrs.begin(); }
- iterator end() { return Attrs.end(); }
+ /// \brief This turns the number of dereferenceable_or_null bytes into the
+ /// form used internally in Attribute.
+ AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
- const_iterator begin() const { return Attrs.begin(); }
- const_iterator end() const { return Attrs.end(); }
+ /// \brief Return true if the builder contains no target-independent
+ /// attributes.
+ bool empty() const { return Attrs.none(); }
// Iterators for target-dependent attributes.
typedef std::pair<std::string, std::string> td_type;
typedef std::map<std::string, std::string>::iterator td_iterator;
typedef std::map<std::string, std::string>::const_iterator td_const_iterator;
+ typedef llvm::iterator_range<td_iterator> td_range;
+ typedef llvm::iterator_range<td_const_iterator> td_const_range;
td_iterator td_begin() { return TargetDepAttrs.begin(); }
td_iterator td_end() { return TargetDepAttrs.end(); }
td_const_iterator td_begin() const { return TargetDepAttrs.begin(); }
td_const_iterator td_end() const { return TargetDepAttrs.end(); }
- /// \brief Remove attributes that are used on functions only.
- void removeFunctionOnlyAttrs() {
- removeAttribute(Attribute::NoReturn)
- .removeAttribute(Attribute::NoUnwind)
- .removeAttribute(Attribute::ReadNone)
- .removeAttribute(Attribute::ReadOnly)
- .removeAttribute(Attribute::NoInline)
- .removeAttribute(Attribute::AlwaysInline)
- .removeAttribute(Attribute::OptimizeForSize)
- .removeAttribute(Attribute::StackProtect)
- .removeAttribute(Attribute::StackProtectReq)
- .removeAttribute(Attribute::StackProtectStrong)
- .removeAttribute(Attribute::NoRedZone)
- .removeAttribute(Attribute::NoImplicitFloat)
- .removeAttribute(Attribute::Naked)
- .removeAttribute(Attribute::InlineHint)
- .removeAttribute(Attribute::StackAlignment)
- .removeAttribute(Attribute::UWTable)
- .removeAttribute(Attribute::NonLazyBind)
- .removeAttribute(Attribute::ReturnsTwice)
- .removeAttribute(Attribute::AddressSafety)
- .removeAttribute(Attribute::MinSize)
- .removeAttribute(Attribute::NoDuplicate);
+ td_range td_attrs() { return td_range(td_begin(), td_end()); }
+ td_const_range td_attrs() const {
+ return td_const_range(td_begin(), td_end());
}
+ bool td_empty() const { return TargetDepAttrs.empty(); }
+
bool operator==(const AttrBuilder &B);
bool operator!=(const AttrBuilder &B) {
return !(*this == B);
namespace AttributeFuncs {
/// \brief Which attributes cannot be applied to a type.
-AttributeSet typeIncompatible(Type *Ty, uint64_t Index);
+AttrBuilder typeIncompatible(Type *Ty);
+
+/// \returns Return true if the two functions have compatible target-independent
+/// attributes for inlining purposes.
+bool areInlineCompatible(const Function &Caller, const Function &Callee);
+
+/// \brief Merge caller's and callee's attributes.
+void mergeAttributesForInlining(Function &Caller, const Function &Callee);
} // end AttributeFuncs namespace