Home | History | Annotate | Download | only in IR
      1 //===-- AttributeImpl.h - Attribute Internals -------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief This file defines various helper methods and classes used by
     12 /// LLVMContextImpl for creating and managing attributes.
     13 ///
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_ATTRIBUTESIMPL_H
     17 #define LLVM_ATTRIBUTESIMPL_H
     18 
     19 #include "llvm/ADT/FoldingSet.h"
     20 #include "llvm/IR/Attributes.h"
     21 #include <string>
     22 
     23 namespace llvm {
     24 
     25 class Constant;
     26 class LLVMContext;
     27 
     28 //===----------------------------------------------------------------------===//
     29 /// \class
     30 /// \brief This class represents a single, uniqued attribute. That attribute
     31 /// could be a single enum, a tuple, or a string.
     32 class AttributeImpl : public FoldingSetNode {
     33   unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
     34 
     35   // AttributesImpl is uniqued, these should not be publicly available.
     36   void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION;
     37   AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION;
     38 
     39 protected:
     40   enum AttrEntryKind {
     41     EnumAttrEntry,
     42     AlignAttrEntry,
     43     StringAttrEntry
     44   };
     45 
     46   AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
     47 
     48 public:
     49   virtual ~AttributeImpl();
     50 
     51   bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
     52   bool isAlignAttribute() const { return KindID == AlignAttrEntry; }
     53   bool isStringAttribute() const { return KindID == StringAttrEntry; }
     54 
     55   bool hasAttribute(Attribute::AttrKind A) const;
     56   bool hasAttribute(StringRef Kind) const;
     57 
     58   Attribute::AttrKind getKindAsEnum() const;
     59   uint64_t getValueAsInt() const;
     60 
     61   StringRef getKindAsString() const;
     62   StringRef getValueAsString() const;
     63 
     64   /// \brief Used when sorting the attributes.
     65   bool operator<(const AttributeImpl &AI) const;
     66 
     67   void Profile(FoldingSetNodeID &ID) const {
     68     if (isEnumAttribute())
     69       Profile(ID, getKindAsEnum(), 0);
     70     else if (isAlignAttribute())
     71       Profile(ID, getKindAsEnum(), getValueAsInt());
     72     else
     73       Profile(ID, getKindAsString(), getValueAsString());
     74   }
     75   static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
     76                       uint64_t Val) {
     77     ID.AddInteger(Kind);
     78     if (Val) ID.AddInteger(Val);
     79   }
     80   static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) {
     81     ID.AddString(Kind);
     82     if (!Values.empty()) ID.AddString(Values);
     83   }
     84 
     85   // FIXME: Remove this!
     86   static uint64_t getAttrMask(Attribute::AttrKind Val);
     87 };
     88 
     89 //===----------------------------------------------------------------------===//
     90 /// \class
     91 /// \brief A set of classes that contain the value of the
     92 /// attribute object. There are three main categories: enum attribute entries,
     93 /// represented by Attribute::AttrKind; alignment attribute entries; and string
     94 /// attribute enties, which are for target-dependent attributes.
     95 
     96 class EnumAttributeImpl : public AttributeImpl {
     97   Attribute::AttrKind Kind;
     98 
     99 protected:
    100   EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind)
    101       : AttributeImpl(ID), Kind(Kind) {}
    102 
    103 public:
    104   EnumAttributeImpl(Attribute::AttrKind Kind)
    105       : AttributeImpl(EnumAttrEntry), Kind(Kind) {}
    106 
    107   Attribute::AttrKind getEnumKind() const { return Kind; }
    108 };
    109 
    110 class AlignAttributeImpl : public EnumAttributeImpl {
    111   unsigned Align;
    112 
    113 public:
    114   AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align)
    115       : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) {
    116     assert(
    117         (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) &&
    118         "Wrong kind for alignment attribute!");
    119   }
    120 
    121   unsigned getAlignment() const { return Align; }
    122 };
    123 
    124 class StringAttributeImpl : public AttributeImpl {
    125   std::string Kind;
    126   std::string Val;
    127 
    128 public:
    129   StringAttributeImpl(StringRef Kind, StringRef Val = StringRef())
    130       : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {}
    131 
    132   StringRef getStringKind() const { return Kind; }
    133   StringRef getStringValue() const { return Val; }
    134 };
    135 
    136 //===----------------------------------------------------------------------===//
    137 /// \class
    138 /// \brief This class represents a group of attributes that apply to one
    139 /// element: function, return type, or parameter.
    140 class AttributeSetNode : public FoldingSetNode {
    141   unsigned NumAttrs; ///< Number of attributes in this node.
    142 
    143   AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) {
    144     // There's memory after the node where we can store the entries in.
    145     std::copy(Attrs.begin(), Attrs.end(),
    146               reinterpret_cast<Attribute *>(this + 1));
    147   }
    148 
    149   // AttributesSetNode is uniqued, these should not be publicly available.
    150   void operator=(const AttributeSetNode &) LLVM_DELETED_FUNCTION;
    151   AttributeSetNode(const AttributeSetNode &) LLVM_DELETED_FUNCTION;
    152 public:
    153   static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
    154 
    155   bool hasAttribute(Attribute::AttrKind Kind) const;
    156   bool hasAttribute(StringRef Kind) const;
    157   bool hasAttributes() const { return NumAttrs != 0; }
    158 
    159   Attribute getAttribute(Attribute::AttrKind Kind) const;
    160   Attribute getAttribute(StringRef Kind) const;
    161 
    162   unsigned getAlignment() const;
    163   unsigned getStackAlignment() const;
    164   std::string getAsString(bool InAttrGrp) const;
    165 
    166   typedef const Attribute *iterator;
    167   iterator begin() const { return reinterpret_cast<iterator>(this + 1); }
    168   iterator end() const { return begin() + NumAttrs; }
    169 
    170   void Profile(FoldingSetNodeID &ID) const {
    171     Profile(ID, makeArrayRef(begin(), end()));
    172   }
    173   static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
    174     for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
    175       AttrList[I].Profile(ID);
    176   }
    177 };
    178 
    179 //===----------------------------------------------------------------------===//
    180 /// \class
    181 /// \brief This class represents a set of attributes that apply to the function,
    182 /// return type, and parameters.
    183 class AttributeSetImpl : public FoldingSetNode {
    184   friend class AttributeSet;
    185 
    186   LLVMContext &Context;
    187 
    188   typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair;
    189   unsigned NumAttrs; ///< Number of entries in this set.
    190 
    191   /// \brief Return a pointer to the IndexAttrPair for the specified slot.
    192   const IndexAttrPair *getNode(unsigned Slot) const {
    193     return reinterpret_cast<const IndexAttrPair *>(this + 1) + Slot;
    194   }
    195 
    196   // AttributesSet is uniqued, these should not be publicly available.
    197   void operator=(const AttributeSetImpl &) LLVM_DELETED_FUNCTION;
    198   AttributeSetImpl(const AttributeSetImpl &) LLVM_DELETED_FUNCTION;
    199 public:
    200   AttributeSetImpl(LLVMContext &C,
    201                    ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
    202       : Context(C), NumAttrs(Attrs.size()) {
    203 #ifndef NDEBUG
    204     if (Attrs.size() >= 2) {
    205       for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1,
    206                                                          *e = Attrs.end();
    207            i != e; ++i) {
    208         assert((i-1)->first <= i->first && "Attribute set not ordered!");
    209       }
    210     }
    211 #endif
    212     // There's memory after the node where we can store the entries in.
    213     std::copy(Attrs.begin(), Attrs.end(),
    214               reinterpret_cast<IndexAttrPair *>(this + 1));
    215   }
    216 
    217   /// \brief Get the context that created this AttributeSetImpl.
    218   LLVMContext &getContext() { return Context; }
    219 
    220   /// \brief Return the number of attributes this AttributeSet contains.
    221   unsigned getNumAttributes() const { return NumAttrs; }
    222 
    223   /// \brief Get the index of the given "slot" in the AttrNodes list. This index
    224   /// is the index of the return, parameter, or function object that the
    225   /// attributes are applied to, not the index into the AttrNodes list where the
    226   /// attributes reside.
    227   unsigned getSlotIndex(unsigned Slot) const {
    228     return getNode(Slot)->first;
    229   }
    230 
    231   /// \brief Retrieve the attributes for the given "slot" in the AttrNode list.
    232   /// \p Slot is an index into the AttrNodes list, not the index of the return /
    233   /// parameter/ function which the attributes apply to.
    234   AttributeSet getSlotAttributes(unsigned Slot) const {
    235     return AttributeSet::get(Context, *getNode(Slot));
    236   }
    237 
    238   /// \brief Retrieve the attribute set node for the given "slot" in the
    239   /// AttrNode list.
    240   AttributeSetNode *getSlotNode(unsigned Slot) const {
    241     return getNode(Slot)->second;
    242   }
    243 
    244   typedef AttributeSetNode::iterator iterator;
    245   iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
    246   iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
    247 
    248   void Profile(FoldingSetNodeID &ID) const {
    249     Profile(ID, makeArrayRef(getNode(0), getNumAttributes()));
    250   }
    251   static void Profile(FoldingSetNodeID &ID,
    252                       ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) {
    253     for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
    254       ID.AddInteger(Nodes[i].first);
    255       ID.AddPointer(Nodes[i].second);
    256     }
    257   }
    258 
    259   // FIXME: This atrocity is temporary.
    260   uint64_t Raw(unsigned Index) const;
    261 
    262   void dump() const;
    263 };
    264 
    265 } // end llvm namespace
    266 
    267 #endif
    268