+DECLARE_LLVM_ATTRIBUTE(NoCapture,1<<21) ///< Function creates no aliases of pointer
+DECLARE_LLVM_ATTRIBUTE(NoRedZone,1<<22) /// disable redzone
+DECLARE_LLVM_ATTRIBUTE(NoImplicitFloat,1<<23) /// disable implicit floating point
+ /// instructions.
+DECLARE_LLVM_ATTRIBUTE(Naked,1<<24) ///< Naked function
+DECLARE_LLVM_ATTRIBUTE(InlineHint,1<<25) ///< source said inlining was
+ ///desirable
+DECLARE_LLVM_ATTRIBUTE(StackAlignment,7<<26) ///< Alignment of stack for
+ ///function (3 bits) stored as log2
+ ///of alignment with +1 bias
+ ///0 means unaligned (different from
+ ///alignstack= {1))
+DECLARE_LLVM_ATTRIBUTE(ReturnsTwice,1<<29) ///< Function can return twice
+DECLARE_LLVM_ATTRIBUTE(UWTable,1<<30) ///< Function must be in a unwind
+ ///table
+DECLARE_LLVM_ATTRIBUTE(NonLazyBind,1U<<31) ///< Function is called early and/or
+ /// often, so lazy binding isn't
+ /// worthwhile.
+DECLARE_LLVM_ATTRIBUTE(AddressSafety,1ULL<<32) ///< Address safety checking is on.
+
+#undef DECLARE_LLVM_ATTRIBUTE
+
+} // namespace Attribute
+
+/// Attributes - A bitset of attributes.
+class Attributes {
+ // Currently, we need less than 64 bits.
+ uint64_t Bits;
+public:
+ Attributes() : Bits(0) { }
+ explicit Attributes(uint64_t Val) : Bits(Val) { }
+ /*implicit*/ Attributes(Attribute::AttrConst Val) : Bits(Val.v) { }
+
+ // Attribute query methods.
+ // FIXME: StackAlignment & Alignment attributes have no predicate methods.
+ bool hasAttributes() const {
+ return Bits != 0;
+ }
+ bool hasAttributes(const Attributes &A) const {
+ return Bits & A.Bits;
+ }
+
+ bool hasZExtAttr() const {
+ return Bits & Attribute::ZExt_i;
+ }
+ bool hasSExtAttr() const {
+ return Bits & Attribute::SExt_i;
+ }
+ bool hasNoReturnAttr() const {
+ return Bits & Attribute::NoReturn_i;
+ }
+ bool hasInRegAttr() const {
+ return Bits & Attribute::InReg_i;
+ }
+ bool hasStructRetAttr() const {
+ return Bits & Attribute::StructRet_i;
+ }
+ bool hasNoUnwindAttr() const {
+ return Bits & Attribute::NoUnwind_i;
+ }
+ bool hasNoAliasAttr() const {
+ return Bits & Attribute::NoAlias_i;
+ }
+ bool hasByValAttr() const {
+ return Bits & Attribute::ByVal_i;
+ }
+ bool hasNestAttr() const {
+ return Bits & Attribute::Nest_i;
+ }
+ bool hasReadNoneAttr() const {
+ return Bits & Attribute::ReadNone_i;
+ }
+ bool hasReadOnlyAttr() const {
+ return Bits & Attribute::ReadOnly_i;
+ }
+ bool hasNoInlineAttr() const {
+ return Bits & Attribute::NoInline_i;
+ }
+ bool hasAlwaysInlineAttr() const {
+ return Bits & Attribute::AlwaysInline_i;
+ }
+ bool hasOptimizeForSizeAttr() const {
+ return Bits & Attribute::OptimizeForSize_i;
+ }
+ bool hasStackProtectAttr() const {
+ return Bits & Attribute::StackProtect_i;
+ }
+ bool hasStackProtectReqAttr() const {
+ return Bits & Attribute::StackProtectReq_i;
+ }
+ bool hasAlignmentAttr() const {
+ return Bits & Attribute::Alignment_i;
+ }
+ bool hasNoCaptureAttr() const {
+ return Bits & Attribute::NoCapture_i;
+ }
+ bool hasNoRedZoneAttr() const {
+ return Bits & Attribute::NoRedZone_i;
+ }
+ bool hasNoImplicitFloatAttr() const {
+ return Bits & Attribute::NoImplicitFloat_i;
+ }
+ bool hasNakedAttr() const {
+ return Bits & Attribute::Naked_i;
+ }
+ bool hasInlineHintAttr() const {
+ return Bits & Attribute::InlineHint_i;
+ }
+ bool hasReturnsTwiceAttr() const {
+ return Bits & Attribute::ReturnsTwice_i;
+ }
+ bool hasStackAlignmentAttr() const {
+ return Bits & Attribute::StackAlignment_i;
+ }
+ bool hasUWTableAttr() const {
+ return Bits & Attribute::UWTable_i;
+ }
+ bool hasNonLazyBindAttr() const {
+ return Bits & Attribute::NonLazyBind_i;
+ }
+ bool hasAddressSafetyAttr() const {
+ return Bits & Attribute::AddressSafety_i;
+ }
+
+ uint64_t getRawAlignment() const {
+ return Bits & Attribute::Alignment_i;
+ }
+ uint64_t getRawStackAlignment() const {
+ return Bits & Attribute::StackAlignment_i;
+ }
+
+ // This is a "safe bool() operator".
+ operator const void *() const { return Bits ? this : 0; }
+ bool isEmptyOrSingleton() const { return (Bits & (Bits - 1)) == 0; }
+ bool operator == (const Attributes &Attrs) const {
+ return Bits == Attrs.Bits;
+ }
+ bool operator != (const Attributes &Attrs) const {
+ return Bits != Attrs.Bits;
+ }
+ Attributes operator | (const Attributes &Attrs) const {
+ return Attributes(Bits | Attrs.Bits);
+ }
+ Attributes operator & (const Attributes &Attrs) const {
+ return Attributes(Bits & Attrs.Bits);
+ }
+ Attributes operator ^ (const Attributes &Attrs) const {
+ return Attributes(Bits ^ Attrs.Bits);
+ }
+ Attributes &operator |= (const Attributes &Attrs) {
+ Bits |= Attrs.Bits;
+ return *this;
+ }
+ Attributes &operator &= (const Attributes &Attrs) {
+ Bits &= Attrs.Bits;
+ return *this;
+ }
+ Attributes operator ~ () const { return Attributes(~Bits); }
+ uint64_t Raw() const { return Bits; }
+
+ /// The set of Attributes set in Attributes is converted to a string of
+ /// equivalent mnemonics. This is, presumably, for writing out the mnemonics
+ /// for the assembly writer.
+ /// @brief Convert attribute bits to text
+ std::string getAsString() const;
+};
+
+namespace Attribute {
+
+/// Note that uwtable is about the ABI or the user mandating an entry in the
+/// unwind table. The nounwind attribute is about an exception passing by the
+/// function.
+/// In a theoretical system that uses tables for profiling and sjlj for
+/// exceptions, they would be fully independent. In a normal system that
+/// uses tables for both, the semantics are:
+/// nil = Needs an entry because an exception might pass by.
+/// nounwind = No need for an entry
+/// uwtable = Needs an entry because the ABI says so and because
+/// an exception might pass by.
+/// uwtable + nounwind = Needs an entry because the ABI says so.