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 16280031Sdim#ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H 17280031Sdim#define LLVM_LIB_IR_ATTRIBUTEIMPL_H 18249259Sdim 19249259Sdim#include "llvm/ADT/FoldingSet.h" 20249259Sdim#include "llvm/IR/Attributes.h" 21296417Sdim#include "llvm/Support/TrailingObjects.h" 22249259Sdim#include <string> 23249259Sdim 24249259Sdimnamespace llvm { 25249259Sdim 26249259Sdimclass Constant; 27249259Sdimclass LLVMContext; 28249259Sdim 29249259Sdim//===----------------------------------------------------------------------===// 30249259Sdim/// \class 31261991Sdim/// \brief This class represents a single, uniqued attribute. That attribute 32261991Sdim/// could be a single enum, a tuple, or a string. 33261991Sdimclass AttributeImpl : public FoldingSetNode { 34261991Sdim unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 35261991Sdim 36261991Sdim // AttributesImpl is uniqued, these should not be publicly available. 37288943Sdim void operator=(const AttributeImpl &) = delete; 38288943Sdim AttributeImpl(const AttributeImpl &) = delete; 39261991Sdim 40249259Sdimprotected: 41249259Sdim enum AttrEntryKind { 42249259Sdim EnumAttrEntry, 43276479Sdim IntAttrEntry, 44249259Sdim StringAttrEntry 45249259Sdim }; 46249259Sdim 47261991Sdim AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} 48249259Sdim 49249259Sdimpublic: 50261991Sdim virtual ~AttributeImpl(); 51249259Sdim 52261991Sdim bool isEnumAttribute() const { return KindID == EnumAttrEntry; } 53276479Sdim bool isIntAttribute() const { return KindID == IntAttrEntry; } 54261991Sdim bool isStringAttribute() const { return KindID == StringAttrEntry; } 55249259Sdim 56249259Sdim bool hasAttribute(Attribute::AttrKind A) const; 57249259Sdim bool hasAttribute(StringRef Kind) const; 58249259Sdim 59249259Sdim Attribute::AttrKind getKindAsEnum() const; 60249259Sdim uint64_t getValueAsInt() const; 61249259Sdim 62249259Sdim StringRef getKindAsString() const; 63249259Sdim StringRef getValueAsString() const; 64249259Sdim 65249259Sdim /// \brief Used when sorting the attributes. 66249259Sdim bool operator<(const AttributeImpl &AI) const; 67249259Sdim 68249259Sdim void Profile(FoldingSetNodeID &ID) const { 69249259Sdim if (isEnumAttribute()) 70249259Sdim Profile(ID, getKindAsEnum(), 0); 71276479Sdim else if (isIntAttribute()) 72249259Sdim Profile(ID, getKindAsEnum(), getValueAsInt()); 73249259Sdim else 74249259Sdim Profile(ID, getKindAsString(), getValueAsString()); 75249259Sdim } 76249259Sdim static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 77249259Sdim uint64_t Val) { 78249259Sdim ID.AddInteger(Kind); 79249259Sdim if (Val) ID.AddInteger(Val); 80249259Sdim } 81249259Sdim static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { 82249259Sdim ID.AddString(Kind); 83249259Sdim if (!Values.empty()) ID.AddString(Values); 84249259Sdim } 85249259Sdim 86249259Sdim // FIXME: Remove this! 87249259Sdim static uint64_t getAttrMask(Attribute::AttrKind Val); 88249259Sdim}; 89249259Sdim 90249259Sdim//===----------------------------------------------------------------------===// 91249259Sdim/// \class 92261991Sdim/// \brief A set of classes that contain the value of the 93261991Sdim/// attribute object. There are three main categories: enum attribute entries, 94261991Sdim/// represented by Attribute::AttrKind; alignment attribute entries; and string 95261991Sdim/// attribute enties, which are for target-dependent attributes. 96261991Sdim 97261991Sdimclass EnumAttributeImpl : public AttributeImpl { 98261991Sdim virtual void anchor(); 99261991Sdim Attribute::AttrKind Kind; 100261991Sdim 101261991Sdimprotected: 102261991Sdim EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 103261991Sdim : AttributeImpl(ID), Kind(Kind) {} 104261991Sdim 105261991Sdimpublic: 106261991Sdim EnumAttributeImpl(Attribute::AttrKind Kind) 107261991Sdim : AttributeImpl(EnumAttrEntry), Kind(Kind) {} 108261991Sdim 109261991Sdim Attribute::AttrKind getEnumKind() const { return Kind; } 110261991Sdim}; 111261991Sdim 112276479Sdimclass IntAttributeImpl : public EnumAttributeImpl { 113276479Sdim void anchor() override; 114276479Sdim uint64_t Val; 115261991Sdim 116261991Sdimpublic: 117276479Sdim IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) 118276479Sdim : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { 119288943Sdim assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || 120288943Sdim Kind == Attribute::Dereferenceable || 121288943Sdim Kind == Attribute::DereferenceableOrNull) && 122288943Sdim "Wrong kind for int attribute!"); 123261991Sdim } 124261991Sdim 125276479Sdim uint64_t getValue() const { return Val; } 126261991Sdim}; 127261991Sdim 128261991Sdimclass StringAttributeImpl : public AttributeImpl { 129261991Sdim virtual void anchor(); 130261991Sdim std::string Kind; 131261991Sdim std::string Val; 132261991Sdim 133261991Sdimpublic: 134261991Sdim StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) 135261991Sdim : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {} 136261991Sdim 137261991Sdim StringRef getStringKind() const { return Kind; } 138261991Sdim StringRef getStringValue() const { return Val; } 139261991Sdim}; 140261991Sdim 141261991Sdim//===----------------------------------------------------------------------===// 142261991Sdim/// \class 143249259Sdim/// \brief This class represents a group of attributes that apply to one 144249259Sdim/// element: function, return type, or parameter. 145296417Sdimclass AttributeSetNode final 146296417Sdim : public FoldingSetNode, 147296417Sdim private TrailingObjects<AttributeSetNode, Attribute> { 148296417Sdim friend TrailingObjects; 149296417Sdim 150261991Sdim unsigned NumAttrs; ///< Number of attributes in this node. 151249259Sdim 152261991Sdim AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) { 153261991Sdim // There's memory after the node where we can store the entries in. 154296417Sdim std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>()); 155261991Sdim } 156249259Sdim 157249259Sdim // AttributesSetNode is uniqued, these should not be publicly available. 158288943Sdim void operator=(const AttributeSetNode &) = delete; 159288943Sdim AttributeSetNode(const AttributeSetNode &) = delete; 160249259Sdimpublic: 161249259Sdim static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); 162249259Sdim 163249259Sdim bool hasAttribute(Attribute::AttrKind Kind) const; 164249259Sdim bool hasAttribute(StringRef Kind) const; 165261991Sdim bool hasAttributes() const { return NumAttrs != 0; } 166249259Sdim 167249259Sdim Attribute getAttribute(Attribute::AttrKind Kind) const; 168249259Sdim Attribute getAttribute(StringRef Kind) const; 169249259Sdim 170249259Sdim unsigned getAlignment() const; 171249259Sdim unsigned getStackAlignment() const; 172276479Sdim uint64_t getDereferenceableBytes() const; 173288943Sdim uint64_t getDereferenceableOrNullBytes() const; 174249259Sdim std::string getAsString(bool InAttrGrp) const; 175249259Sdim 176261991Sdim typedef const Attribute *iterator; 177296417Sdim iterator begin() const { return getTrailingObjects<Attribute>(); } 178261991Sdim iterator end() const { return begin() + NumAttrs; } 179249259Sdim 180249259Sdim void Profile(FoldingSetNodeID &ID) const { 181261991Sdim Profile(ID, makeArrayRef(begin(), end())); 182249259Sdim } 183249259Sdim static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { 184249259Sdim for (unsigned I = 0, E = AttrList.size(); I != E; ++I) 185249259Sdim AttrList[I].Profile(ID); 186249259Sdim } 187249259Sdim}; 188249259Sdim 189296417Sdimtypedef std::pair<unsigned, AttributeSetNode *> IndexAttrPair; 190296417Sdim 191249259Sdim//===----------------------------------------------------------------------===// 192249259Sdim/// \class 193249259Sdim/// \brief This class represents a set of attributes that apply to the function, 194249259Sdim/// return type, and parameters. 195296417Sdimclass AttributeSetImpl final 196296417Sdim : public FoldingSetNode, 197296417Sdim private TrailingObjects<AttributeSetImpl, IndexAttrPair> { 198249259Sdim friend class AttributeSet; 199296417Sdim friend TrailingObjects; 200249259Sdim 201288943Sdimprivate: 202249259Sdim LLVMContext &Context; 203261991Sdim unsigned NumAttrs; ///< Number of entries in this set. 204249259Sdim 205296417Sdim // Helper fn for TrailingObjects class. 206296417Sdim size_t numTrailingObjects(OverloadToken<IndexAttrPair>) { return NumAttrs; } 207296417Sdim 208261991Sdim /// \brief Return a pointer to the IndexAttrPair for the specified slot. 209261991Sdim const IndexAttrPair *getNode(unsigned Slot) const { 210296417Sdim return getTrailingObjects<IndexAttrPair>() + Slot; 211261991Sdim } 212261991Sdim 213249259Sdim // AttributesSet is uniqued, these should not be publicly available. 214288943Sdim void operator=(const AttributeSetImpl &) = delete; 215288943Sdim AttributeSetImpl(const AttributeSetImpl &) = delete; 216249259Sdimpublic: 217249259Sdim AttributeSetImpl(LLVMContext &C, 218261991Sdim ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs) 219261991Sdim : Context(C), NumAttrs(Attrs.size()) { 220288943Sdim 221261991Sdim#ifndef NDEBUG 222261991Sdim if (Attrs.size() >= 2) { 223261991Sdim for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1, 224261991Sdim *e = Attrs.end(); 225261991Sdim i != e; ++i) { 226261991Sdim assert((i-1)->first <= i->first && "Attribute set not ordered!"); 227261991Sdim } 228261991Sdim } 229261991Sdim#endif 230261991Sdim // There's memory after the node where we can store the entries in. 231296417Sdim std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<IndexAttrPair>()); 232261991Sdim } 233249259Sdim 234249259Sdim /// \brief Get the context that created this AttributeSetImpl. 235249259Sdim LLVMContext &getContext() { return Context; } 236249259Sdim 237249259Sdim /// \brief Return the number of attributes this AttributeSet contains. 238261991Sdim unsigned getNumAttributes() const { return NumAttrs; } 239249259Sdim 240249259Sdim /// \brief Get the index of the given "slot" in the AttrNodes list. This index 241249259Sdim /// is the index of the return, parameter, or function object that the 242249259Sdim /// attributes are applied to, not the index into the AttrNodes list where the 243249259Sdim /// attributes reside. 244251662Sdim unsigned getSlotIndex(unsigned Slot) const { 245261991Sdim return getNode(Slot)->first; 246249259Sdim } 247249259Sdim 248249259Sdim /// \brief Retrieve the attributes for the given "slot" in the AttrNode list. 249249259Sdim /// \p Slot is an index into the AttrNodes list, not the index of the return / 250249259Sdim /// parameter/ function which the attributes apply to. 251249259Sdim AttributeSet getSlotAttributes(unsigned Slot) const { 252261991Sdim return AttributeSet::get(Context, *getNode(Slot)); 253249259Sdim } 254249259Sdim 255249259Sdim /// \brief Retrieve the attribute set node for the given "slot" in the 256249259Sdim /// AttrNode list. 257249259Sdim AttributeSetNode *getSlotNode(unsigned Slot) const { 258261991Sdim return getNode(Slot)->second; 259249259Sdim } 260249259Sdim 261261991Sdim typedef AttributeSetNode::iterator iterator; 262261991Sdim iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); } 263261991Sdim iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); } 264249259Sdim 265249259Sdim void Profile(FoldingSetNodeID &ID) const { 266261991Sdim Profile(ID, makeArrayRef(getNode(0), getNumAttributes())); 267249259Sdim } 268249259Sdim static void Profile(FoldingSetNodeID &ID, 269249259Sdim ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) { 270249259Sdim for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { 271249259Sdim ID.AddInteger(Nodes[i].first); 272249259Sdim ID.AddPointer(Nodes[i].second); 273249259Sdim } 274249259Sdim } 275249259Sdim 276249259Sdim // FIXME: This atrocity is temporary. 277251662Sdim uint64_t Raw(unsigned Index) const; 278261991Sdim 279261991Sdim void dump() const; 280249259Sdim}; 281249259Sdim 282249259Sdim} // end llvm namespace 283249259Sdim 284249259Sdim#endif 285