#ifndef LLVM_ATTRIBUTES_H
#define LLVM_ATTRIBUTES_H
#include "llvm/Support/MathExtras.h"
#include "llvm/ADT/ArrayRef.h"
#include <cassert>
#include <string>
namespace llvm {
class LLVMContext;
class Type;
namespace Attribute {
struct AttrConst {
uint64_t v;
AttrConst operator | (const AttrConst Attrs) const {
AttrConst Res = {v | Attrs.v};
return Res;
}
AttrConst operator ~ () const {
AttrConst Res = {~v};
return Res;
}
};
#define DECLARE_LLVM_ATTRIBUTE(name, value) \
const uint64_t name##_i = value; \
const AttrConst name = {value};
DECLARE_LLVM_ATTRIBUTE(None,0) DECLARE_LLVM_ATTRIBUTE(ZExt,1<<0) DECLARE_LLVM_ATTRIBUTE(SExt,1<<1) DECLARE_LLVM_ATTRIBUTE(NoReturn,1<<2) DECLARE_LLVM_ATTRIBUTE(InReg,1<<3) DECLARE_LLVM_ATTRIBUTE(StructRet,1<<4) DECLARE_LLVM_ATTRIBUTE(NoUnwind,1<<5) DECLARE_LLVM_ATTRIBUTE(NoAlias,1<<6) DECLARE_LLVM_ATTRIBUTE(ByVal,1<<7) DECLARE_LLVM_ATTRIBUTE(Nest,1<<8) DECLARE_LLVM_ATTRIBUTE(ReadNone,1<<9) DECLARE_LLVM_ATTRIBUTE(ReadOnly,1<<10) DECLARE_LLVM_ATTRIBUTE(NoInline,1<<11) DECLARE_LLVM_ATTRIBUTE(AlwaysInline,1<<12) DECLARE_LLVM_ATTRIBUTE(OptimizeForSize,1<<13) DECLARE_LLVM_ATTRIBUTE(StackProtect,1<<14) DECLARE_LLVM_ATTRIBUTE(StackProtectReq,1<<15) DECLARE_LLVM_ATTRIBUTE(Alignment,31<<16) DECLARE_LLVM_ATTRIBUTE(NoCapture,1<<21) DECLARE_LLVM_ATTRIBUTE(NoRedZone,1<<22) DECLARE_LLVM_ATTRIBUTE(NoImplicitFloat,1<<23) DECLARE_LLVM_ATTRIBUTE(Naked,1<<24) DECLARE_LLVM_ATTRIBUTE(InlineHint,1<<25) DECLARE_LLVM_ATTRIBUTE(StackAlignment,7<<26) DECLARE_LLVM_ATTRIBUTE(ReturnsTwice,1<<29) DECLARE_LLVM_ATTRIBUTE(UWTable,1<<30) DECLARE_LLVM_ATTRIBUTE(NonLazyBind,1U<<31) DECLARE_LLVM_ATTRIBUTE(AddressSafety,1ULL<<32)
#undef DECLARE_LLVM_ATTRIBUTE
const AttrConst ParameterOnly = {ByVal_i | Nest_i |
StructRet_i | NoCapture_i};
const AttrConst FunctionOnly = {NoReturn_i | NoUnwind_i | ReadNone_i |
ReadOnly_i | NoInline_i | AlwaysInline_i | OptimizeForSize_i |
StackProtect_i | StackProtectReq_i | NoRedZone_i | NoImplicitFloat_i |
Naked_i | InlineHint_i | StackAlignment_i |
UWTable_i | NonLazyBind_i | ReturnsTwice_i | AddressSafety_i};
const AttrConst VarArgsIncompatible = {StructRet_i};
const AttrConst MutuallyIncompatible[5] = {
{ByVal_i | Nest_i | StructRet_i},
{ByVal_i | Nest_i | InReg_i },
{ZExt_i | SExt_i},
{ReadNone_i | ReadOnly_i},
{NoInline_i | AlwaysInline_i}
};
}
class AttributesImpl;
class Attributes {
uint64_t Bits;
explicit Attributes(AttributesImpl *A);
public:
Attributes() : Bits(0) {}
explicit Attributes(uint64_t Val) : Bits(Val) {}
Attributes(Attribute::AttrConst Val) : Bits(Val.v) {}
class Builder {
friend class Attributes;
uint64_t Bits;
public:
Builder() : Bits(0) {}
Builder(const Attributes &A) : Bits(A.Bits) {}
void addZExtAttr() {
Bits |= Attribute::ZExt_i;
}
void addSExtAttr() {
Bits |= Attribute::SExt_i;
}
void addNoReturnAttr() {
Bits |= Attribute::NoReturn_i;
}
void addInRegAttr() {
Bits |= Attribute::InReg_i;
}
void addStructRetAttr() {
Bits |= Attribute::StructRet_i;
}
void addNoUnwindAttr() {
Bits |= Attribute::NoUnwind_i;
}
void addNoAliasAttr() {
Bits |= Attribute::NoAlias_i;
}
void addByValAttr() {
Bits |= Attribute::ByVal_i;
}
void addNestAttr() {
Bits |= Attribute::Nest_i;
}
void addReadNoneAttr() {
Bits |= Attribute::ReadNone_i;
}
void addReadOnlyAttr() {
Bits |= Attribute::ReadOnly_i;
}
void addNoInlineAttr() {
Bits |= Attribute::NoInline_i;
}
void addAlwaysInlineAttr() {
Bits |= Attribute::AlwaysInline_i;
}
void addOptimizeForSizeAttr() {
Bits |= Attribute::OptimizeForSize_i;
}
void addStackProtectAttr() {
Bits |= Attribute::StackProtect_i;
}
void addStackProtectReqAttr() {
Bits |= Attribute::StackProtectReq_i;
}
void addNoCaptureAttr() {
Bits |= Attribute::NoCapture_i;
}
void addNoRedZoneAttr() {
Bits |= Attribute::NoRedZone_i;
}
void addNoImplicitFloatAttr() {
Bits |= Attribute::NoImplicitFloat_i;
}
void addNakedAttr() {
Bits |= Attribute::Naked_i;
}
void addInlineHintAttr() {
Bits |= Attribute::InlineHint_i;
}
void addReturnsTwiceAttr() {
Bits |= Attribute::ReturnsTwice_i;
}
void addUWTableAttr() {
Bits |= Attribute::UWTable_i;
}
void addNonLazyBindAttr() {
Bits |= Attribute::NonLazyBind_i;
}
void addAddressSafetyAttr() {
Bits |= Attribute::AddressSafety_i;
}
void addAlignmentAttr(unsigned Align) {
if (Align == 0) return;
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
assert(Align <= 0x40000000 && "Alignment too large.");
Bits |= (Log2_32(Align) + 1) << 16;
}
void addStackAlignmentAttr(unsigned Align) {
if (Align == 0) return;
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
assert(Align <= 0x100 && "Alignment too large.");
Bits |= (Log2_32(Align) + 1) << 26;
}
};
static Attributes get(LLVMContext &Context, Builder &B);
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;
}
unsigned getAlignment() const {
if (!hasAlignmentAttr())
return 0;
return 1U << (((Bits & Attribute::Alignment_i) >> 16) - 1);
}
unsigned getStackAlignment() const {
if (!hasStackAlignmentAttr())
return 0;
return 1U << (((Bits & Attribute::StackAlignment_i) >> 26) - 1);
}
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; }
static Attributes constructAlignmentFromInt(unsigned i) {
if (i == 0)
return Attribute::None;
assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
assert(i <= 0x40000000 && "Alignment too large.");
return Attributes((Log2_32(i)+1) << 16);
}
static Attributes constructStackAlignmentFromInt(unsigned i) {
if (i == 0)
return Attribute::None;
assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
assert(i <= 0x100 && "Alignment too large.");
return Attributes((Log2_32(i)+1) << 26);
}
static Attributes typeIncompatible(Type *Ty);
static uint64_t encodeLLVMAttributesForBitcode(Attributes Attrs) {
uint64_t EncodedAttrs = Attrs.Raw() & 0xffff;
if (Attrs.hasAlignmentAttr())
EncodedAttrs |= (1ULL << 16) <<
(((Attrs.Bits & Attribute::Alignment_i) - 1) >> 16);
EncodedAttrs |= (Attrs.Raw() & (0xfffULL << 21)) << 11;
return EncodedAttrs;
}
static Attributes decodeLLVMAttributesForBitcode(uint64_t EncodedAttrs) {
unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
assert((!Alignment || isPowerOf2_32(Alignment)) &&
"Alignment must be a power of two.");
Attributes Attrs(EncodedAttrs & 0xffff);
if (Alignment)
Attrs |= Attributes::constructAlignmentFromInt(Alignment);
Attrs |= Attributes((EncodedAttrs & (0xfffULL << 32)) >> 11);
return Attrs;
}
std::string getAsString() const;
};
struct AttributeWithIndex {
Attributes Attrs; unsigned Index;
static AttributeWithIndex get(unsigned Idx, Attributes Attrs) {
AttributeWithIndex P;
P.Index = Idx;
P.Attrs = Attrs;
return P;
}
};
class AttributeListImpl;
class AttrListPtr {
AttributeListImpl *AttrList;
public:
AttrListPtr() : AttrList(0) {}
AttrListPtr(const AttrListPtr &P);
const AttrListPtr &operator=(const AttrListPtr &RHS);
~AttrListPtr();
static AttrListPtr get(ArrayRef<AttributeWithIndex> Attrs);
AttrListPtr addAttr(unsigned Idx, Attributes Attrs) const;
AttrListPtr removeAttr(unsigned Idx, Attributes Attrs) const;
Attributes getParamAttributes(unsigned Idx) const {
assert (Idx && Idx != ~0U && "Invalid parameter index!");
return getAttributes(Idx);
}
Attributes getRetAttributes() const {
return getAttributes(0);
}
Attributes getFnAttributes() const {
return getAttributes(~0U);
}
bool paramHasAttr(unsigned Idx, Attributes Attr) const {
return getAttributes(Idx).hasAttributes(Attr);
}
unsigned getParamAlignment(unsigned Idx) const {
return getAttributes(Idx).getAlignment();
}
bool hasAttrSomewhere(Attributes Attr) const;
bool operator==(const AttrListPtr &RHS) const
{ return AttrList == RHS.AttrList; }
bool operator!=(const AttrListPtr &RHS) const
{ return AttrList != RHS.AttrList; }
void dump() const;
void *getRawPointer() const {
return AttrList;
}
bool isEmpty() const {
return AttrList == 0;
}
unsigned getNumSlots() const;
const AttributeWithIndex &getSlot(unsigned Slot) const;
private:
explicit AttrListPtr(AttributeListImpl *L);
Attributes getAttributes(unsigned Idx) const;
};
}
#endif