AttributeImpl.h revision 360784
167754Smsmith//===- AttributeImpl.h - Attribute Internals --------------------*- C++ -*-===// 267754Smsmith// 367754Smsmith// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 467754Smsmith// See https://llvm.org/LICENSE.txt for license information. 567754Smsmith// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 667754Smsmith// 7217365Sjkim//===----------------------------------------------------------------------===// 8306536Sjkim/// 970243Smsmith/// \file 1067754Smsmith/// This file defines various helper methods and classes used by 11217365Sjkim/// LLVMContextImpl for creating and managing attributes. 12217365Sjkim/// 13217365Sjkim//===----------------------------------------------------------------------===// 14217365Sjkim 15217365Sjkim#ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H 16217365Sjkim#define LLVM_LIB_IR_ATTRIBUTEIMPL_H 17217365Sjkim 18217365Sjkim#include "llvm/ADT/ArrayRef.h" 19217365Sjkim#include "llvm/ADT/FoldingSet.h" 20217365Sjkim#include "llvm/ADT/StringRef.h" 21217365Sjkim#include "llvm/IR/Attributes.h" 22217365Sjkim#include "llvm/Support/TrailingObjects.h" 23217365Sjkim#include <cassert> 24217365Sjkim#include <cstddef> 2567754Smsmith#include <cstdint> 26217365Sjkim#include <string> 27217365Sjkim#include <utility> 28217365Sjkim 2967754Smsmithnamespace llvm { 30217365Sjkim 31217365Sjkimclass LLVMContext; 32217365Sjkimclass Type; 33217365Sjkim 34217365Sjkim//===----------------------------------------------------------------------===// 35217365Sjkim/// \class 36217365Sjkim/// This class represents a single, uniqued attribute. That attribute 37217365Sjkim/// could be a single enum, a tuple, or a string. 38217365Sjkimclass AttributeImpl : public FoldingSetNode { 39217365Sjkim unsigned char KindID; ///< Holds the AttrEntryKind of the attribute 40217365Sjkim 41217365Sjkimprotected: 42217365Sjkim enum AttrEntryKind { 4367754Smsmith EnumAttrEntry, 44193341Sjkim IntAttrEntry, 45193341Sjkim StringAttrEntry, 46193341Sjkim TypeAttrEntry, 47193341Sjkim }; 48193341Sjkim 49193341Sjkim AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} 50193341Sjkim 51306536Sjkimpublic: 52193341Sjkim // AttributesImpl is uniqued, these should not be available. 5367754Smsmith AttributeImpl(const AttributeImpl &) = delete; 5467754Smsmith AttributeImpl &operator=(const AttributeImpl &) = delete; 55102550Siwasaki 5691116Smsmith virtual ~AttributeImpl(); 5767754Smsmith 58151937Sjkim bool isEnumAttribute() const { return KindID == EnumAttrEntry; } 5967754Smsmith bool isIntAttribute() const { return KindID == IntAttrEntry; } 60151937Sjkim bool isStringAttribute() const { return KindID == StringAttrEntry; } 61151937Sjkim bool isTypeAttribute() const { return KindID == TypeAttrEntry; } 62151937Sjkim 63151937Sjkim bool hasAttribute(Attribute::AttrKind A) const; 64151937Sjkim bool hasAttribute(StringRef Kind) const; 65151937Sjkim 66151937Sjkim Attribute::AttrKind getKindAsEnum() const; 67151937Sjkim uint64_t getValueAsInt() const; 68249663Sjkim 69249663Sjkim StringRef getKindAsString() const; 70249663Sjkim StringRef getValueAsString() const; 71249663Sjkim 72249663Sjkim Type *getValueAsType() const; 73249663Sjkim 74151937Sjkim /// Used when sorting the attributes. 75220663Sjkim bool operator<(const AttributeImpl &AI) const; 76220663Sjkim 77220663Sjkim void Profile(FoldingSetNodeID &ID) const { 78220663Sjkim if (isEnumAttribute()) 79220663Sjkim Profile(ID, getKindAsEnum(), static_cast<uint64_t>(0)); 80220663Sjkim else if (isIntAttribute()) 81220663Sjkim Profile(ID, getKindAsEnum(), getValueAsInt()); 82249663Sjkim else if (isStringAttribute()) 83220663Sjkim Profile(ID, getKindAsString(), getValueAsString()); 84220663Sjkim else 85220663Sjkim Profile(ID, getKindAsEnum(), getValueAsType()); 86220663Sjkim } 87220663Sjkim 88220663Sjkim static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 89220663Sjkim uint64_t Val) { 90220663Sjkim ID.AddInteger(Kind); 91220663Sjkim if (Val) ID.AddInteger(Val); 92220663Sjkim } 93220663Sjkim 94220663Sjkim static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { 95220663Sjkim ID.AddString(Kind); 96220663Sjkim if (!Values.empty()) ID.AddString(Values); 97228110Sjkim } 98228110Sjkim 99220663Sjkim static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, 100220663Sjkim Type *Ty) { 101220663Sjkim ID.AddInteger(Kind); 102220663Sjkim ID.AddPointer(Ty); 103220663Sjkim } 104220663Sjkim}; 105220663Sjkim 106220663Sjkim//===----------------------------------------------------------------------===// 107220663Sjkim/// \class 108220663Sjkim/// A set of classes that contain the value of the 109220663Sjkim/// attribute object. There are three main categories: enum attribute entries, 110220663Sjkim/// represented by Attribute::AttrKind; alignment attribute entries; and string 111220663Sjkim/// attribute enties, which are for target-dependent attributes. 112220663Sjkim 113220663Sjkimclass EnumAttributeImpl : public AttributeImpl { 114234623Sjkim virtual void anchor(); 115234623Sjkim 116220663Sjkim Attribute::AttrKind Kind; 117220663Sjkim 118220663Sjkimprotected: 119220663Sjkim EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) 120220663Sjkim : AttributeImpl(ID), Kind(Kind) {} 121220663Sjkim 122151937Sjkimpublic: 12367754Smsmith EnumAttributeImpl(Attribute::AttrKind Kind) 12467754Smsmith : AttributeImpl(EnumAttrEntry), Kind(Kind) {} 12567754Smsmith 12667754Smsmith Attribute::AttrKind getEnumKind() const { return Kind; } 12767754Smsmith}; 12867754Smsmith 12967754Smsmithclass IntAttributeImpl : public EnumAttributeImpl { 13067754Smsmith uint64_t Val; 13167754Smsmith 132151937Sjkim void anchor() override; 13367754Smsmith 134151937Sjkimpublic: 13567754Smsmith IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) 13667754Smsmith : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { 13767754Smsmith assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || 13867754Smsmith Kind == Attribute::Dereferenceable || 139252279Sjkim Kind == Attribute::DereferenceableOrNull || 14067754Smsmith Kind == Attribute::AllocSize) && 14167754Smsmith "Wrong kind for int attribute!"); 142306536Sjkim } 143252279Sjkim 14467754Smsmith uint64_t getValue() const { return Val; } 14567754Smsmith}; 14667754Smsmith 14767754Smsmithclass StringAttributeImpl : public AttributeImpl { 14867754Smsmith virtual void anchor(); 14967754Smsmith 15067754Smsmith std::string Kind; 15167754Smsmith std::string Val; 15267754Smsmith 15367754Smsmithpublic: 15467754Smsmith StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) 15567754Smsmith : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {} 15667754Smsmith 15767754Smsmith StringRef getStringKind() const { return Kind; } 15867754Smsmith StringRef getStringValue() const { return Val; } 15967754Smsmith}; 160151937Sjkim 16167754Smsmithclass TypeAttributeImpl : public EnumAttributeImpl { 16267754Smsmith void anchor() override; 16367754Smsmith 16483174Smsmith Type *Ty; 16567754Smsmith 16667754Smsmithpublic: 16799679Siwasaki TypeAttributeImpl(Attribute::AttrKind Kind, Type *Ty) 16867754Smsmith : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {} 16967754Smsmith 17099679Siwasaki Type *getTypeValue() const { return Ty; } 17167754Smsmith}; 172151937Sjkim 173151937Sjkim//===----------------------------------------------------------------------===// 17467754Smsmith/// \class 17599679Siwasaki/// This class represents a group of attributes that apply to one 17699679Siwasaki/// element: function, return type, or parameter. 17799679Siwasakiclass AttributeSetNode final 17867754Smsmith : public FoldingSetNode, 17967754Smsmith private TrailingObjects<AttributeSetNode, Attribute> { 18067754Smsmith friend TrailingObjects; 18167754Smsmith 18267754Smsmith unsigned NumAttrs; ///< Number of attributes in this node. 18367754Smsmith /// Bitset with a bit for each available attribute Attribute::AttrKind. 18467754Smsmith uint8_t AvailableAttrs[12] = {}; 185241973Sjkim 18667754Smsmith AttributeSetNode(ArrayRef<Attribute> Attrs); 18767754Smsmith 18867754Smsmithpublic: 18967754Smsmith // AttributesSetNode is uniqued, these should not be available. 19067754Smsmith AttributeSetNode(const AttributeSetNode &) = delete; 19167754Smsmith AttributeSetNode &operator=(const AttributeSetNode &) = delete; 19267754Smsmith 19367754Smsmith void operator delete(void *p) { ::operator delete(p); } 19467754Smsmith 19567754Smsmith static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B); 19667754Smsmith 197114237Snjl static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); 198114237Snjl 19967754Smsmith /// Return the number of attributes this AttributeList contains. 20067754Smsmith unsigned getNumAttributes() const { return NumAttrs; } 20167754Smsmith 20287031Smsmith bool hasAttribute(Attribute::AttrKind Kind) const { 20367754Smsmith return AvailableAttrs[Kind / 8] & ((uint64_t)1) << (Kind % 8); 204114237Snjl } 20567754Smsmith bool hasAttribute(StringRef Kind) const; 20667754Smsmith bool hasAttributes() const { return NumAttrs != 0; } 20767754Smsmith 20867754Smsmith Attribute getAttribute(Attribute::AttrKind Kind) const; 20967754Smsmith Attribute getAttribute(StringRef Kind) const; 21067754Smsmith 21167754Smsmith MaybeAlign getAlignment() const; 21267754Smsmith MaybeAlign getStackAlignment() const; 21367754Smsmith uint64_t getDereferenceableBytes() const; 21467754Smsmith uint64_t getDereferenceableOrNullBytes() const; 21567754Smsmith std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; 21667754Smsmith std::string getAsString(bool InAttrGrp) const; 21767754Smsmith Type *getByValType() const; 21867754Smsmith 219151937Sjkim using iterator = const Attribute *; 22067754Smsmith 22167754Smsmith iterator begin() const { return getTrailingObjects<Attribute>(); } 22267754Smsmith iterator end() const { return begin() + NumAttrs; } 22367754Smsmith 22467754Smsmith void Profile(FoldingSetNodeID &ID) const { 22567754Smsmith Profile(ID, makeArrayRef(begin(), end())); 22667754Smsmith } 22767754Smsmith 22867754Smsmith static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { 22967754Smsmith for (const auto &Attr : AttrList) 23067754Smsmith Attr.Profile(ID); 23167754Smsmith } 23267754Smsmith}; 23367754Smsmith 23467754Smsmithusing IndexAttrPair = std::pair<unsigned, AttributeSet>; 23567754Smsmith 23667754Smsmith//===----------------------------------------------------------------------===// 23767754Smsmith/// \class 23867754Smsmith/// This class represents a set of attributes that apply to the function, 23967754Smsmith/// return type, and parameters. 24067754Smsmithclass AttributeListImpl final 24167754Smsmith : public FoldingSetNode, 24267754Smsmith private TrailingObjects<AttributeListImpl, AttributeSet> { 24367754Smsmith friend class AttributeList; 244306536Sjkim friend TrailingObjects; 245306536Sjkim 246151937Sjkimprivate: 24767754Smsmith LLVMContext &Context; 24867754Smsmith unsigned NumAttrSets; ///< Number of entries in this set. 24967754Smsmith /// Bitset with a bit for each available attribute Attribute::AttrKind. 25067754Smsmith uint8_t AvailableFunctionAttrs[12] = {}; 25167754Smsmith 25291116Smsmith // Helper fn for TrailingObjects class. 25367754Smsmith size_t numTrailingObjects(OverloadToken<AttributeSet>) { return NumAttrSets; } 25491116Smsmith 25567754Smsmithpublic: 25691116Smsmith AttributeListImpl(LLVMContext &C, ArrayRef<AttributeSet> Sets); 25791116Smsmith 25867754Smsmith // AttributesSetImpt is uniqued, these should not be available. 25967754Smsmith AttributeListImpl(const AttributeListImpl &) = delete; 260151937Sjkim AttributeListImpl &operator=(const AttributeListImpl &) = delete; 261306536Sjkim 262306536Sjkim void operator delete(void *p) { ::operator delete(p); } 26367754Smsmith 26467754Smsmith /// Get the context that created this AttributeListImpl. 26567754Smsmith LLVMContext &getContext() { return Context; } 26667754Smsmith 267151937Sjkim /// Return true if the AttributeSet or the FunctionIndex has an 26867754Smsmith /// enum attribute of the given kind. 26999679Siwasaki bool hasFnAttribute(Attribute::AttrKind Kind) const { 27091116Smsmith return AvailableFunctionAttrs[Kind / 8] & ((uint64_t)1) << (Kind % 8); 27191116Smsmith } 27291116Smsmith 27367754Smsmith using iterator = const AttributeSet *; 27467754Smsmith 275306536Sjkim iterator begin() const { return getTrailingObjects<AttributeSet>(); } 276306536Sjkim iterator end() const { return begin() + NumAttrSets; } 277151937Sjkim 27867754Smsmith void Profile(FoldingSetNodeID &ID) const; 27967754Smsmith static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeSet> Nodes); 28067754Smsmith 281306536Sjkim void dump() const; 282306536Sjkim}; 28377424Smsmith 28491116Smsmith} // end namespace llvm 28567754Smsmith 28691116Smsmith#endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H 28791116Smsmith