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