1249259Sdim//===-- AttributeImpl.h - Attribute Internals -------------------*- C++ -*-===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim/// 10249259Sdim/// \file 11249259Sdim/// \brief This file defines various helper methods and classes used by 12249259Sdim/// LLVMContextImpl for creating and managing attributes. 13249259Sdim/// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#ifndef LLVM_ATTRIBUTESIMPL_H 17249259Sdim#define LLVM_ATTRIBUTESIMPL_H 18249259Sdim 19249259Sdim#include "llvm/ADT/FoldingSet.h" 20249259Sdim#include "llvm/IR/Attributes.h" 21249259Sdim#include <string> 22249259Sdim 23249259Sdimnamespace llvm { 24249259Sdim 25249259Sdimclass Constant; 26249259Sdimclass LLVMContext; 27249259Sdim 28249259Sdim//===----------------------------------------------------------------------===// 29249259Sdim/// \class 30263509Sdim/// \brief This class represents a single, uniqued attribute. That attribute 31263509Sdim/// could be a single enum, a tuple, or a string. 32263509Sdimclass AttributeImpl : public FoldingSetNode { 33263509Sdim unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 34263509Sdim 35263509Sdim // AttributesImpl is uniqued, these should not be publicly available. 36263509Sdim void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION; 37263509Sdim AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION; 38263509Sdim 39249259Sdimprotected: 40249259Sdim enum AttrEntryKind { 41249259Sdim EnumAttrEntry, 42249259Sdim AlignAttrEntry, 43249259Sdim StringAttrEntry 44249259Sdim }; 45249259Sdim 46263509Sdim AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} 47249259Sdim 48249259Sdimpublic: 49263509Sdim virtual ~AttributeImpl(); 50249259Sdim 51263509Sdim bool isEnumAttribute() const { return KindID == EnumAttrEntry; } 52263509Sdim bool isAlignAttribute() const { return KindID == AlignAttrEntry; } 53263509Sdim bool isStringAttribute() const { return KindID == StringAttrEntry; } 54249259Sdim 55249259Sdim bool hasAttribute(Attribute::AttrKind A) const; 56249259Sdim bool hasAttribute(StringRef Kind) const; 57249259Sdim 58249259Sdim Attribute::AttrKind getKindAsEnum() const; 59249259Sdim uint64_t getValueAsInt() const; 60249259Sdim 61249259Sdim StringRef getKindAsString() const; 62249259Sdim StringRef getValueAsString() const; 63249259Sdim 64249259Sdim /// \brief Used when sorting the attributes. 65249259Sdim bool operator<(const AttributeImpl &AI) const; 66249259Sdim 67249259Sdim void Profile(FoldingSetNodeID &ID) const { 68249259Sdim if (isEnumAttribute()) 69249259Sdim Profile(ID, getKindAsEnum(), 0); 70249259Sdim else if (isAlignAttribute()) 71249259Sdim Profile(ID, getKindAsEnum(), getValueAsInt()); 72249259Sdim else 73249259Sdim Profile(ID, getKindAsString(), getValueAsString()); 74249259Sdim } 75249259Sdim static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 76249259Sdim uint64_t Val) { 77249259Sdim ID.AddInteger(Kind); 78249259Sdim if (Val) ID.AddInteger(Val); 79249259Sdim } 80249259Sdim static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { 81249259Sdim ID.AddString(Kind); 82249259Sdim if (!Values.empty()) ID.AddString(Values); 83249259Sdim } 84249259Sdim 85249259Sdim // FIXME: Remove this! 86249259Sdim static uint64_t getAttrMask(Attribute::AttrKind Val); 87249259Sdim}; 88249259Sdim 89249259Sdim//===----------------------------------------------------------------------===// 90249259Sdim/// \class 91263509Sdim/// \brief A set of classes that contain the value of the 92263509Sdim/// attribute object. There are three main categories: enum attribute entries, 93263509Sdim/// represented by Attribute::AttrKind; alignment attribute entries; and string 94263509Sdim/// attribute enties, which are for target-dependent attributes. 95263509Sdim 96263509Sdimclass EnumAttributeImpl : public AttributeImpl { 97263509Sdim virtual void anchor(); 98263509Sdim Attribute::AttrKind Kind; 99263509Sdim 100263509Sdimprotected: 101263509Sdim EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 102263509Sdim : AttributeImpl(ID), Kind(Kind) {} 103263509Sdim 104263509Sdimpublic: 105263509Sdim EnumAttributeImpl(Attribute::AttrKind Kind) 106263509Sdim : AttributeImpl(EnumAttrEntry), Kind(Kind) {} 107263509Sdim 108263509Sdim Attribute::AttrKind getEnumKind() const { return Kind; } 109263509Sdim}; 110263509Sdim 111263509Sdimclass AlignAttributeImpl : public EnumAttributeImpl { 112263509Sdim virtual void anchor(); 113263509Sdim unsigned Align; 114263509Sdim 115263509Sdimpublic: 116263509Sdim AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align) 117263509Sdim : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) { 118263509Sdim assert( 119263509Sdim (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) && 120263509Sdim "Wrong kind for alignment attribute!"); 121263509Sdim } 122263509Sdim 123263509Sdim unsigned getAlignment() const { return Align; } 124263509Sdim}; 125263509Sdim 126263509Sdimclass StringAttributeImpl : public AttributeImpl { 127263509Sdim virtual void anchor(); 128263509Sdim std::string Kind; 129263509Sdim std::string Val; 130263509Sdim 131263509Sdimpublic: 132263509Sdim StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) 133263509Sdim : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {} 134263509Sdim 135263509Sdim StringRef getStringKind() const { return Kind; } 136263509Sdim StringRef getStringValue() const { return Val; } 137263509Sdim}; 138263509Sdim 139263509Sdim//===----------------------------------------------------------------------===// 140263509Sdim/// \class 141249259Sdim/// \brief This class represents a group of attributes that apply to one 142249259Sdim/// element: function, return type, or parameter. 143249259Sdimclass AttributeSetNode : public FoldingSetNode { 144263509Sdim unsigned NumAttrs; ///< Number of attributes in this node. 145249259Sdim 146263509Sdim AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) { 147263509Sdim // There's memory after the node where we can store the entries in. 148263509Sdim std::copy(Attrs.begin(), Attrs.end(), 149263509Sdim reinterpret_cast<Attribute *>(this + 1)); 150263509Sdim } 151249259Sdim 152249259Sdim // AttributesSetNode is uniqued, these should not be publicly available. 153249259Sdim void operator=(const AttributeSetNode &) LLVM_DELETED_FUNCTION; 154249259Sdim AttributeSetNode(const AttributeSetNode &) LLVM_DELETED_FUNCTION; 155249259Sdimpublic: 156249259Sdim static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); 157249259Sdim 158249259Sdim bool hasAttribute(Attribute::AttrKind Kind) const; 159249259Sdim bool hasAttribute(StringRef Kind) const; 160263509Sdim bool hasAttributes() const { return NumAttrs != 0; } 161249259Sdim 162249259Sdim Attribute getAttribute(Attribute::AttrKind Kind) const; 163249259Sdim Attribute getAttribute(StringRef Kind) const; 164249259Sdim 165249259Sdim unsigned getAlignment() const; 166249259Sdim unsigned getStackAlignment() const; 167249259Sdim std::string getAsString(bool InAttrGrp) const; 168249259Sdim 169263509Sdim typedef const Attribute *iterator; 170263509Sdim iterator begin() const { return reinterpret_cast<iterator>(this + 1); } 171263509Sdim iterator end() const { return begin() + NumAttrs; } 172249259Sdim 173249259Sdim void Profile(FoldingSetNodeID &ID) const { 174263509Sdim Profile(ID, makeArrayRef(begin(), end())); 175249259Sdim } 176249259Sdim static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { 177249259Sdim for (unsigned I = 0, E = AttrList.size(); I != E; ++I) 178249259Sdim AttrList[I].Profile(ID); 179249259Sdim } 180249259Sdim}; 181249259Sdim 182249259Sdim//===----------------------------------------------------------------------===// 183249259Sdim/// \class 184249259Sdim/// \brief This class represents a set of attributes that apply to the function, 185249259Sdim/// return type, and parameters. 186249259Sdimclass AttributeSetImpl : public FoldingSetNode { 187249259Sdim friend class AttributeSet; 188249259Sdim 189249259Sdim LLVMContext &Context; 190249259Sdim 191249259Sdim typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair; 192263509Sdim unsigned NumAttrs; ///< Number of entries in this set. 193249259Sdim 194263509Sdim /// \brief Return a pointer to the IndexAttrPair for the specified slot. 195263509Sdim const IndexAttrPair *getNode(unsigned Slot) const { 196263509Sdim return reinterpret_cast<const IndexAttrPair *>(this + 1) + Slot; 197263509Sdim } 198263509Sdim 199249259Sdim // AttributesSet is uniqued, these should not be publicly available. 200249259Sdim void operator=(const AttributeSetImpl &) LLVM_DELETED_FUNCTION; 201249259Sdim AttributeSetImpl(const AttributeSetImpl &) LLVM_DELETED_FUNCTION; 202249259Sdimpublic: 203249259Sdim AttributeSetImpl(LLVMContext &C, 204263509Sdim ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs) 205263509Sdim : Context(C), NumAttrs(Attrs.size()) { 206263509Sdim#ifndef NDEBUG 207263509Sdim if (Attrs.size() >= 2) { 208263509Sdim for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1, 209263509Sdim *e = Attrs.end(); 210263509Sdim i != e; ++i) { 211263509Sdim assert((i-1)->first <= i->first && "Attribute set not ordered!"); 212263509Sdim } 213263509Sdim } 214263509Sdim#endif 215263509Sdim // There's memory after the node where we can store the entries in. 216263509Sdim std::copy(Attrs.begin(), Attrs.end(), 217263509Sdim reinterpret_cast<IndexAttrPair *>(this + 1)); 218263509Sdim } 219249259Sdim 220249259Sdim /// \brief Get the context that created this AttributeSetImpl. 221249259Sdim LLVMContext &getContext() { return Context; } 222249259Sdim 223249259Sdim /// \brief Return the number of attributes this AttributeSet contains. 224263509Sdim unsigned getNumAttributes() const { return NumAttrs; } 225249259Sdim 226249259Sdim /// \brief Get the index of the given "slot" in the AttrNodes list. This index 227249259Sdim /// is the index of the return, parameter, or function object that the 228249259Sdim /// attributes are applied to, not the index into the AttrNodes list where the 229249259Sdim /// attributes reside. 230252723Sdim unsigned getSlotIndex(unsigned Slot) const { 231263509Sdim return getNode(Slot)->first; 232249259Sdim } 233249259Sdim 234249259Sdim /// \brief Retrieve the attributes for the given "slot" in the AttrNode list. 235249259Sdim /// \p Slot is an index into the AttrNodes list, not the index of the return / 236249259Sdim /// parameter/ function which the attributes apply to. 237249259Sdim AttributeSet getSlotAttributes(unsigned Slot) const { 238263509Sdim return AttributeSet::get(Context, *getNode(Slot)); 239249259Sdim } 240249259Sdim 241249259Sdim /// \brief Retrieve the attribute set node for the given "slot" in the 242249259Sdim /// AttrNode list. 243249259Sdim AttributeSetNode *getSlotNode(unsigned Slot) const { 244263509Sdim return getNode(Slot)->second; 245249259Sdim } 246249259Sdim 247263509Sdim typedef AttributeSetNode::iterator iterator; 248263509Sdim iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); } 249263509Sdim iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); } 250249259Sdim 251249259Sdim void Profile(FoldingSetNodeID &ID) const { 252263509Sdim Profile(ID, makeArrayRef(getNode(0), getNumAttributes())); 253249259Sdim } 254249259Sdim static void Profile(FoldingSetNodeID &ID, 255249259Sdim ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) { 256249259Sdim for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { 257249259Sdim ID.AddInteger(Nodes[i].first); 258249259Sdim ID.AddPointer(Nodes[i].second); 259249259Sdim } 260249259Sdim } 261249259Sdim 262249259Sdim // FIXME: This atrocity is temporary. 263252723Sdim uint64_t Raw(unsigned Index) const; 264263509Sdim 265263509Sdim void dump() const; 266249259Sdim}; 267249259Sdim 268249259Sdim} // end llvm namespace 269249259Sdim 270249259Sdim#endif 271