xref: /openbsd-src/gnu/llvm/llvm/lib/IR/Attributes.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- Attributes.cpp - Implement AttributesList --------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // \file
1009467b48Spatrick // This file implements the Attribute, AttributeImpl, AttrBuilder,
1109467b48Spatrick // AttributeListImpl, and AttributeList classes.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick 
1509467b48Spatrick #include "llvm/IR/Attributes.h"
1609467b48Spatrick #include "AttributeImpl.h"
1709467b48Spatrick #include "LLVMContextImpl.h"
1809467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1909467b48Spatrick #include "llvm/ADT/FoldingSet.h"
2009467b48Spatrick #include "llvm/ADT/STLExtras.h"
2109467b48Spatrick #include "llvm/ADT/SmallVector.h"
2209467b48Spatrick #include "llvm/ADT/StringExtras.h"
2309467b48Spatrick #include "llvm/ADT/StringRef.h"
24097a140dSpatrick #include "llvm/ADT/StringSwitch.h"
2509467b48Spatrick #include "llvm/Config/llvm-config.h"
2609467b48Spatrick #include "llvm/IR/Function.h"
2709467b48Spatrick #include "llvm/IR/LLVMContext.h"
2809467b48Spatrick #include "llvm/IR/Type.h"
2909467b48Spatrick #include "llvm/Support/Compiler.h"
3009467b48Spatrick #include "llvm/Support/ErrorHandling.h"
31*d415bd75Srobert #include "llvm/Support/ModRef.h"
3209467b48Spatrick #include "llvm/Support/raw_ostream.h"
3309467b48Spatrick #include <algorithm>
3409467b48Spatrick #include <cassert>
3509467b48Spatrick #include <cstddef>
3609467b48Spatrick #include <cstdint>
3709467b48Spatrick #include <limits>
38*d415bd75Srobert #include <optional>
3909467b48Spatrick #include <string>
4009467b48Spatrick #include <tuple>
4109467b48Spatrick #include <utility>
4209467b48Spatrick 
4309467b48Spatrick using namespace llvm;
4409467b48Spatrick 
4509467b48Spatrick //===----------------------------------------------------------------------===//
4609467b48Spatrick // Attribute Construction Methods
4709467b48Spatrick //===----------------------------------------------------------------------===//
4809467b48Spatrick 
4909467b48Spatrick // allocsize has two integer arguments, but because they're both 32 bits, we can
5009467b48Spatrick // pack them into one 64-bit value, at the cost of making said value
5109467b48Spatrick // nonsensical.
5209467b48Spatrick //
5309467b48Spatrick // In order to do this, we need to reserve one value of the second (optional)
5409467b48Spatrick // allocsize argument to signify "not present."
5509467b48Spatrick static const unsigned AllocSizeNumElemsNotPresent = -1;
5609467b48Spatrick 
packAllocSizeArgs(unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)5709467b48Spatrick static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
58*d415bd75Srobert                                   const std::optional<unsigned> &NumElemsArg) {
59*d415bd75Srobert   assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
6009467b48Spatrick          "Attempting to pack a reserved value");
6109467b48Spatrick 
6209467b48Spatrick   return uint64_t(ElemSizeArg) << 32 |
63*d415bd75Srobert          NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
6409467b48Spatrick }
6509467b48Spatrick 
66*d415bd75Srobert static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)6709467b48Spatrick unpackAllocSizeArgs(uint64_t Num) {
6809467b48Spatrick   unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
6909467b48Spatrick   unsigned ElemSizeArg = Num >> 32;
7009467b48Spatrick 
71*d415bd75Srobert   std::optional<unsigned> NumElemsArg;
7209467b48Spatrick   if (NumElems != AllocSizeNumElemsNotPresent)
7309467b48Spatrick     NumElemsArg = NumElems;
7409467b48Spatrick   return std::make_pair(ElemSizeArg, NumElemsArg);
7509467b48Spatrick }
7609467b48Spatrick 
packVScaleRangeArgs(unsigned MinValue,std::optional<unsigned> MaxValue)77*d415bd75Srobert static uint64_t packVScaleRangeArgs(unsigned MinValue,
78*d415bd75Srobert                                     std::optional<unsigned> MaxValue) {
79*d415bd75Srobert   return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
8073471bf0Spatrick }
8173471bf0Spatrick 
82*d415bd75Srobert static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)83*d415bd75Srobert unpackVScaleRangeArgs(uint64_t Value) {
8473471bf0Spatrick   unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
8573471bf0Spatrick   unsigned MinValue = Value >> 32;
8673471bf0Spatrick 
87*d415bd75Srobert   return std::make_pair(MinValue,
88*d415bd75Srobert                         MaxValue > 0 ? MaxValue : std::optional<unsigned>());
8973471bf0Spatrick }
9073471bf0Spatrick 
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)9109467b48Spatrick Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
9209467b48Spatrick                          uint64_t Val) {
93*d415bd75Srobert   bool IsIntAttr = Attribute::isIntAttrKind(Kind);
94*d415bd75Srobert   assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
95*d415bd75Srobert          "Not an enum or int attribute");
9673471bf0Spatrick 
9709467b48Spatrick   LLVMContextImpl *pImpl = Context.pImpl;
9809467b48Spatrick   FoldingSetNodeID ID;
9909467b48Spatrick   ID.AddInteger(Kind);
100*d415bd75Srobert   if (IsIntAttr)
101*d415bd75Srobert     ID.AddInteger(Val);
102*d415bd75Srobert   else
103*d415bd75Srobert     assert(Val == 0 && "Value must be zero for enum attributes");
10409467b48Spatrick 
10509467b48Spatrick   void *InsertPoint;
10609467b48Spatrick   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
10709467b48Spatrick 
10809467b48Spatrick   if (!PA) {
10909467b48Spatrick     // If we didn't find any existing attributes of the same shape then create a
11009467b48Spatrick     // new one and insert it.
111*d415bd75Srobert     if (!IsIntAttr)
112097a140dSpatrick       PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
11309467b48Spatrick     else
114097a140dSpatrick       PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
11509467b48Spatrick     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
11609467b48Spatrick   }
11709467b48Spatrick 
11809467b48Spatrick   // Return the Attribute that we found or created.
11909467b48Spatrick   return Attribute(PA);
12009467b48Spatrick }
12109467b48Spatrick 
get(LLVMContext & Context,StringRef Kind,StringRef Val)12209467b48Spatrick Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
12309467b48Spatrick   LLVMContextImpl *pImpl = Context.pImpl;
12409467b48Spatrick   FoldingSetNodeID ID;
12509467b48Spatrick   ID.AddString(Kind);
12609467b48Spatrick   if (!Val.empty()) ID.AddString(Val);
12709467b48Spatrick 
12809467b48Spatrick   void *InsertPoint;
12909467b48Spatrick   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
13009467b48Spatrick 
13109467b48Spatrick   if (!PA) {
13209467b48Spatrick     // If we didn't find any existing attributes of the same shape then create a
13309467b48Spatrick     // new one and insert it.
134097a140dSpatrick     void *Mem =
135097a140dSpatrick         pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
136097a140dSpatrick                               alignof(StringAttributeImpl));
137097a140dSpatrick     PA = new (Mem) StringAttributeImpl(Kind, Val);
13809467b48Spatrick     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
13909467b48Spatrick   }
14009467b48Spatrick 
14109467b48Spatrick   // Return the Attribute that we found or created.
14209467b48Spatrick   return Attribute(PA);
14309467b48Spatrick }
14409467b48Spatrick 
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)14509467b48Spatrick Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
14609467b48Spatrick                          Type *Ty) {
14773471bf0Spatrick   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
14809467b48Spatrick   LLVMContextImpl *pImpl = Context.pImpl;
14909467b48Spatrick   FoldingSetNodeID ID;
15009467b48Spatrick   ID.AddInteger(Kind);
15109467b48Spatrick   ID.AddPointer(Ty);
15209467b48Spatrick 
15309467b48Spatrick   void *InsertPoint;
15409467b48Spatrick   AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
15509467b48Spatrick 
15609467b48Spatrick   if (!PA) {
15709467b48Spatrick     // If we didn't find any existing attributes of the same shape then create a
15809467b48Spatrick     // new one and insert it.
159097a140dSpatrick     PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
16009467b48Spatrick     pImpl->AttrsSet.InsertNode(PA, InsertPoint);
16109467b48Spatrick   }
16209467b48Spatrick 
16309467b48Spatrick   // Return the Attribute that we found or created.
16409467b48Spatrick   return Attribute(PA);
16509467b48Spatrick }
16609467b48Spatrick 
getWithAlignment(LLVMContext & Context,Align A)16709467b48Spatrick Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
168097a140dSpatrick   assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
16909467b48Spatrick   return get(Context, Alignment, A.value());
17009467b48Spatrick }
17109467b48Spatrick 
getWithStackAlignment(LLVMContext & Context,Align A)17209467b48Spatrick Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
17309467b48Spatrick   assert(A <= 0x100 && "Alignment too large.");
17409467b48Spatrick   return get(Context, StackAlignment, A.value());
17509467b48Spatrick }
17609467b48Spatrick 
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)17709467b48Spatrick Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
17809467b48Spatrick                                                 uint64_t Bytes) {
17909467b48Spatrick   assert(Bytes && "Bytes must be non-zero.");
18009467b48Spatrick   return get(Context, Dereferenceable, Bytes);
18109467b48Spatrick }
18209467b48Spatrick 
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)18309467b48Spatrick Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
18409467b48Spatrick                                                        uint64_t Bytes) {
18509467b48Spatrick   assert(Bytes && "Bytes must be non-zero.");
18609467b48Spatrick   return get(Context, DereferenceableOrNull, Bytes);
18709467b48Spatrick }
18809467b48Spatrick 
getWithByValType(LLVMContext & Context,Type * Ty)18909467b48Spatrick Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
19009467b48Spatrick   return get(Context, ByVal, Ty);
19109467b48Spatrick }
19209467b48Spatrick 
getWithStructRetType(LLVMContext & Context,Type * Ty)19373471bf0Spatrick Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
19473471bf0Spatrick   return get(Context, StructRet, Ty);
19573471bf0Spatrick }
19673471bf0Spatrick 
getWithByRefType(LLVMContext & Context,Type * Ty)19773471bf0Spatrick Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
19873471bf0Spatrick   return get(Context, ByRef, Ty);
19973471bf0Spatrick }
20073471bf0Spatrick 
getWithPreallocatedType(LLVMContext & Context,Type * Ty)201097a140dSpatrick Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
202097a140dSpatrick   return get(Context, Preallocated, Ty);
203097a140dSpatrick }
204097a140dSpatrick 
getWithInAllocaType(LLVMContext & Context,Type * Ty)20573471bf0Spatrick Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
20673471bf0Spatrick   return get(Context, InAlloca, Ty);
20773471bf0Spatrick }
20873471bf0Spatrick 
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)209*d415bd75Srobert Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
210*d415bd75Srobert                                         UWTableKind Kind) {
211*d415bd75Srobert   return get(Context, UWTable, uint64_t(Kind));
212*d415bd75Srobert }
213*d415bd75Srobert 
getWithMemoryEffects(LLVMContext & Context,MemoryEffects ME)214*d415bd75Srobert Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
215*d415bd75Srobert                                           MemoryEffects ME) {
216*d415bd75Srobert   return get(Context, Memory, ME.toIntValue());
217*d415bd75Srobert }
218*d415bd75Srobert 
21909467b48Spatrick Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)22009467b48Spatrick Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
221*d415bd75Srobert                                 const std::optional<unsigned> &NumElemsArg) {
22209467b48Spatrick   assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
22309467b48Spatrick          "Invalid allocsize arguments -- given allocsize(0, 0)");
22409467b48Spatrick   return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
22509467b48Spatrick }
22609467b48Spatrick 
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)22773471bf0Spatrick Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
22873471bf0Spatrick                                             unsigned MinValue,
22973471bf0Spatrick                                             unsigned MaxValue) {
23073471bf0Spatrick   return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
23173471bf0Spatrick }
23273471bf0Spatrick 
getAttrKindFromName(StringRef AttrName)233097a140dSpatrick Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
234097a140dSpatrick   return StringSwitch<Attribute::AttrKind>(AttrName)
235097a140dSpatrick #define GET_ATTR_NAMES
236097a140dSpatrick #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
237097a140dSpatrick   .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
238097a140dSpatrick #include "llvm/IR/Attributes.inc"
239097a140dSpatrick       .Default(Attribute::None);
240097a140dSpatrick }
241097a140dSpatrick 
getNameFromAttrKind(Attribute::AttrKind AttrKind)242097a140dSpatrick StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
243097a140dSpatrick   switch (AttrKind) {
244097a140dSpatrick #define GET_ATTR_NAMES
245097a140dSpatrick #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
246097a140dSpatrick   case Attribute::ENUM_NAME:                                                   \
247097a140dSpatrick     return #DISPLAY_NAME;
248097a140dSpatrick #include "llvm/IR/Attributes.inc"
249097a140dSpatrick   case Attribute::None:
250097a140dSpatrick     return "none";
251097a140dSpatrick   default:
252097a140dSpatrick     llvm_unreachable("invalid Kind");
253097a140dSpatrick   }
254097a140dSpatrick }
255097a140dSpatrick 
isExistingAttribute(StringRef Name)256097a140dSpatrick bool Attribute::isExistingAttribute(StringRef Name) {
257097a140dSpatrick   return StringSwitch<bool>(Name)
258097a140dSpatrick #define GET_ATTR_NAMES
259097a140dSpatrick #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
260097a140dSpatrick #include "llvm/IR/Attributes.inc"
261097a140dSpatrick       .Default(false);
262097a140dSpatrick }
263097a140dSpatrick 
26409467b48Spatrick //===----------------------------------------------------------------------===//
26509467b48Spatrick // Attribute Accessor Methods
26609467b48Spatrick //===----------------------------------------------------------------------===//
26709467b48Spatrick 
isEnumAttribute() const26809467b48Spatrick bool Attribute::isEnumAttribute() const {
26909467b48Spatrick   return pImpl && pImpl->isEnumAttribute();
27009467b48Spatrick }
27109467b48Spatrick 
isIntAttribute() const27209467b48Spatrick bool Attribute::isIntAttribute() const {
27309467b48Spatrick   return pImpl && pImpl->isIntAttribute();
27409467b48Spatrick }
27509467b48Spatrick 
isStringAttribute() const27609467b48Spatrick bool Attribute::isStringAttribute() const {
27709467b48Spatrick   return pImpl && pImpl->isStringAttribute();
27809467b48Spatrick }
27909467b48Spatrick 
isTypeAttribute() const28009467b48Spatrick bool Attribute::isTypeAttribute() const {
28109467b48Spatrick   return pImpl && pImpl->isTypeAttribute();
28209467b48Spatrick }
28309467b48Spatrick 
getKindAsEnum() const28409467b48Spatrick Attribute::AttrKind Attribute::getKindAsEnum() const {
28509467b48Spatrick   if (!pImpl) return None;
28609467b48Spatrick   assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
28709467b48Spatrick          "Invalid attribute type to get the kind as an enum!");
28809467b48Spatrick   return pImpl->getKindAsEnum();
28909467b48Spatrick }
29009467b48Spatrick 
getValueAsInt() const29109467b48Spatrick uint64_t Attribute::getValueAsInt() const {
29209467b48Spatrick   if (!pImpl) return 0;
29309467b48Spatrick   assert(isIntAttribute() &&
29409467b48Spatrick          "Expected the attribute to be an integer attribute!");
29509467b48Spatrick   return pImpl->getValueAsInt();
29609467b48Spatrick }
29709467b48Spatrick 
getValueAsBool() const29873471bf0Spatrick bool Attribute::getValueAsBool() const {
29973471bf0Spatrick   if (!pImpl) return false;
30073471bf0Spatrick   assert(isStringAttribute() &&
30173471bf0Spatrick          "Expected the attribute to be a string attribute!");
30273471bf0Spatrick   return pImpl->getValueAsBool();
30373471bf0Spatrick }
30473471bf0Spatrick 
getKindAsString() const30509467b48Spatrick StringRef Attribute::getKindAsString() const {
30609467b48Spatrick   if (!pImpl) return {};
30709467b48Spatrick   assert(isStringAttribute() &&
30809467b48Spatrick          "Invalid attribute type to get the kind as a string!");
30909467b48Spatrick   return pImpl->getKindAsString();
31009467b48Spatrick }
31109467b48Spatrick 
getValueAsString() const31209467b48Spatrick StringRef Attribute::getValueAsString() const {
31309467b48Spatrick   if (!pImpl) return {};
31409467b48Spatrick   assert(isStringAttribute() &&
31509467b48Spatrick          "Invalid attribute type to get the value as a string!");
31609467b48Spatrick   return pImpl->getValueAsString();
31709467b48Spatrick }
31809467b48Spatrick 
getValueAsType() const31909467b48Spatrick Type *Attribute::getValueAsType() const {
32009467b48Spatrick   if (!pImpl) return {};
32109467b48Spatrick   assert(isTypeAttribute() &&
32209467b48Spatrick          "Invalid attribute type to get the value as a type!");
32309467b48Spatrick   return pImpl->getValueAsType();
32409467b48Spatrick }
32509467b48Spatrick 
32609467b48Spatrick 
hasAttribute(AttrKind Kind) const32709467b48Spatrick bool Attribute::hasAttribute(AttrKind Kind) const {
32809467b48Spatrick   return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
32909467b48Spatrick }
33009467b48Spatrick 
hasAttribute(StringRef Kind) const33109467b48Spatrick bool Attribute::hasAttribute(StringRef Kind) const {
33209467b48Spatrick   if (!isStringAttribute()) return false;
33309467b48Spatrick   return pImpl && pImpl->hasAttribute(Kind);
33409467b48Spatrick }
33509467b48Spatrick 
getAlignment() const33609467b48Spatrick MaybeAlign Attribute::getAlignment() const {
33709467b48Spatrick   assert(hasAttribute(Attribute::Alignment) &&
33809467b48Spatrick          "Trying to get alignment from non-alignment attribute!");
33909467b48Spatrick   return MaybeAlign(pImpl->getValueAsInt());
34009467b48Spatrick }
34109467b48Spatrick 
getStackAlignment() const34209467b48Spatrick MaybeAlign Attribute::getStackAlignment() const {
34309467b48Spatrick   assert(hasAttribute(Attribute::StackAlignment) &&
34409467b48Spatrick          "Trying to get alignment from non-alignment attribute!");
34509467b48Spatrick   return MaybeAlign(pImpl->getValueAsInt());
34609467b48Spatrick }
34709467b48Spatrick 
getDereferenceableBytes() const34809467b48Spatrick uint64_t Attribute::getDereferenceableBytes() const {
34909467b48Spatrick   assert(hasAttribute(Attribute::Dereferenceable) &&
35009467b48Spatrick          "Trying to get dereferenceable bytes from "
35109467b48Spatrick          "non-dereferenceable attribute!");
35209467b48Spatrick   return pImpl->getValueAsInt();
35309467b48Spatrick }
35409467b48Spatrick 
getDereferenceableOrNullBytes() const35509467b48Spatrick uint64_t Attribute::getDereferenceableOrNullBytes() const {
35609467b48Spatrick   assert(hasAttribute(Attribute::DereferenceableOrNull) &&
35709467b48Spatrick          "Trying to get dereferenceable bytes from "
35809467b48Spatrick          "non-dereferenceable attribute!");
35909467b48Spatrick   return pImpl->getValueAsInt();
36009467b48Spatrick }
36109467b48Spatrick 
362*d415bd75Srobert std::pair<unsigned, std::optional<unsigned>>
getAllocSizeArgs() const363*d415bd75Srobert Attribute::getAllocSizeArgs() const {
36409467b48Spatrick   assert(hasAttribute(Attribute::AllocSize) &&
36509467b48Spatrick          "Trying to get allocsize args from non-allocsize attribute");
36609467b48Spatrick   return unpackAllocSizeArgs(pImpl->getValueAsInt());
36709467b48Spatrick }
36809467b48Spatrick 
getVScaleRangeMin() const369*d415bd75Srobert unsigned Attribute::getVScaleRangeMin() const {
37073471bf0Spatrick   assert(hasAttribute(Attribute::VScaleRange) &&
37173471bf0Spatrick          "Trying to get vscale args from non-vscale attribute");
372*d415bd75Srobert   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
373*d415bd75Srobert }
374*d415bd75Srobert 
getVScaleRangeMax() const375*d415bd75Srobert std::optional<unsigned> Attribute::getVScaleRangeMax() const {
376*d415bd75Srobert   assert(hasAttribute(Attribute::VScaleRange) &&
377*d415bd75Srobert          "Trying to get vscale args from non-vscale attribute");
378*d415bd75Srobert   return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
379*d415bd75Srobert }
380*d415bd75Srobert 
getUWTableKind() const381*d415bd75Srobert UWTableKind Attribute::getUWTableKind() const {
382*d415bd75Srobert   assert(hasAttribute(Attribute::UWTable) &&
383*d415bd75Srobert          "Trying to get unwind table kind from non-uwtable attribute");
384*d415bd75Srobert   return UWTableKind(pImpl->getValueAsInt());
385*d415bd75Srobert }
386*d415bd75Srobert 
getAllocKind() const387*d415bd75Srobert AllocFnKind Attribute::getAllocKind() const {
388*d415bd75Srobert   assert(hasAttribute(Attribute::AllocKind) &&
389*d415bd75Srobert          "Trying to get allockind value from non-allockind attribute");
390*d415bd75Srobert   return AllocFnKind(pImpl->getValueAsInt());
391*d415bd75Srobert }
392*d415bd75Srobert 
getMemoryEffects() const393*d415bd75Srobert MemoryEffects Attribute::getMemoryEffects() const {
394*d415bd75Srobert   assert(hasAttribute(Attribute::Memory) &&
395*d415bd75Srobert          "Can only call getMemoryEffects() on memory attribute");
396*d415bd75Srobert   return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
397*d415bd75Srobert }
398*d415bd75Srobert 
getModRefStr(ModRefInfo MR)399*d415bd75Srobert static const char *getModRefStr(ModRefInfo MR) {
400*d415bd75Srobert   switch (MR) {
401*d415bd75Srobert   case ModRefInfo::NoModRef:
402*d415bd75Srobert     return "none";
403*d415bd75Srobert   case ModRefInfo::Ref:
404*d415bd75Srobert     return "read";
405*d415bd75Srobert   case ModRefInfo::Mod:
406*d415bd75Srobert     return "write";
407*d415bd75Srobert   case ModRefInfo::ModRef:
408*d415bd75Srobert     return "readwrite";
409*d415bd75Srobert   }
410*d415bd75Srobert   llvm_unreachable("Invalid ModRefInfo");
41173471bf0Spatrick }
41273471bf0Spatrick 
getAsString(bool InAttrGrp) const41309467b48Spatrick std::string Attribute::getAsString(bool InAttrGrp) const {
41409467b48Spatrick   if (!pImpl) return {};
41509467b48Spatrick 
41673471bf0Spatrick   if (isEnumAttribute())
41773471bf0Spatrick     return getNameFromAttrKind(getKindAsEnum()).str();
41809467b48Spatrick 
41973471bf0Spatrick   if (isTypeAttribute()) {
42073471bf0Spatrick     std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
42109467b48Spatrick     Result += '(';
422097a140dSpatrick     raw_string_ostream OS(Result);
423097a140dSpatrick     getValueAsType()->print(OS, false, true);
424097a140dSpatrick     OS.flush();
425097a140dSpatrick     Result += ')';
426097a140dSpatrick     return Result;
427097a140dSpatrick   }
428097a140dSpatrick 
42909467b48Spatrick   // FIXME: These should be output like this:
43009467b48Spatrick   //
43109467b48Spatrick   //   align=4
43209467b48Spatrick   //   alignstack=8
43309467b48Spatrick   //
434*d415bd75Srobert   if (hasAttribute(Attribute::Alignment))
435*d415bd75Srobert     return (InAttrGrp ? "align=" + Twine(getValueAsInt())
436*d415bd75Srobert                       : "align " + Twine(getValueAsInt()))
437*d415bd75Srobert         .str();
43809467b48Spatrick 
43909467b48Spatrick   auto AttrWithBytesToString = [&](const char *Name) {
440*d415bd75Srobert     return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
441*d415bd75Srobert                       : Name + ("(" + Twine(getValueAsInt())) + ")")
442*d415bd75Srobert         .str();
44309467b48Spatrick   };
44409467b48Spatrick 
44509467b48Spatrick   if (hasAttribute(Attribute::StackAlignment))
44609467b48Spatrick     return AttrWithBytesToString("alignstack");
44709467b48Spatrick 
44809467b48Spatrick   if (hasAttribute(Attribute::Dereferenceable))
44909467b48Spatrick     return AttrWithBytesToString("dereferenceable");
45009467b48Spatrick 
45109467b48Spatrick   if (hasAttribute(Attribute::DereferenceableOrNull))
45209467b48Spatrick     return AttrWithBytesToString("dereferenceable_or_null");
45309467b48Spatrick 
45409467b48Spatrick   if (hasAttribute(Attribute::AllocSize)) {
45509467b48Spatrick     unsigned ElemSize;
456*d415bd75Srobert     std::optional<unsigned> NumElems;
45709467b48Spatrick     std::tie(ElemSize, NumElems) = getAllocSizeArgs();
45809467b48Spatrick 
459*d415bd75Srobert     return (NumElems
460*d415bd75Srobert                 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
461*d415bd75Srobert                 : "allocsize(" + Twine(ElemSize) + ")")
462*d415bd75Srobert         .str();
46309467b48Spatrick   }
46409467b48Spatrick 
46573471bf0Spatrick   if (hasAttribute(Attribute::VScaleRange)) {
466*d415bd75Srobert     unsigned MinValue = getVScaleRangeMin();
467*d415bd75Srobert     std::optional<unsigned> MaxValue = getVScaleRangeMax();
468*d415bd75Srobert     return ("vscale_range(" + Twine(MinValue) + "," +
469*d415bd75Srobert             Twine(MaxValue.value_or(0)) + ")")
470*d415bd75Srobert         .str();
471*d415bd75Srobert   }
47273471bf0Spatrick 
473*d415bd75Srobert   if (hasAttribute(Attribute::UWTable)) {
474*d415bd75Srobert     UWTableKind Kind = getUWTableKind();
475*d415bd75Srobert     if (Kind != UWTableKind::None) {
476*d415bd75Srobert       return Kind == UWTableKind::Default
477*d415bd75Srobert                  ? "uwtable"
478*d415bd75Srobert                  : ("uwtable(" +
479*d415bd75Srobert                     Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
480*d415bd75Srobert                        .str();
481*d415bd75Srobert     }
482*d415bd75Srobert   }
483*d415bd75Srobert 
484*d415bd75Srobert   if (hasAttribute(Attribute::AllocKind)) {
485*d415bd75Srobert     AllocFnKind Kind = getAllocKind();
486*d415bd75Srobert     SmallVector<StringRef> parts;
487*d415bd75Srobert     if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
488*d415bd75Srobert       parts.push_back("alloc");
489*d415bd75Srobert     if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
490*d415bd75Srobert       parts.push_back("realloc");
491*d415bd75Srobert     if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
492*d415bd75Srobert       parts.push_back("free");
493*d415bd75Srobert     if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
494*d415bd75Srobert       parts.push_back("uninitialized");
495*d415bd75Srobert     if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
496*d415bd75Srobert       parts.push_back("zeroed");
497*d415bd75Srobert     if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
498*d415bd75Srobert       parts.push_back("aligned");
499*d415bd75Srobert     return ("allockind(\"" +
500*d415bd75Srobert             Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
501*d415bd75Srobert         .str();
502*d415bd75Srobert   }
503*d415bd75Srobert 
504*d415bd75Srobert   if (hasAttribute(Attribute::Memory)) {
505*d415bd75Srobert     std::string Result;
506*d415bd75Srobert     raw_string_ostream OS(Result);
507*d415bd75Srobert     bool First = true;
508*d415bd75Srobert     OS << "memory(";
509*d415bd75Srobert 
510*d415bd75Srobert     MemoryEffects ME = getMemoryEffects();
511*d415bd75Srobert 
512*d415bd75Srobert     // Print access kind for "other" as the default access kind. This way it
513*d415bd75Srobert     // will apply to any new location kinds that get split out of "other".
514*d415bd75Srobert     ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
515*d415bd75Srobert     if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
516*d415bd75Srobert       First = false;
517*d415bd75Srobert       OS << getModRefStr(OtherMR);
518*d415bd75Srobert     }
519*d415bd75Srobert 
520*d415bd75Srobert     for (auto Loc : MemoryEffects::locations()) {
521*d415bd75Srobert       ModRefInfo MR = ME.getModRef(Loc);
522*d415bd75Srobert       if (MR == OtherMR)
523*d415bd75Srobert         continue;
524*d415bd75Srobert 
525*d415bd75Srobert       if (!First)
526*d415bd75Srobert         OS << ", ";
527*d415bd75Srobert       First = false;
528*d415bd75Srobert 
529*d415bd75Srobert       switch (Loc) {
530*d415bd75Srobert       case MemoryEffects::ArgMem:
531*d415bd75Srobert         OS << "argmem: ";
532*d415bd75Srobert         break;
533*d415bd75Srobert       case MemoryEffects::InaccessibleMem:
534*d415bd75Srobert         OS << "inaccessiblemem: ";
535*d415bd75Srobert         break;
536*d415bd75Srobert       case MemoryEffects::Other:
537*d415bd75Srobert         llvm_unreachable("This is represented as the default access kind");
538*d415bd75Srobert       }
539*d415bd75Srobert       OS << getModRefStr(MR);
540*d415bd75Srobert     }
541*d415bd75Srobert     OS << ")";
542*d415bd75Srobert     OS.flush();
54373471bf0Spatrick     return Result;
54473471bf0Spatrick   }
54573471bf0Spatrick 
54609467b48Spatrick   // Convert target-dependent attributes to strings of the form:
54709467b48Spatrick   //
54809467b48Spatrick   //   "kind"
54909467b48Spatrick   //   "kind" = "value"
55009467b48Spatrick   //
55109467b48Spatrick   if (isStringAttribute()) {
55209467b48Spatrick     std::string Result;
55309467b48Spatrick     {
55409467b48Spatrick       raw_string_ostream OS(Result);
555097a140dSpatrick       OS << '"' << getKindAsString() << '"';
556097a140dSpatrick 
557097a140dSpatrick       // Since some attribute strings contain special characters that cannot be
558097a140dSpatrick       // printable, those have to be escaped to make the attribute value
559097a140dSpatrick       // printable as is.  e.g. "\01__gnu_mcount_nc"
560097a140dSpatrick       const auto &AttrVal = pImpl->getValueAsString();
561097a140dSpatrick       if (!AttrVal.empty()) {
56209467b48Spatrick         OS << "=\"";
56309467b48Spatrick         printEscapedString(AttrVal, OS);
56409467b48Spatrick         OS << "\"";
56509467b48Spatrick       }
566097a140dSpatrick     }
56709467b48Spatrick     return Result;
56809467b48Spatrick   }
56909467b48Spatrick 
57009467b48Spatrick   llvm_unreachable("Unknown attribute");
57109467b48Spatrick }
57209467b48Spatrick 
hasParentContext(LLVMContext & C) const57373471bf0Spatrick bool Attribute::hasParentContext(LLVMContext &C) const {
57473471bf0Spatrick   assert(isValid() && "invalid Attribute doesn't refer to any context");
57573471bf0Spatrick   FoldingSetNodeID ID;
57673471bf0Spatrick   pImpl->Profile(ID);
57773471bf0Spatrick   void *Unused;
57873471bf0Spatrick   return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
57973471bf0Spatrick }
58073471bf0Spatrick 
operator <(Attribute A) const58109467b48Spatrick bool Attribute::operator<(Attribute A) const {
58209467b48Spatrick   if (!pImpl && !A.pImpl) return false;
58309467b48Spatrick   if (!pImpl) return true;
58409467b48Spatrick   if (!A.pImpl) return false;
58509467b48Spatrick   return *pImpl < *A.pImpl;
58609467b48Spatrick }
58709467b48Spatrick 
Profile(FoldingSetNodeID & ID) const588097a140dSpatrick void Attribute::Profile(FoldingSetNodeID &ID) const {
589097a140dSpatrick   ID.AddPointer(pImpl);
590097a140dSpatrick }
591097a140dSpatrick 
59273471bf0Spatrick enum AttributeProperty {
59373471bf0Spatrick   FnAttr = (1 << 0),
59473471bf0Spatrick   ParamAttr = (1 << 1),
59573471bf0Spatrick   RetAttr = (1 << 2),
59673471bf0Spatrick };
59773471bf0Spatrick 
59873471bf0Spatrick #define GET_ATTR_PROP_TABLE
59973471bf0Spatrick #include "llvm/IR/Attributes.inc"
60073471bf0Spatrick 
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)60173471bf0Spatrick static bool hasAttributeProperty(Attribute::AttrKind Kind,
60273471bf0Spatrick                                  AttributeProperty Prop) {
60373471bf0Spatrick   unsigned Index = Kind - 1;
604*d415bd75Srobert   assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
60573471bf0Spatrick   return AttrPropTable[Index] & Prop;
60673471bf0Spatrick }
60773471bf0Spatrick 
canUseAsFnAttr(AttrKind Kind)60873471bf0Spatrick bool Attribute::canUseAsFnAttr(AttrKind Kind) {
60973471bf0Spatrick   return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
61073471bf0Spatrick }
61173471bf0Spatrick 
canUseAsParamAttr(AttrKind Kind)61273471bf0Spatrick bool Attribute::canUseAsParamAttr(AttrKind Kind) {
61373471bf0Spatrick   return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
61473471bf0Spatrick }
61573471bf0Spatrick 
canUseAsRetAttr(AttrKind Kind)61673471bf0Spatrick bool Attribute::canUseAsRetAttr(AttrKind Kind) {
61773471bf0Spatrick   return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
61873471bf0Spatrick }
61973471bf0Spatrick 
62009467b48Spatrick //===----------------------------------------------------------------------===//
62109467b48Spatrick // AttributeImpl Definition
62209467b48Spatrick //===----------------------------------------------------------------------===//
62309467b48Spatrick 
hasAttribute(Attribute::AttrKind A) const62409467b48Spatrick bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
62509467b48Spatrick   if (isStringAttribute()) return false;
62609467b48Spatrick   return getKindAsEnum() == A;
62709467b48Spatrick }
62809467b48Spatrick 
hasAttribute(StringRef Kind) const62909467b48Spatrick bool AttributeImpl::hasAttribute(StringRef Kind) const {
63009467b48Spatrick   if (!isStringAttribute()) return false;
63109467b48Spatrick   return getKindAsString() == Kind;
63209467b48Spatrick }
63309467b48Spatrick 
getKindAsEnum() const63409467b48Spatrick Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
63509467b48Spatrick   assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
63609467b48Spatrick   return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
63709467b48Spatrick }
63809467b48Spatrick 
getValueAsInt() const63909467b48Spatrick uint64_t AttributeImpl::getValueAsInt() const {
64009467b48Spatrick   assert(isIntAttribute());
64109467b48Spatrick   return static_cast<const IntAttributeImpl *>(this)->getValue();
64209467b48Spatrick }
64309467b48Spatrick 
getValueAsBool() const64473471bf0Spatrick bool AttributeImpl::getValueAsBool() const {
64573471bf0Spatrick   assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
64673471bf0Spatrick   return getValueAsString() == "true";
64773471bf0Spatrick }
64873471bf0Spatrick 
getKindAsString() const64909467b48Spatrick StringRef AttributeImpl::getKindAsString() const {
65009467b48Spatrick   assert(isStringAttribute());
65109467b48Spatrick   return static_cast<const StringAttributeImpl *>(this)->getStringKind();
65209467b48Spatrick }
65309467b48Spatrick 
getValueAsString() const65409467b48Spatrick StringRef AttributeImpl::getValueAsString() const {
65509467b48Spatrick   assert(isStringAttribute());
65609467b48Spatrick   return static_cast<const StringAttributeImpl *>(this)->getStringValue();
65709467b48Spatrick }
65809467b48Spatrick 
getValueAsType() const65909467b48Spatrick Type *AttributeImpl::getValueAsType() const {
66009467b48Spatrick   assert(isTypeAttribute());
66109467b48Spatrick   return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
66209467b48Spatrick }
66309467b48Spatrick 
operator <(const AttributeImpl & AI) const66409467b48Spatrick bool AttributeImpl::operator<(const AttributeImpl &AI) const {
665097a140dSpatrick   if (this == &AI)
666097a140dSpatrick     return false;
66773471bf0Spatrick 
66809467b48Spatrick   // This sorts the attributes with Attribute::AttrKinds coming first (sorted
66909467b48Spatrick   // relative to their enum value) and then strings.
67073471bf0Spatrick   if (!isStringAttribute()) {
67173471bf0Spatrick     if (AI.isStringAttribute())
67273471bf0Spatrick       return true;
67373471bf0Spatrick     if (getKindAsEnum() != AI.getKindAsEnum())
67409467b48Spatrick       return getKindAsEnum() < AI.getKindAsEnum();
67573471bf0Spatrick     assert(!AI.isEnumAttribute() && "Non-unique attribute");
67673471bf0Spatrick     assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
67773471bf0Spatrick     // TODO: Is this actually needed?
67873471bf0Spatrick     assert(AI.isIntAttribute() && "Only possibility left");
67909467b48Spatrick     return getValueAsInt() < AI.getValueAsInt();
68009467b48Spatrick   }
68109467b48Spatrick 
68273471bf0Spatrick   if (!AI.isStringAttribute())
68373471bf0Spatrick     return false;
68409467b48Spatrick   if (getKindAsString() == AI.getKindAsString())
68509467b48Spatrick     return getValueAsString() < AI.getValueAsString();
68609467b48Spatrick   return getKindAsString() < AI.getKindAsString();
68709467b48Spatrick }
68809467b48Spatrick 
68909467b48Spatrick //===----------------------------------------------------------------------===//
69009467b48Spatrick // AttributeSet Definition
69109467b48Spatrick //===----------------------------------------------------------------------===//
69209467b48Spatrick 
get(LLVMContext & C,const AttrBuilder & B)69309467b48Spatrick AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
69409467b48Spatrick   return AttributeSet(AttributeSetNode::get(C, B));
69509467b48Spatrick }
69609467b48Spatrick 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)69709467b48Spatrick AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
69809467b48Spatrick   return AttributeSet(AttributeSetNode::get(C, Attrs));
69909467b48Spatrick }
70009467b48Spatrick 
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const70109467b48Spatrick AttributeSet AttributeSet::addAttribute(LLVMContext &C,
70209467b48Spatrick                                         Attribute::AttrKind Kind) const {
70309467b48Spatrick   if (hasAttribute(Kind)) return *this;
704*d415bd75Srobert   AttrBuilder B(C);
70509467b48Spatrick   B.addAttribute(Kind);
70609467b48Spatrick   return addAttributes(C, AttributeSet::get(C, B));
70709467b48Spatrick }
70809467b48Spatrick 
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const70909467b48Spatrick AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
71009467b48Spatrick                                         StringRef Value) const {
711*d415bd75Srobert   AttrBuilder B(C);
71209467b48Spatrick   B.addAttribute(Kind, Value);
71309467b48Spatrick   return addAttributes(C, AttributeSet::get(C, B));
71409467b48Spatrick }
71509467b48Spatrick 
addAttributes(LLVMContext & C,const AttributeSet AS) const71609467b48Spatrick AttributeSet AttributeSet::addAttributes(LLVMContext &C,
71709467b48Spatrick                                          const AttributeSet AS) const {
71809467b48Spatrick   if (!hasAttributes())
71909467b48Spatrick     return AS;
72009467b48Spatrick 
72109467b48Spatrick   if (!AS.hasAttributes())
72209467b48Spatrick     return *this;
72309467b48Spatrick 
724*d415bd75Srobert   AttrBuilder B(C, *this);
725*d415bd75Srobert   B.merge(AttrBuilder(C, AS));
72609467b48Spatrick   return get(C, B);
72709467b48Spatrick }
72809467b48Spatrick 
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const72909467b48Spatrick AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
73009467b48Spatrick                                              Attribute::AttrKind Kind) const {
73109467b48Spatrick   if (!hasAttribute(Kind)) return *this;
732*d415bd75Srobert   AttrBuilder B(C, *this);
73309467b48Spatrick   B.removeAttribute(Kind);
73409467b48Spatrick   return get(C, B);
73509467b48Spatrick }
73609467b48Spatrick 
removeAttribute(LLVMContext & C,StringRef Kind) const73709467b48Spatrick AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
73809467b48Spatrick                                              StringRef Kind) const {
73909467b48Spatrick   if (!hasAttribute(Kind)) return *this;
740*d415bd75Srobert   AttrBuilder B(C, *this);
74109467b48Spatrick   B.removeAttribute(Kind);
74209467b48Spatrick   return get(C, B);
74309467b48Spatrick }
74409467b48Spatrick 
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const74509467b48Spatrick AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
746*d415bd75Srobert                                             const AttributeMask &Attrs) const {
747*d415bd75Srobert   AttrBuilder B(C, *this);
74873471bf0Spatrick   // If there is nothing to remove, directly return the original set.
74973471bf0Spatrick   if (!B.overlaps(Attrs))
75073471bf0Spatrick     return *this;
75173471bf0Spatrick 
75209467b48Spatrick   B.remove(Attrs);
75309467b48Spatrick   return get(C, B);
75409467b48Spatrick }
75509467b48Spatrick 
getNumAttributes() const75609467b48Spatrick unsigned AttributeSet::getNumAttributes() const {
75709467b48Spatrick   return SetNode ? SetNode->getNumAttributes() : 0;
75809467b48Spatrick }
75909467b48Spatrick 
hasAttribute(Attribute::AttrKind Kind) const76009467b48Spatrick bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
76109467b48Spatrick   return SetNode ? SetNode->hasAttribute(Kind) : false;
76209467b48Spatrick }
76309467b48Spatrick 
hasAttribute(StringRef Kind) const76409467b48Spatrick bool AttributeSet::hasAttribute(StringRef Kind) const {
76509467b48Spatrick   return SetNode ? SetNode->hasAttribute(Kind) : false;
76609467b48Spatrick }
76709467b48Spatrick 
getAttribute(Attribute::AttrKind Kind) const76809467b48Spatrick Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
76909467b48Spatrick   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
77009467b48Spatrick }
77109467b48Spatrick 
getAttribute(StringRef Kind) const77209467b48Spatrick Attribute AttributeSet::getAttribute(StringRef Kind) const {
77309467b48Spatrick   return SetNode ? SetNode->getAttribute(Kind) : Attribute();
77409467b48Spatrick }
77509467b48Spatrick 
getAlignment() const77609467b48Spatrick MaybeAlign AttributeSet::getAlignment() const {
777*d415bd75Srobert   return SetNode ? SetNode->getAlignment() : std::nullopt;
77809467b48Spatrick }
77909467b48Spatrick 
getStackAlignment() const78009467b48Spatrick MaybeAlign AttributeSet::getStackAlignment() const {
781*d415bd75Srobert   return SetNode ? SetNode->getStackAlignment() : std::nullopt;
78209467b48Spatrick }
78309467b48Spatrick 
getDereferenceableBytes() const78409467b48Spatrick uint64_t AttributeSet::getDereferenceableBytes() const {
78509467b48Spatrick   return SetNode ? SetNode->getDereferenceableBytes() : 0;
78609467b48Spatrick }
78709467b48Spatrick 
getDereferenceableOrNullBytes() const78809467b48Spatrick uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
78909467b48Spatrick   return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
79009467b48Spatrick }
79109467b48Spatrick 
getByRefType() const79273471bf0Spatrick Type *AttributeSet::getByRefType() const {
79373471bf0Spatrick   return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
79473471bf0Spatrick }
79573471bf0Spatrick 
getByValType() const79609467b48Spatrick Type *AttributeSet::getByValType() const {
79773471bf0Spatrick   return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
79873471bf0Spatrick }
79973471bf0Spatrick 
getStructRetType() const80073471bf0Spatrick Type *AttributeSet::getStructRetType() const {
80173471bf0Spatrick   return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
80209467b48Spatrick }
80309467b48Spatrick 
getPreallocatedType() const804097a140dSpatrick Type *AttributeSet::getPreallocatedType() const {
80573471bf0Spatrick   return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
80673471bf0Spatrick }
80773471bf0Spatrick 
getInAllocaType() const80873471bf0Spatrick Type *AttributeSet::getInAllocaType() const {
80973471bf0Spatrick   return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
81073471bf0Spatrick }
81173471bf0Spatrick 
getElementType() const81273471bf0Spatrick Type *AttributeSet::getElementType() const {
81373471bf0Spatrick   return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
814097a140dSpatrick }
815097a140dSpatrick 
816*d415bd75Srobert std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const817*d415bd75Srobert AttributeSet::getAllocSizeArgs() const {
818*d415bd75Srobert   if (SetNode)
819*d415bd75Srobert     return SetNode->getAllocSizeArgs();
820*d415bd75Srobert   return std::nullopt;
82109467b48Spatrick }
82209467b48Spatrick 
getVScaleRangeMin() const823*d415bd75Srobert unsigned AttributeSet::getVScaleRangeMin() const {
824*d415bd75Srobert   return SetNode ? SetNode->getVScaleRangeMin() : 1;
825*d415bd75Srobert }
826*d415bd75Srobert 
getVScaleRangeMax() const827*d415bd75Srobert std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
828*d415bd75Srobert   return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
829*d415bd75Srobert }
830*d415bd75Srobert 
getUWTableKind() const831*d415bd75Srobert UWTableKind AttributeSet::getUWTableKind() const {
832*d415bd75Srobert   return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
833*d415bd75Srobert }
834*d415bd75Srobert 
getAllocKind() const835*d415bd75Srobert AllocFnKind AttributeSet::getAllocKind() const {
836*d415bd75Srobert   return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
837*d415bd75Srobert }
838*d415bd75Srobert 
getMemoryEffects() const839*d415bd75Srobert MemoryEffects AttributeSet::getMemoryEffects() const {
840*d415bd75Srobert   return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
84173471bf0Spatrick }
84273471bf0Spatrick 
getAsString(bool InAttrGrp) const84309467b48Spatrick std::string AttributeSet::getAsString(bool InAttrGrp) const {
84409467b48Spatrick   return SetNode ? SetNode->getAsString(InAttrGrp) : "";
84509467b48Spatrick }
84609467b48Spatrick 
hasParentContext(LLVMContext & C) const84773471bf0Spatrick bool AttributeSet::hasParentContext(LLVMContext &C) const {
84873471bf0Spatrick   assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
84973471bf0Spatrick   FoldingSetNodeID ID;
85073471bf0Spatrick   SetNode->Profile(ID);
85173471bf0Spatrick   void *Unused;
85273471bf0Spatrick   return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
85373471bf0Spatrick }
85473471bf0Spatrick 
begin() const85509467b48Spatrick AttributeSet::iterator AttributeSet::begin() const {
85609467b48Spatrick   return SetNode ? SetNode->begin() : nullptr;
85709467b48Spatrick }
85809467b48Spatrick 
end() const85909467b48Spatrick AttributeSet::iterator AttributeSet::end() const {
86009467b48Spatrick   return SetNode ? SetNode->end() : nullptr;
86109467b48Spatrick }
86209467b48Spatrick 
86309467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const86409467b48Spatrick LLVM_DUMP_METHOD void AttributeSet::dump() const {
86509467b48Spatrick   dbgs() << "AS =\n";
86609467b48Spatrick     dbgs() << "  { ";
86709467b48Spatrick     dbgs() << getAsString(true) << " }\n";
86809467b48Spatrick }
86909467b48Spatrick #endif
87009467b48Spatrick 
87109467b48Spatrick //===----------------------------------------------------------------------===//
87209467b48Spatrick // AttributeSetNode Definition
87309467b48Spatrick //===----------------------------------------------------------------------===//
87409467b48Spatrick 
AttributeSetNode(ArrayRef<Attribute> Attrs)87509467b48Spatrick AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
87609467b48Spatrick     : NumAttrs(Attrs.size()) {
87709467b48Spatrick   // There's memory after the node where we can store the entries in.
87809467b48Spatrick   llvm::copy(Attrs, getTrailingObjects<Attribute>());
87909467b48Spatrick 
88009467b48Spatrick   for (const auto &I : *this) {
881097a140dSpatrick     if (I.isStringAttribute())
882097a140dSpatrick       StringAttrs.insert({ I.getKindAsString(), I });
883097a140dSpatrick     else
884097a140dSpatrick       AvailableAttrs.addAttribute(I.getKindAsEnum());
88509467b48Spatrick   }
88609467b48Spatrick }
88709467b48Spatrick 
get(LLVMContext & C,ArrayRef<Attribute> Attrs)88809467b48Spatrick AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
88909467b48Spatrick                                         ArrayRef<Attribute> Attrs) {
890097a140dSpatrick   SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
891097a140dSpatrick   llvm::sort(SortedAttrs);
892097a140dSpatrick   return getSorted(C, SortedAttrs);
893097a140dSpatrick }
894097a140dSpatrick 
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)895097a140dSpatrick AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
896097a140dSpatrick                                               ArrayRef<Attribute> SortedAttrs) {
897097a140dSpatrick   if (SortedAttrs.empty())
89809467b48Spatrick     return nullptr;
89909467b48Spatrick 
900097a140dSpatrick   // Build a key to look up the existing attributes.
90109467b48Spatrick   LLVMContextImpl *pImpl = C.pImpl;
90209467b48Spatrick   FoldingSetNodeID ID;
90309467b48Spatrick 
904097a140dSpatrick   assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
90509467b48Spatrick   for (const auto &Attr : SortedAttrs)
90609467b48Spatrick     Attr.Profile(ID);
90709467b48Spatrick 
90809467b48Spatrick   void *InsertPoint;
90909467b48Spatrick   AttributeSetNode *PA =
91009467b48Spatrick     pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
91109467b48Spatrick 
91209467b48Spatrick   // If we didn't find any existing attributes of the same shape then create a
91309467b48Spatrick   // new one and insert it.
91409467b48Spatrick   if (!PA) {
91509467b48Spatrick     // Coallocate entries after the AttributeSetNode itself.
91609467b48Spatrick     void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
91709467b48Spatrick     PA = new (Mem) AttributeSetNode(SortedAttrs);
91809467b48Spatrick     pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
91909467b48Spatrick   }
92009467b48Spatrick 
92109467b48Spatrick   // Return the AttributeSetNode that we found or created.
92209467b48Spatrick   return PA;
92309467b48Spatrick }
92409467b48Spatrick 
get(LLVMContext & C,const AttrBuilder & B)92509467b48Spatrick AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
926*d415bd75Srobert   return getSorted(C, B.attrs());
92709467b48Spatrick }
92809467b48Spatrick 
hasAttribute(StringRef Kind) const92909467b48Spatrick bool AttributeSetNode::hasAttribute(StringRef Kind) const {
930097a140dSpatrick   return StringAttrs.count(Kind);
931097a140dSpatrick }
932097a140dSpatrick 
933*d415bd75Srobert std::optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const934097a140dSpatrick AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
935097a140dSpatrick   // Do a quick presence check.
936097a140dSpatrick   if (!hasAttribute(Kind))
937*d415bd75Srobert     return std::nullopt;
938097a140dSpatrick 
939097a140dSpatrick   // Attributes in a set are sorted by enum value, followed by string
940097a140dSpatrick   // attributes. Binary search the one we want.
941097a140dSpatrick   const Attribute *I =
942097a140dSpatrick       std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
943097a140dSpatrick                        [](Attribute A, Attribute::AttrKind Kind) {
944097a140dSpatrick                          return A.getKindAsEnum() < Kind;
945097a140dSpatrick                        });
946097a140dSpatrick   assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
947097a140dSpatrick   return *I;
94809467b48Spatrick }
94909467b48Spatrick 
getAttribute(Attribute::AttrKind Kind) const95009467b48Spatrick Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
951097a140dSpatrick   if (auto A = findEnumAttribute(Kind))
952097a140dSpatrick     return *A;
95309467b48Spatrick   return {};
95409467b48Spatrick }
95509467b48Spatrick 
getAttribute(StringRef Kind) const95609467b48Spatrick Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
957097a140dSpatrick   return StringAttrs.lookup(Kind);
95809467b48Spatrick }
95909467b48Spatrick 
getAlignment() const96009467b48Spatrick MaybeAlign AttributeSetNode::getAlignment() const {
961097a140dSpatrick   if (auto A = findEnumAttribute(Attribute::Alignment))
962097a140dSpatrick     return A->getAlignment();
963*d415bd75Srobert   return std::nullopt;
96409467b48Spatrick }
96509467b48Spatrick 
getStackAlignment() const96609467b48Spatrick MaybeAlign AttributeSetNode::getStackAlignment() const {
967097a140dSpatrick   if (auto A = findEnumAttribute(Attribute::StackAlignment))
968097a140dSpatrick     return A->getStackAlignment();
969*d415bd75Srobert   return std::nullopt;
97009467b48Spatrick }
97109467b48Spatrick 
getAttributeType(Attribute::AttrKind Kind) const97273471bf0Spatrick Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
97373471bf0Spatrick   if (auto A = findEnumAttribute(Kind))
974097a140dSpatrick     return A->getValueAsType();
97573471bf0Spatrick   return nullptr;
97609467b48Spatrick }
97709467b48Spatrick 
getDereferenceableBytes() const97809467b48Spatrick uint64_t AttributeSetNode::getDereferenceableBytes() const {
979097a140dSpatrick   if (auto A = findEnumAttribute(Attribute::Dereferenceable))
980097a140dSpatrick     return A->getDereferenceableBytes();
98109467b48Spatrick   return 0;
98209467b48Spatrick }
98309467b48Spatrick 
getDereferenceableOrNullBytes() const98409467b48Spatrick uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
985097a140dSpatrick   if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
986097a140dSpatrick     return A->getDereferenceableOrNullBytes();
98709467b48Spatrick   return 0;
98809467b48Spatrick }
98909467b48Spatrick 
990*d415bd75Srobert std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const99109467b48Spatrick AttributeSetNode::getAllocSizeArgs() const {
992097a140dSpatrick   if (auto A = findEnumAttribute(Attribute::AllocSize))
993097a140dSpatrick     return A->getAllocSizeArgs();
994*d415bd75Srobert   return std::nullopt;
99509467b48Spatrick }
99609467b48Spatrick 
getVScaleRangeMin() const997*d415bd75Srobert unsigned AttributeSetNode::getVScaleRangeMin() const {
99873471bf0Spatrick   if (auto A = findEnumAttribute(Attribute::VScaleRange))
999*d415bd75Srobert     return A->getVScaleRangeMin();
1000*d415bd75Srobert   return 1;
1001*d415bd75Srobert }
1002*d415bd75Srobert 
getVScaleRangeMax() const1003*d415bd75Srobert std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1004*d415bd75Srobert   if (auto A = findEnumAttribute(Attribute::VScaleRange))
1005*d415bd75Srobert     return A->getVScaleRangeMax();
1006*d415bd75Srobert   return std::nullopt;
1007*d415bd75Srobert }
1008*d415bd75Srobert 
getUWTableKind() const1009*d415bd75Srobert UWTableKind AttributeSetNode::getUWTableKind() const {
1010*d415bd75Srobert   if (auto A = findEnumAttribute(Attribute::UWTable))
1011*d415bd75Srobert     return A->getUWTableKind();
1012*d415bd75Srobert   return UWTableKind::None;
1013*d415bd75Srobert }
1014*d415bd75Srobert 
getAllocKind() const1015*d415bd75Srobert AllocFnKind AttributeSetNode::getAllocKind() const {
1016*d415bd75Srobert   if (auto A = findEnumAttribute(Attribute::AllocKind))
1017*d415bd75Srobert     return A->getAllocKind();
1018*d415bd75Srobert   return AllocFnKind::Unknown;
1019*d415bd75Srobert }
1020*d415bd75Srobert 
getMemoryEffects() const1021*d415bd75Srobert MemoryEffects AttributeSetNode::getMemoryEffects() const {
1022*d415bd75Srobert   if (auto A = findEnumAttribute(Attribute::Memory))
1023*d415bd75Srobert     return A->getMemoryEffects();
1024*d415bd75Srobert   return MemoryEffects::unknown();
102573471bf0Spatrick }
102673471bf0Spatrick 
getAsString(bool InAttrGrp) const102709467b48Spatrick std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
102809467b48Spatrick   std::string Str;
102909467b48Spatrick   for (iterator I = begin(), E = end(); I != E; ++I) {
103009467b48Spatrick     if (I != begin())
103109467b48Spatrick       Str += ' ';
103209467b48Spatrick     Str += I->getAsString(InAttrGrp);
103309467b48Spatrick   }
103409467b48Spatrick   return Str;
103509467b48Spatrick }
103609467b48Spatrick 
103709467b48Spatrick //===----------------------------------------------------------------------===//
103809467b48Spatrick // AttributeListImpl Definition
103909467b48Spatrick //===----------------------------------------------------------------------===//
104009467b48Spatrick 
104109467b48Spatrick /// Map from AttributeList index to the internal array index. Adding one happens
1042097a140dSpatrick /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)104373471bf0Spatrick static unsigned attrIdxToArrayIdx(unsigned Index) {
1044097a140dSpatrick   return Index + 1;
104509467b48Spatrick }
104609467b48Spatrick 
AttributeListImpl(ArrayRef<AttributeSet> Sets)1047097a140dSpatrick AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
1048097a140dSpatrick     : NumAttrSets(Sets.size()) {
104909467b48Spatrick   assert(!Sets.empty() && "pointless AttributeListImpl");
105009467b48Spatrick 
105109467b48Spatrick   // There's memory after the node where we can store the entries in.
105209467b48Spatrick   llvm::copy(Sets, getTrailingObjects<AttributeSet>());
105309467b48Spatrick 
1054097a140dSpatrick   // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1055097a140dSpatrick   // summary bitsets.
105673471bf0Spatrick   for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1057097a140dSpatrick     if (!I.isStringAttribute())
1058097a140dSpatrick       AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1059097a140dSpatrick 
1060097a140dSpatrick   for (const auto &Set : Sets)
1061097a140dSpatrick     for (const auto &I : Set)
1062097a140dSpatrick       if (!I.isStringAttribute())
1063097a140dSpatrick         AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
106409467b48Spatrick }
106509467b48Spatrick 
Profile(FoldingSetNodeID & ID) const106609467b48Spatrick void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
1067*d415bd75Srobert   Profile(ID, ArrayRef(begin(), end()));
106809467b48Spatrick }
106909467b48Spatrick 
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)107009467b48Spatrick void AttributeListImpl::Profile(FoldingSetNodeID &ID,
107109467b48Spatrick                                 ArrayRef<AttributeSet> Sets) {
107209467b48Spatrick   for (const auto &Set : Sets)
107309467b48Spatrick     ID.AddPointer(Set.SetNode);
107409467b48Spatrick }
107509467b48Spatrick 
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const1076097a140dSpatrick bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
1077097a140dSpatrick                                         unsigned *Index) const {
1078097a140dSpatrick   if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1079097a140dSpatrick     return false;
1080097a140dSpatrick 
1081097a140dSpatrick   if (Index) {
1082097a140dSpatrick     for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1083097a140dSpatrick       if (begin()[I].hasAttribute(Kind)) {
1084097a140dSpatrick         *Index = I - 1;
1085097a140dSpatrick         break;
1086097a140dSpatrick       }
1087097a140dSpatrick     }
1088097a140dSpatrick   }
1089097a140dSpatrick 
1090097a140dSpatrick   return true;
1091097a140dSpatrick }
1092097a140dSpatrick 
1093097a140dSpatrick 
109409467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const109509467b48Spatrick LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
109609467b48Spatrick   AttributeList(const_cast<AttributeListImpl *>(this)).dump();
109709467b48Spatrick }
109809467b48Spatrick #endif
109909467b48Spatrick 
110009467b48Spatrick //===----------------------------------------------------------------------===//
110109467b48Spatrick // AttributeList Construction and Mutation Methods
110209467b48Spatrick //===----------------------------------------------------------------------===//
110309467b48Spatrick 
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)110409467b48Spatrick AttributeList AttributeList::getImpl(LLVMContext &C,
110509467b48Spatrick                                      ArrayRef<AttributeSet> AttrSets) {
110609467b48Spatrick   assert(!AttrSets.empty() && "pointless AttributeListImpl");
110709467b48Spatrick 
110809467b48Spatrick   LLVMContextImpl *pImpl = C.pImpl;
110909467b48Spatrick   FoldingSetNodeID ID;
111009467b48Spatrick   AttributeListImpl::Profile(ID, AttrSets);
111109467b48Spatrick 
111209467b48Spatrick   void *InsertPoint;
111309467b48Spatrick   AttributeListImpl *PA =
111409467b48Spatrick       pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
111509467b48Spatrick 
111609467b48Spatrick   // If we didn't find any existing attributes of the same shape then
111709467b48Spatrick   // create a new one and insert it.
111809467b48Spatrick   if (!PA) {
111909467b48Spatrick     // Coallocate entries after the AttributeListImpl itself.
1120097a140dSpatrick     void *Mem = pImpl->Alloc.Allocate(
1121097a140dSpatrick         AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1122097a140dSpatrick         alignof(AttributeListImpl));
1123097a140dSpatrick     PA = new (Mem) AttributeListImpl(AttrSets);
112409467b48Spatrick     pImpl->AttrsLists.InsertNode(PA, InsertPoint);
112509467b48Spatrick   }
112609467b48Spatrick 
112709467b48Spatrick   // Return the AttributesList that we found or created.
112809467b48Spatrick   return AttributeList(PA);
112909467b48Spatrick }
113009467b48Spatrick 
113109467b48Spatrick AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)113209467b48Spatrick AttributeList::get(LLVMContext &C,
113309467b48Spatrick                    ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
113409467b48Spatrick   // If there are no attributes then return a null AttributesList pointer.
113509467b48Spatrick   if (Attrs.empty())
113609467b48Spatrick     return {};
113709467b48Spatrick 
1138*d415bd75Srobert   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
1139097a140dSpatrick          "Misordered Attributes list!");
114073471bf0Spatrick   assert(llvm::all_of(Attrs,
114109467b48Spatrick                       [](const std::pair<unsigned, Attribute> &Pair) {
114273471bf0Spatrick                         return Pair.second.isValid();
114309467b48Spatrick                       }) &&
114409467b48Spatrick          "Pointless attribute!");
114509467b48Spatrick 
114609467b48Spatrick   // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
114709467b48Spatrick   // list.
114809467b48Spatrick   SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
114909467b48Spatrick   for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
115009467b48Spatrick          E = Attrs.end(); I != E; ) {
115109467b48Spatrick     unsigned Index = I->first;
115209467b48Spatrick     SmallVector<Attribute, 4> AttrVec;
115309467b48Spatrick     while (I != E && I->first == Index) {
115409467b48Spatrick       AttrVec.push_back(I->second);
115509467b48Spatrick       ++I;
115609467b48Spatrick     }
115709467b48Spatrick 
115809467b48Spatrick     AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
115909467b48Spatrick   }
116009467b48Spatrick 
116109467b48Spatrick   return get(C, AttrPairVec);
116209467b48Spatrick }
116309467b48Spatrick 
116409467b48Spatrick AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)116509467b48Spatrick AttributeList::get(LLVMContext &C,
116609467b48Spatrick                    ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
116709467b48Spatrick   // If there are no attributes then return a null AttributesList pointer.
116809467b48Spatrick   if (Attrs.empty())
116909467b48Spatrick     return {};
117009467b48Spatrick 
1171*d415bd75Srobert   assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
117209467b48Spatrick          "Misordered Attributes list!");
117309467b48Spatrick   assert(llvm::none_of(Attrs,
117409467b48Spatrick                        [](const std::pair<unsigned, AttributeSet> &Pair) {
117509467b48Spatrick                          return !Pair.second.hasAttributes();
117609467b48Spatrick                        }) &&
117709467b48Spatrick          "Pointless attribute!");
117809467b48Spatrick 
117909467b48Spatrick   unsigned MaxIndex = Attrs.back().first;
118009467b48Spatrick   // If the MaxIndex is FunctionIndex and there are other indices in front
118109467b48Spatrick   // of it, we need to use the largest of those to get the right size.
118209467b48Spatrick   if (MaxIndex == FunctionIndex && Attrs.size() > 1)
118309467b48Spatrick     MaxIndex = Attrs[Attrs.size() - 2].first;
118409467b48Spatrick 
118509467b48Spatrick   SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
118609467b48Spatrick   for (const auto &Pair : Attrs)
118709467b48Spatrick     AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
118809467b48Spatrick 
118909467b48Spatrick   return getImpl(C, AttrVec);
119009467b48Spatrick }
119109467b48Spatrick 
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)119209467b48Spatrick AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
119309467b48Spatrick                                  AttributeSet RetAttrs,
119409467b48Spatrick                                  ArrayRef<AttributeSet> ArgAttrs) {
119509467b48Spatrick   // Scan from the end to find the last argument with attributes.  Most
119609467b48Spatrick   // arguments don't have attributes, so it's nice if we can have fewer unique
119709467b48Spatrick   // AttributeListImpls by dropping empty attribute sets at the end of the list.
119809467b48Spatrick   unsigned NumSets = 0;
119909467b48Spatrick   for (size_t I = ArgAttrs.size(); I != 0; --I) {
120009467b48Spatrick     if (ArgAttrs[I - 1].hasAttributes()) {
120109467b48Spatrick       NumSets = I + 2;
120209467b48Spatrick       break;
120309467b48Spatrick     }
120409467b48Spatrick   }
120509467b48Spatrick   if (NumSets == 0) {
120609467b48Spatrick     // Check function and return attributes if we didn't have argument
120709467b48Spatrick     // attributes.
120809467b48Spatrick     if (RetAttrs.hasAttributes())
120909467b48Spatrick       NumSets = 2;
121009467b48Spatrick     else if (FnAttrs.hasAttributes())
121109467b48Spatrick       NumSets = 1;
121209467b48Spatrick   }
121309467b48Spatrick 
121409467b48Spatrick   // If all attribute sets were empty, we can use the empty attribute list.
121509467b48Spatrick   if (NumSets == 0)
121609467b48Spatrick     return {};
121709467b48Spatrick 
121809467b48Spatrick   SmallVector<AttributeSet, 8> AttrSets;
121909467b48Spatrick   AttrSets.reserve(NumSets);
122009467b48Spatrick   // If we have any attributes, we always have function attributes.
122109467b48Spatrick   AttrSets.push_back(FnAttrs);
122209467b48Spatrick   if (NumSets > 1)
122309467b48Spatrick     AttrSets.push_back(RetAttrs);
122409467b48Spatrick   if (NumSets > 2) {
122509467b48Spatrick     // Drop the empty argument attribute sets at the end.
122609467b48Spatrick     ArgAttrs = ArgAttrs.take_front(NumSets - 2);
122773471bf0Spatrick     llvm::append_range(AttrSets, ArgAttrs);
122809467b48Spatrick   }
122909467b48Spatrick 
123009467b48Spatrick   return getImpl(C, AttrSets);
123109467b48Spatrick }
123209467b48Spatrick 
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)123309467b48Spatrick AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1234*d415bd75Srobert                                  AttributeSet Attrs) {
1235*d415bd75Srobert   if (!Attrs.hasAttributes())
123609467b48Spatrick     return {};
123709467b48Spatrick   Index = attrIdxToArrayIdx(Index);
123809467b48Spatrick   SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1239*d415bd75Srobert   AttrSets[Index] = Attrs;
124009467b48Spatrick   return getImpl(C, AttrSets);
124109467b48Spatrick }
124209467b48Spatrick 
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)124309467b48Spatrick AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1244*d415bd75Srobert                                  const AttrBuilder &B) {
1245*d415bd75Srobert   return get(C, Index, AttributeSet::get(C, B));
1246*d415bd75Srobert }
1247*d415bd75Srobert 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)1248*d415bd75Srobert AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
124909467b48Spatrick                                  ArrayRef<Attribute::AttrKind> Kinds) {
125009467b48Spatrick   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
125109467b48Spatrick   for (const auto K : Kinds)
125209467b48Spatrick     Attrs.emplace_back(Index, Attribute::get(C, K));
125309467b48Spatrick   return get(C, Attrs);
125409467b48Spatrick }
125509467b48Spatrick 
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)125609467b48Spatrick AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1257097a140dSpatrick                                  ArrayRef<Attribute::AttrKind> Kinds,
1258097a140dSpatrick                                  ArrayRef<uint64_t> Values) {
1259097a140dSpatrick   assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1260097a140dSpatrick   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1261097a140dSpatrick   auto VI = Values.begin();
1262097a140dSpatrick   for (const auto K : Kinds)
1263097a140dSpatrick     Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1264097a140dSpatrick   return get(C, Attrs);
1265097a140dSpatrick }
1266097a140dSpatrick 
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1267097a140dSpatrick AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
126809467b48Spatrick                                  ArrayRef<StringRef> Kinds) {
126909467b48Spatrick   SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
127009467b48Spatrick   for (const auto &K : Kinds)
127109467b48Spatrick     Attrs.emplace_back(Index, Attribute::get(C, K));
127209467b48Spatrick   return get(C, Attrs);
127309467b48Spatrick }
127409467b48Spatrick 
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)127509467b48Spatrick AttributeList AttributeList::get(LLVMContext &C,
127609467b48Spatrick                                  ArrayRef<AttributeList> Attrs) {
127709467b48Spatrick   if (Attrs.empty())
127809467b48Spatrick     return {};
127909467b48Spatrick   if (Attrs.size() == 1)
128009467b48Spatrick     return Attrs[0];
128109467b48Spatrick 
128209467b48Spatrick   unsigned MaxSize = 0;
128309467b48Spatrick   for (const auto &List : Attrs)
128409467b48Spatrick     MaxSize = std::max(MaxSize, List.getNumAttrSets());
128509467b48Spatrick 
128609467b48Spatrick   // If every list was empty, there is no point in merging the lists.
128709467b48Spatrick   if (MaxSize == 0)
128809467b48Spatrick     return {};
128909467b48Spatrick 
129009467b48Spatrick   SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
129109467b48Spatrick   for (unsigned I = 0; I < MaxSize; ++I) {
1292*d415bd75Srobert     AttrBuilder CurBuilder(C);
129309467b48Spatrick     for (const auto &List : Attrs)
1294*d415bd75Srobert       CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
129509467b48Spatrick     NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
129609467b48Spatrick   }
129709467b48Spatrick 
129809467b48Spatrick   return getImpl(C, NewAttrSets);
129909467b48Spatrick }
130009467b48Spatrick 
1301*d415bd75Srobert AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1302*d415bd75Srobert AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
130309467b48Spatrick                                    Attribute::AttrKind Kind) const {
130473471bf0Spatrick   AttributeSet Attrs = getAttributes(Index);
1305*d415bd75Srobert   if (Attrs.hasAttribute(Kind))
1306*d415bd75Srobert     return *this;
130773471bf0Spatrick   // TODO: Insert at correct position and avoid sort.
130873471bf0Spatrick   SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
130973471bf0Spatrick   NewAttrs.push_back(Attribute::get(C, Kind));
1310*d415bd75Srobert   return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
131109467b48Spatrick }
131209467b48Spatrick 
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1313*d415bd75Srobert AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
131409467b48Spatrick                                                  StringRef Kind,
131509467b48Spatrick                                                  StringRef Value) const {
1316*d415bd75Srobert   AttrBuilder B(C);
131709467b48Spatrick   B.addAttribute(Kind, Value);
1318*d415bd75Srobert   return addAttributesAtIndex(C, Index, B);
131909467b48Spatrick }
132009467b48Spatrick 
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1321*d415bd75Srobert AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
132209467b48Spatrick                                                  Attribute A) const {
1323*d415bd75Srobert   AttrBuilder B(C);
132409467b48Spatrick   B.addAttribute(A);
1325*d415bd75Srobert   return addAttributesAtIndex(C, Index, B);
132609467b48Spatrick }
132709467b48Spatrick 
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1328*d415bd75Srobert AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1329*d415bd75Srobert                                                   unsigned Index,
133073471bf0Spatrick                                                   AttributeSet Attrs) const {
133173471bf0Spatrick   Index = attrIdxToArrayIdx(Index);
133273471bf0Spatrick   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
133373471bf0Spatrick   if (Index >= AttrSets.size())
133473471bf0Spatrick     AttrSets.resize(Index + 1);
133573471bf0Spatrick   AttrSets[Index] = Attrs;
1336*d415bd75Srobert 
1337*d415bd75Srobert   // Remove trailing empty attribute sets.
1338*d415bd75Srobert   while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1339*d415bd75Srobert     AttrSets.pop_back();
1340*d415bd75Srobert   if (AttrSets.empty())
1341*d415bd75Srobert     return {};
134273471bf0Spatrick   return AttributeList::getImpl(C, AttrSets);
134373471bf0Spatrick }
134473471bf0Spatrick 
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1345*d415bd75Srobert AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1346*d415bd75Srobert                                                   unsigned Index,
134709467b48Spatrick                                                   const AttrBuilder &B) const {
134809467b48Spatrick   if (!B.hasAttributes())
134909467b48Spatrick     return *this;
135009467b48Spatrick 
135109467b48Spatrick   if (!pImpl)
135209467b48Spatrick     return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
135309467b48Spatrick 
1354*d415bd75Srobert   AttrBuilder Merged(C, getAttributes(Index));
135509467b48Spatrick   Merged.merge(B);
1356*d415bd75Srobert   return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
135709467b48Spatrick }
135809467b48Spatrick 
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const135909467b48Spatrick AttributeList AttributeList::addParamAttribute(LLVMContext &C,
136009467b48Spatrick                                                ArrayRef<unsigned> ArgNos,
136109467b48Spatrick                                                Attribute A) const {
1362097a140dSpatrick   assert(llvm::is_sorted(ArgNos));
136309467b48Spatrick 
136409467b48Spatrick   SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
136509467b48Spatrick   unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
136609467b48Spatrick   if (MaxIndex >= AttrSets.size())
136709467b48Spatrick     AttrSets.resize(MaxIndex + 1);
136809467b48Spatrick 
136909467b48Spatrick   for (unsigned ArgNo : ArgNos) {
137009467b48Spatrick     unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1371*d415bd75Srobert     AttrBuilder B(C, AttrSets[Index]);
137209467b48Spatrick     B.addAttribute(A);
137309467b48Spatrick     AttrSets[Index] = AttributeSet::get(C, B);
137409467b48Spatrick   }
137509467b48Spatrick 
137609467b48Spatrick   return getImpl(C, AttrSets);
137709467b48Spatrick }
137809467b48Spatrick 
137909467b48Spatrick AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1380*d415bd75Srobert AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1381*d415bd75Srobert                                       Attribute::AttrKind Kind) const {
1382*d415bd75Srobert   AttributeSet Attrs = getAttributes(Index);
1383*d415bd75Srobert   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1384*d415bd75Srobert   if (Attrs == NewAttrs)
1385*d415bd75Srobert     return *this;
1386*d415bd75Srobert   return setAttributesAtIndex(C, Index, NewAttrs);
1387*d415bd75Srobert }
1388*d415bd75Srobert 
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1389*d415bd75Srobert AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1390*d415bd75Srobert                                                     unsigned Index,
1391*d415bd75Srobert                                                     StringRef Kind) const {
1392*d415bd75Srobert   AttributeSet Attrs = getAttributes(Index);
1393*d415bd75Srobert   AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1394*d415bd75Srobert   if (Attrs == NewAttrs)
1395*d415bd75Srobert     return *this;
1396*d415bd75Srobert   return setAttributesAtIndex(C, Index, NewAttrs);
1397*d415bd75Srobert }
1398*d415bd75Srobert 
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const1399*d415bd75Srobert AttributeList AttributeList::removeAttributesAtIndex(
1400*d415bd75Srobert     LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
140173471bf0Spatrick   AttributeSet Attrs = getAttributes(Index);
140273471bf0Spatrick   AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
140373471bf0Spatrick   // If nothing was removed, return the original list.
140473471bf0Spatrick   if (Attrs == NewAttrs)
140573471bf0Spatrick     return *this;
1406*d415bd75Srobert   return setAttributesAtIndex(C, Index, NewAttrs);
140709467b48Spatrick }
140809467b48Spatrick 
1409*d415bd75Srobert AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1410*d415bd75Srobert AttributeList::removeAttributesAtIndex(LLVMContext &C,
141109467b48Spatrick                                        unsigned WithoutIndex) const {
141209467b48Spatrick   if (!pImpl)
141309467b48Spatrick     return {};
1414*d415bd75Srobert   if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
141509467b48Spatrick     return *this;
1416*d415bd75Srobert   return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
141709467b48Spatrick }
141809467b48Spatrick 
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const1419*d415bd75Srobert AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1420*d415bd75Srobert                                                        uint64_t Bytes) const {
1421*d415bd75Srobert   AttrBuilder B(C);
1422*d415bd75Srobert   B.addDereferenceableAttr(Bytes);
1423*d415bd75Srobert   return addRetAttributes(C, B);
1424*d415bd75Srobert }
1425*d415bd75Srobert 
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1426*d415bd75Srobert AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
142709467b48Spatrick                                                          unsigned Index,
142809467b48Spatrick                                                          uint64_t Bytes) const {
1429*d415bd75Srobert   AttrBuilder B(C);
143009467b48Spatrick   B.addDereferenceableAttr(Bytes);
1431*d415bd75Srobert   return addParamAttributes(C, Index, B);
143209467b48Spatrick }
143309467b48Spatrick 
143409467b48Spatrick AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1435*d415bd75Srobert AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
143609467b48Spatrick                                                  uint64_t Bytes) const {
1437*d415bd75Srobert   AttrBuilder B(C);
143809467b48Spatrick   B.addDereferenceableOrNullAttr(Bytes);
1439*d415bd75Srobert   return addParamAttributes(C, Index, B);
144009467b48Spatrick }
144109467b48Spatrick 
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const std::optional<unsigned> & NumElemsArg)1442*d415bd75Srobert AttributeList AttributeList::addAllocSizeParamAttr(
1443*d415bd75Srobert     LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1444*d415bd75Srobert     const std::optional<unsigned> &NumElemsArg) {
1445*d415bd75Srobert   AttrBuilder B(C);
144609467b48Spatrick   B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1447*d415bd75Srobert   return addParamAttributes(C, Index, B);
144873471bf0Spatrick }
144973471bf0Spatrick 
145009467b48Spatrick //===----------------------------------------------------------------------===//
145109467b48Spatrick // AttributeList Accessor Methods
145209467b48Spatrick //===----------------------------------------------------------------------===//
145309467b48Spatrick 
getParamAttrs(unsigned ArgNo) const1454*d415bd75Srobert AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
145509467b48Spatrick   return getAttributes(ArgNo + FirstArgIndex);
145609467b48Spatrick }
145709467b48Spatrick 
getRetAttrs() const1458*d415bd75Srobert AttributeSet AttributeList::getRetAttrs() const {
145909467b48Spatrick   return getAttributes(ReturnIndex);
146009467b48Spatrick }
146109467b48Spatrick 
getFnAttrs() const1462*d415bd75Srobert AttributeSet AttributeList::getFnAttrs() const {
146309467b48Spatrick   return getAttributes(FunctionIndex);
146409467b48Spatrick }
146509467b48Spatrick 
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1466*d415bd75Srobert bool AttributeList::hasAttributeAtIndex(unsigned Index,
146709467b48Spatrick                                         Attribute::AttrKind Kind) const {
146809467b48Spatrick   return getAttributes(Index).hasAttribute(Kind);
146909467b48Spatrick }
147009467b48Spatrick 
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1471*d415bd75Srobert bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
147209467b48Spatrick   return getAttributes(Index).hasAttribute(Kind);
147309467b48Spatrick }
147409467b48Spatrick 
hasAttributesAtIndex(unsigned Index) const1475*d415bd75Srobert bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
147609467b48Spatrick   return getAttributes(Index).hasAttributes();
147709467b48Spatrick }
147809467b48Spatrick 
hasFnAttr(Attribute::AttrKind Kind) const1479*d415bd75Srobert bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
148009467b48Spatrick   return pImpl && pImpl->hasFnAttribute(Kind);
148109467b48Spatrick }
148209467b48Spatrick 
hasFnAttr(StringRef Kind) const1483*d415bd75Srobert bool AttributeList::hasFnAttr(StringRef Kind) const {
1484*d415bd75Srobert   return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
148509467b48Spatrick }
148609467b48Spatrick 
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const148709467b48Spatrick bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
148809467b48Spatrick                                      unsigned *Index) const {
1489097a140dSpatrick   return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
149009467b48Spatrick }
149109467b48Spatrick 
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1492*d415bd75Srobert Attribute AttributeList::getAttributeAtIndex(unsigned Index,
149309467b48Spatrick                                              Attribute::AttrKind Kind) const {
149409467b48Spatrick   return getAttributes(Index).getAttribute(Kind);
149509467b48Spatrick }
149609467b48Spatrick 
getAttributeAtIndex(unsigned Index,StringRef Kind) const1497*d415bd75Srobert Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1498*d415bd75Srobert                                              StringRef Kind) const {
149909467b48Spatrick   return getAttributes(Index).getAttribute(Kind);
150009467b48Spatrick }
150109467b48Spatrick 
getRetAlignment() const150209467b48Spatrick MaybeAlign AttributeList::getRetAlignment() const {
150309467b48Spatrick   return getAttributes(ReturnIndex).getAlignment();
150409467b48Spatrick }
150509467b48Spatrick 
getParamAlignment(unsigned ArgNo) const150609467b48Spatrick MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
150709467b48Spatrick   return getAttributes(ArgNo + FirstArgIndex).getAlignment();
150809467b48Spatrick }
150909467b48Spatrick 
getParamStackAlignment(unsigned ArgNo) const151073471bf0Spatrick MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
151173471bf0Spatrick   return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
151273471bf0Spatrick }
151373471bf0Spatrick 
getParamByValType(unsigned Index) const151409467b48Spatrick Type *AttributeList::getParamByValType(unsigned Index) const {
151509467b48Spatrick   return getAttributes(Index+FirstArgIndex).getByValType();
151609467b48Spatrick }
151709467b48Spatrick 
getParamStructRetType(unsigned Index) const151873471bf0Spatrick Type *AttributeList::getParamStructRetType(unsigned Index) const {
151973471bf0Spatrick   return getAttributes(Index + FirstArgIndex).getStructRetType();
152073471bf0Spatrick }
152173471bf0Spatrick 
getParamByRefType(unsigned Index) const152273471bf0Spatrick Type *AttributeList::getParamByRefType(unsigned Index) const {
152373471bf0Spatrick   return getAttributes(Index + FirstArgIndex).getByRefType();
152473471bf0Spatrick }
152573471bf0Spatrick 
getParamPreallocatedType(unsigned Index) const1526097a140dSpatrick Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1527097a140dSpatrick   return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1528097a140dSpatrick }
1529097a140dSpatrick 
getParamInAllocaType(unsigned Index) const153073471bf0Spatrick Type *AttributeList::getParamInAllocaType(unsigned Index) const {
153173471bf0Spatrick   return getAttributes(Index + FirstArgIndex).getInAllocaType();
153273471bf0Spatrick }
153373471bf0Spatrick 
getParamElementType(unsigned Index) const153473471bf0Spatrick Type *AttributeList::getParamElementType(unsigned Index) const {
153573471bf0Spatrick   return getAttributes(Index + FirstArgIndex).getElementType();
153673471bf0Spatrick }
153773471bf0Spatrick 
getFnStackAlignment() const1538*d415bd75Srobert MaybeAlign AttributeList::getFnStackAlignment() const {
1539*d415bd75Srobert   return getFnAttrs().getStackAlignment();
154009467b48Spatrick }
154109467b48Spatrick 
getRetStackAlignment() const1542*d415bd75Srobert MaybeAlign AttributeList::getRetStackAlignment() const {
1543*d415bd75Srobert   return getRetAttrs().getStackAlignment();
154409467b48Spatrick }
154509467b48Spatrick 
getRetDereferenceableBytes() const1546*d415bd75Srobert uint64_t AttributeList::getRetDereferenceableBytes() const {
1547*d415bd75Srobert   return getRetAttrs().getDereferenceableBytes();
154809467b48Spatrick }
154909467b48Spatrick 
getParamDereferenceableBytes(unsigned Index) const1550*d415bd75Srobert uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
1551*d415bd75Srobert   return getParamAttrs(Index).getDereferenceableBytes();
155209467b48Spatrick }
155309467b48Spatrick 
getRetDereferenceableOrNullBytes() const1554*d415bd75Srobert uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
1555*d415bd75Srobert   return getRetAttrs().getDereferenceableOrNullBytes();
1556*d415bd75Srobert }
1557*d415bd75Srobert 
1558*d415bd75Srobert uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const1559*d415bd75Srobert AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
1560*d415bd75Srobert   return getParamAttrs(Index).getDereferenceableOrNullBytes();
1561*d415bd75Srobert }
1562*d415bd75Srobert 
getUWTableKind() const1563*d415bd75Srobert UWTableKind AttributeList::getUWTableKind() const {
1564*d415bd75Srobert   return getFnAttrs().getUWTableKind();
1565*d415bd75Srobert }
1566*d415bd75Srobert 
getAllocKind() const1567*d415bd75Srobert AllocFnKind AttributeList::getAllocKind() const {
1568*d415bd75Srobert   return getFnAttrs().getAllocKind();
1569*d415bd75Srobert }
1570*d415bd75Srobert 
getMemoryEffects() const1571*d415bd75Srobert MemoryEffects AttributeList::getMemoryEffects() const {
1572*d415bd75Srobert   return getFnAttrs().getMemoryEffects();
157373471bf0Spatrick }
157473471bf0Spatrick 
getAsString(unsigned Index,bool InAttrGrp) const157509467b48Spatrick std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
157609467b48Spatrick   return getAttributes(Index).getAsString(InAttrGrp);
157709467b48Spatrick }
157809467b48Spatrick 
getAttributes(unsigned Index) const157909467b48Spatrick AttributeSet AttributeList::getAttributes(unsigned Index) const {
158009467b48Spatrick   Index = attrIdxToArrayIdx(Index);
158109467b48Spatrick   if (!pImpl || Index >= getNumAttrSets())
158209467b48Spatrick     return {};
158309467b48Spatrick   return pImpl->begin()[Index];
158409467b48Spatrick }
158509467b48Spatrick 
hasParentContext(LLVMContext & C) const158673471bf0Spatrick bool AttributeList::hasParentContext(LLVMContext &C) const {
158773471bf0Spatrick   assert(!isEmpty() && "an empty attribute list has no parent context");
158873471bf0Spatrick   FoldingSetNodeID ID;
158973471bf0Spatrick   pImpl->Profile(ID);
159073471bf0Spatrick   void *Unused;
159173471bf0Spatrick   return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
159273471bf0Spatrick }
159373471bf0Spatrick 
begin() const159409467b48Spatrick AttributeList::iterator AttributeList::begin() const {
159509467b48Spatrick   return pImpl ? pImpl->begin() : nullptr;
159609467b48Spatrick }
159709467b48Spatrick 
end() const159809467b48Spatrick AttributeList::iterator AttributeList::end() const {
159909467b48Spatrick   return pImpl ? pImpl->end() : nullptr;
160009467b48Spatrick }
160109467b48Spatrick 
160209467b48Spatrick //===----------------------------------------------------------------------===//
160309467b48Spatrick // AttributeList Introspection Methods
160409467b48Spatrick //===----------------------------------------------------------------------===//
160509467b48Spatrick 
getNumAttrSets() const160609467b48Spatrick unsigned AttributeList::getNumAttrSets() const {
160709467b48Spatrick   return pImpl ? pImpl->NumAttrSets : 0;
160809467b48Spatrick }
160909467b48Spatrick 
print(raw_ostream & O) const161073471bf0Spatrick void AttributeList::print(raw_ostream &O) const {
161173471bf0Spatrick   O << "AttributeList[\n";
161209467b48Spatrick 
1613*d415bd75Srobert   for (unsigned i : indexes()) {
161473471bf0Spatrick     if (!getAttributes(i).hasAttributes())
161573471bf0Spatrick       continue;
161673471bf0Spatrick     O << "  { ";
161773471bf0Spatrick     switch (i) {
161873471bf0Spatrick     case AttrIndex::ReturnIndex:
161973471bf0Spatrick       O << "return";
162073471bf0Spatrick       break;
162173471bf0Spatrick     case AttrIndex::FunctionIndex:
162273471bf0Spatrick       O << "function";
162373471bf0Spatrick       break;
162473471bf0Spatrick     default:
162573471bf0Spatrick       O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
162673471bf0Spatrick     }
162773471bf0Spatrick     O << " => " << getAsString(i) << " }\n";
162809467b48Spatrick   }
162909467b48Spatrick 
163073471bf0Spatrick   O << "]\n";
163109467b48Spatrick }
163273471bf0Spatrick 
163373471bf0Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const163473471bf0Spatrick LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
163509467b48Spatrick #endif
163609467b48Spatrick 
163709467b48Spatrick //===----------------------------------------------------------------------===//
163809467b48Spatrick // AttrBuilder Method Implementations
163909467b48Spatrick //===----------------------------------------------------------------------===//
164009467b48Spatrick 
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1641*d415bd75Srobert AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
1642*d415bd75Srobert   append_range(Attrs, AS);
1643*d415bd75Srobert   assert(is_sorted(Attrs) && "AttributeSet should be sorted");
164409467b48Spatrick }
164509467b48Spatrick 
clear()1646*d415bd75Srobert void AttrBuilder::clear() { Attrs.clear(); }
164709467b48Spatrick 
1648*d415bd75Srobert /// Attribute comparator that only compares attribute keys. Enum attributes are
1649*d415bd75Srobert /// sorted before string attributes.
1650*d415bd75Srobert struct AttributeComparator {
operator ()AttributeComparator1651*d415bd75Srobert   bool operator()(Attribute A0, Attribute A1) const {
1652*d415bd75Srobert     bool A0IsString = A0.isStringAttribute();
1653*d415bd75Srobert     bool A1IsString = A1.isStringAttribute();
1654*d415bd75Srobert     if (A0IsString) {
1655*d415bd75Srobert       if (A1IsString)
1656*d415bd75Srobert         return A0.getKindAsString() < A1.getKindAsString();
1657*d415bd75Srobert       else
1658*d415bd75Srobert         return false;
165909467b48Spatrick     }
1660*d415bd75Srobert     if (A1IsString)
1661*d415bd75Srobert       return true;
1662*d415bd75Srobert     return A0.getKindAsEnum() < A1.getKindAsEnum();
1663*d415bd75Srobert   }
operator ()AttributeComparator1664*d415bd75Srobert   bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
1665*d415bd75Srobert     if (A0.isStringAttribute())
1666*d415bd75Srobert       return false;
1667*d415bd75Srobert     return A0.getKindAsEnum() < Kind;
1668*d415bd75Srobert   }
operator ()AttributeComparator1669*d415bd75Srobert   bool operator()(Attribute A0, StringRef Kind) const {
1670*d415bd75Srobert     if (A0.isStringAttribute())
1671*d415bd75Srobert       return A0.getKindAsString() < Kind;
1672*d415bd75Srobert     return true;
1673*d415bd75Srobert   }
1674*d415bd75Srobert };
167509467b48Spatrick 
1676*d415bd75Srobert template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)1677*d415bd75Srobert static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
1678*d415bd75Srobert                              Attribute Attr) {
1679*d415bd75Srobert   auto It = lower_bound(Attrs, Kind, AttributeComparator());
1680*d415bd75Srobert   if (It != Attrs.end() && It->hasAttribute(Kind))
1681*d415bd75Srobert     std::swap(*It, Attr);
1682*d415bd75Srobert   else
1683*d415bd75Srobert     Attrs.insert(It, Attr);
168409467b48Spatrick }
168509467b48Spatrick 
addAttribute(Attribute Attr)168609467b48Spatrick AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1687*d415bd75Srobert   if (Attr.isStringAttribute())
1688*d415bd75Srobert     addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
1689*d415bd75Srobert   else
1690*d415bd75Srobert     addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
169109467b48Spatrick   return *this;
169209467b48Spatrick }
169309467b48Spatrick 
addAttribute(Attribute::AttrKind Kind)1694*d415bd75Srobert AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
1695*d415bd75Srobert   addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
169609467b48Spatrick   return *this;
169709467b48Spatrick }
169809467b48Spatrick 
addAttribute(StringRef A,StringRef V)169909467b48Spatrick AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1700*d415bd75Srobert   addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
170109467b48Spatrick   return *this;
170209467b48Spatrick }
170309467b48Spatrick 
removeAttribute(Attribute::AttrKind Val)170409467b48Spatrick AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
170509467b48Spatrick   assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
1706*d415bd75Srobert   auto It = lower_bound(Attrs, Val, AttributeComparator());
1707*d415bd75Srobert   if (It != Attrs.end() && It->hasAttribute(Val))
1708*d415bd75Srobert     Attrs.erase(It);
170909467b48Spatrick   return *this;
171009467b48Spatrick }
171109467b48Spatrick 
removeAttribute(StringRef A)171209467b48Spatrick AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1713*d415bd75Srobert   auto It = lower_bound(Attrs, A, AttributeComparator());
1714*d415bd75Srobert   if (It != Attrs.end() && It->hasAttribute(A))
1715*d415bd75Srobert     Attrs.erase(It);
171609467b48Spatrick   return *this;
171709467b48Spatrick }
171809467b48Spatrick 
1719*d415bd75Srobert std::optional<uint64_t>
getRawIntAttr(Attribute::AttrKind Kind) const1720*d415bd75Srobert AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
1721*d415bd75Srobert   assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
1722*d415bd75Srobert   Attribute A = getAttribute(Kind);
1723*d415bd75Srobert   if (A.isValid())
1724*d415bd75Srobert     return A.getValueAsInt();
1725*d415bd75Srobert   return std::nullopt;
172609467b48Spatrick }
172709467b48Spatrick 
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)1728*d415bd75Srobert AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
1729*d415bd75Srobert                                         uint64_t Value) {
1730*d415bd75Srobert   return addAttribute(Attribute::get(Ctx, Kind, Value));
1731*d415bd75Srobert }
1732*d415bd75Srobert 
1733*d415bd75Srobert std::optional<std::pair<unsigned, std::optional<unsigned>>>
getAllocSizeArgs() const1734*d415bd75Srobert AttrBuilder::getAllocSizeArgs() const {
1735*d415bd75Srobert   Attribute A = getAttribute(Attribute::AllocSize);
1736*d415bd75Srobert   if (A.isValid())
1737*d415bd75Srobert     return A.getAllocSizeArgs();
1738*d415bd75Srobert   return std::nullopt;
173973471bf0Spatrick }
174073471bf0Spatrick 
addAlignmentAttr(MaybeAlign Align)174109467b48Spatrick AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
174209467b48Spatrick   if (!Align)
174309467b48Spatrick     return *this;
174409467b48Spatrick 
1745097a140dSpatrick   assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
1746*d415bd75Srobert   return addRawIntAttr(Attribute::Alignment, Align->value());
174709467b48Spatrick }
174809467b48Spatrick 
addStackAlignmentAttr(MaybeAlign Align)174909467b48Spatrick AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
175009467b48Spatrick   // Default alignment, allow the target to define how to align it.
175109467b48Spatrick   if (!Align)
175209467b48Spatrick     return *this;
175309467b48Spatrick 
175409467b48Spatrick   assert(*Align <= 0x100 && "Alignment too large.");
1755*d415bd75Srobert   return addRawIntAttr(Attribute::StackAlignment, Align->value());
175609467b48Spatrick }
175709467b48Spatrick 
addDereferenceableAttr(uint64_t Bytes)175809467b48Spatrick AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
175909467b48Spatrick   if (Bytes == 0) return *this;
176009467b48Spatrick 
1761*d415bd75Srobert   return addRawIntAttr(Attribute::Dereferenceable, Bytes);
176209467b48Spatrick }
176309467b48Spatrick 
addDereferenceableOrNullAttr(uint64_t Bytes)176409467b48Spatrick AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
176509467b48Spatrick   if (Bytes == 0)
176609467b48Spatrick     return *this;
176709467b48Spatrick 
1768*d415bd75Srobert   return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
176909467b48Spatrick }
177009467b48Spatrick 
1771*d415bd75Srobert AttrBuilder &
addAllocSizeAttr(unsigned ElemSize,const std::optional<unsigned> & NumElems)1772*d415bd75Srobert AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1773*d415bd75Srobert                               const std::optional<unsigned> &NumElems) {
177409467b48Spatrick   return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
177509467b48Spatrick }
177609467b48Spatrick 
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)177709467b48Spatrick AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
177809467b48Spatrick   // (0, 0) is our "not present" value, so we need to check for it here.
177909467b48Spatrick   assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
1780*d415bd75Srobert   return addRawIntAttr(Attribute::AllocSize, RawArgs);
178109467b48Spatrick }
178209467b48Spatrick 
addVScaleRangeAttr(unsigned MinValue,std::optional<unsigned> MaxValue)178373471bf0Spatrick AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1784*d415bd75Srobert                                              std::optional<unsigned> MaxValue) {
178573471bf0Spatrick   return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
178673471bf0Spatrick }
178773471bf0Spatrick 
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)178873471bf0Spatrick AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
178973471bf0Spatrick   // (0, 0) is not present hence ignore this case
179073471bf0Spatrick   if (RawArgs == 0)
179173471bf0Spatrick     return *this;
179273471bf0Spatrick 
1793*d415bd75Srobert   return addRawIntAttr(Attribute::VScaleRange, RawArgs);
1794*d415bd75Srobert }
1795*d415bd75Srobert 
addUWTableAttr(UWTableKind Kind)1796*d415bd75Srobert AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
1797*d415bd75Srobert   if (Kind == UWTableKind::None)
179809467b48Spatrick     return *this;
1799*d415bd75Srobert   return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
1800*d415bd75Srobert }
1801*d415bd75Srobert 
addMemoryAttr(MemoryEffects ME)1802*d415bd75Srobert AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
1803*d415bd75Srobert   return addRawIntAttr(Attribute::Memory, ME.toIntValue());
1804*d415bd75Srobert }
1805*d415bd75Srobert 
addAllocKindAttr(AllocFnKind Kind)1806*d415bd75Srobert AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1807*d415bd75Srobert   return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
180809467b48Spatrick }
180909467b48Spatrick 
getTypeAttr(Attribute::AttrKind Kind) const181073471bf0Spatrick Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1811*d415bd75Srobert   assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
1812*d415bd75Srobert   Attribute A = getAttribute(Kind);
1813*d415bd75Srobert   return A.isValid() ? A.getValueAsType() : nullptr;
181473471bf0Spatrick }
181573471bf0Spatrick 
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)181673471bf0Spatrick AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1817*d415bd75Srobert   return addAttribute(Attribute::get(Ctx, Kind, Ty));
1818097a140dSpatrick }
1819097a140dSpatrick 
addByValAttr(Type * Ty)182073471bf0Spatrick AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
182173471bf0Spatrick   return addTypeAttr(Attribute::ByVal, Ty);
182273471bf0Spatrick }
182373471bf0Spatrick 
addStructRetAttr(Type * Ty)182473471bf0Spatrick AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
182573471bf0Spatrick   return addTypeAttr(Attribute::StructRet, Ty);
182673471bf0Spatrick }
182773471bf0Spatrick 
addByRefAttr(Type * Ty)182873471bf0Spatrick AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
182973471bf0Spatrick   return addTypeAttr(Attribute::ByRef, Ty);
183073471bf0Spatrick }
183173471bf0Spatrick 
addPreallocatedAttr(Type * Ty)183273471bf0Spatrick AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
183373471bf0Spatrick   return addTypeAttr(Attribute::Preallocated, Ty);
183473471bf0Spatrick }
183573471bf0Spatrick 
addInAllocaAttr(Type * Ty)183673471bf0Spatrick AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
183773471bf0Spatrick   return addTypeAttr(Attribute::InAlloca, Ty);
183873471bf0Spatrick }
183973471bf0Spatrick 
merge(const AttrBuilder & B)184009467b48Spatrick AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1841*d415bd75Srobert   // TODO: Could make this O(n) as we're merging two sorted lists.
1842*d415bd75Srobert   for (const auto &I : B.attrs())
1843*d415bd75Srobert     addAttribute(I);
184409467b48Spatrick 
184509467b48Spatrick   return *this;
184609467b48Spatrick }
184709467b48Spatrick 
remove(const AttributeMask & AM)1848*d415bd75Srobert AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
1849*d415bd75Srobert   erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
185009467b48Spatrick   return *this;
185109467b48Spatrick }
185209467b48Spatrick 
overlaps(const AttributeMask & AM) const1853*d415bd75Srobert bool AttrBuilder::overlaps(const AttributeMask &AM) const {
1854*d415bd75Srobert   return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
1855*d415bd75Srobert }
185609467b48Spatrick 
getAttribute(Attribute::AttrKind A) const1857*d415bd75Srobert Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
1858*d415bd75Srobert   assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
1859*d415bd75Srobert   auto It = lower_bound(Attrs, A, AttributeComparator());
1860*d415bd75Srobert   if (It != Attrs.end() && It->hasAttribute(A))
1861*d415bd75Srobert     return *It;
1862*d415bd75Srobert   return {};
1863*d415bd75Srobert }
186409467b48Spatrick 
getAttribute(StringRef A) const1865*d415bd75Srobert Attribute AttrBuilder::getAttribute(StringRef A) const {
1866*d415bd75Srobert   auto It = lower_bound(Attrs, A, AttributeComparator());
1867*d415bd75Srobert   if (It != Attrs.end() && It->hasAttribute(A))
1868*d415bd75Srobert     return *It;
1869*d415bd75Srobert   return {};
1870*d415bd75Srobert }
1871*d415bd75Srobert 
contains(Attribute::AttrKind A) const1872*d415bd75Srobert bool AttrBuilder::contains(Attribute::AttrKind A) const {
1873*d415bd75Srobert   return getAttribute(A).isValid();
187409467b48Spatrick }
187509467b48Spatrick 
contains(StringRef A) const187609467b48Spatrick bool AttrBuilder::contains(StringRef A) const {
1877*d415bd75Srobert   return getAttribute(A).isValid();
187809467b48Spatrick }
187909467b48Spatrick 
operator ==(const AttrBuilder & B) const188073471bf0Spatrick bool AttrBuilder::operator==(const AttrBuilder &B) const {
1881*d415bd75Srobert   return Attrs == B.Attrs;
188209467b48Spatrick }
188309467b48Spatrick 
188409467b48Spatrick //===----------------------------------------------------------------------===//
188509467b48Spatrick // AttributeFuncs Function Defintions
188609467b48Spatrick //===----------------------------------------------------------------------===//
188709467b48Spatrick 
188809467b48Spatrick /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)1889*d415bd75Srobert AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
1890*d415bd75Srobert                                                AttributeSafetyKind ASK) {
1891*d415bd75Srobert   AttributeMask Incompatible;
189209467b48Spatrick 
1893*d415bd75Srobert   if (!Ty->isIntegerTy()) {
1894*d415bd75Srobert     // Attributes that only apply to integers.
1895*d415bd75Srobert     if (ASK & ASK_SAFE_TO_DROP)
1896*d415bd75Srobert       Incompatible.addAttribute(Attribute::AllocAlign);
1897*d415bd75Srobert     if (ASK & ASK_UNSAFE_TO_DROP)
1898*d415bd75Srobert       Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
1899*d415bd75Srobert   }
190009467b48Spatrick 
1901*d415bd75Srobert   if (!Ty->isPointerTy()) {
1902*d415bd75Srobert     // Attributes that only apply to pointers.
1903*d415bd75Srobert     if (ASK & ASK_SAFE_TO_DROP)
1904*d415bd75Srobert       Incompatible.addAttribute(Attribute::NoAlias)
190509467b48Spatrick           .addAttribute(Attribute::NoCapture)
190609467b48Spatrick           .addAttribute(Attribute::NonNull)
190709467b48Spatrick           .addAttribute(Attribute::ReadNone)
190809467b48Spatrick           .addAttribute(Attribute::ReadOnly)
1909*d415bd75Srobert           .addAttribute(Attribute::Dereferenceable)
1910*d415bd75Srobert           .addAttribute(Attribute::DereferenceableOrNull);
1911*d415bd75Srobert     if (ASK & ASK_UNSAFE_TO_DROP)
1912*d415bd75Srobert       Incompatible.addAttribute(Attribute::Nest)
191373471bf0Spatrick           .addAttribute(Attribute::SwiftError)
1914*d415bd75Srobert           .addAttribute(Attribute::Preallocated)
1915*d415bd75Srobert           .addAttribute(Attribute::InAlloca)
1916*d415bd75Srobert           .addAttribute(Attribute::ByVal)
1917*d415bd75Srobert           .addAttribute(Attribute::StructRet)
1918*d415bd75Srobert           .addAttribute(Attribute::ByRef)
1919*d415bd75Srobert           .addAttribute(Attribute::ElementType)
1920*d415bd75Srobert           .addAttribute(Attribute::AllocatedPointer);
1921*d415bd75Srobert   }
1922*d415bd75Srobert 
1923*d415bd75Srobert     // Attributes that only apply to pointers or vectors of pointers.
1924*d415bd75Srobert   if (!Ty->isPtrOrPtrVectorTy()) {
1925*d415bd75Srobert     if (ASK & ASK_SAFE_TO_DROP)
1926*d415bd75Srobert       Incompatible.addAttribute(Attribute::Alignment);
1927*d415bd75Srobert   }
192873471bf0Spatrick 
192973471bf0Spatrick   // Some attributes can apply to all "values" but there are no `void` values.
1930*d415bd75Srobert   if (Ty->isVoidTy()) {
1931*d415bd75Srobert     if (ASK & ASK_SAFE_TO_DROP)
193273471bf0Spatrick       Incompatible.addAttribute(Attribute::NoUndef);
1933*d415bd75Srobert   }
193409467b48Spatrick 
193509467b48Spatrick   return Incompatible;
193609467b48Spatrick }
193709467b48Spatrick 
getUBImplyingAttributes()1938*d415bd75Srobert AttributeMask AttributeFuncs::getUBImplyingAttributes() {
1939*d415bd75Srobert   AttributeMask AM;
1940*d415bd75Srobert   AM.addAttribute(Attribute::NoUndef);
1941*d415bd75Srobert   AM.addAttribute(Attribute::Dereferenceable);
1942*d415bd75Srobert   AM.addAttribute(Attribute::DereferenceableOrNull);
1943*d415bd75Srobert   return AM;
194473471bf0Spatrick }
194573471bf0Spatrick 
194609467b48Spatrick template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)194709467b48Spatrick static bool isEqual(const Function &Caller, const Function &Callee) {
194809467b48Spatrick   return Caller.getFnAttribute(AttrClass::getKind()) ==
194909467b48Spatrick          Callee.getFnAttribute(AttrClass::getKind());
195009467b48Spatrick }
195109467b48Spatrick 
195209467b48Spatrick /// Compute the logical AND of the attributes of the caller and the
195309467b48Spatrick /// callee.
195409467b48Spatrick ///
195509467b48Spatrick /// This function sets the caller's attribute to false if the callee's attribute
195609467b48Spatrick /// is false.
195709467b48Spatrick template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)195809467b48Spatrick static void setAND(Function &Caller, const Function &Callee) {
195909467b48Spatrick   if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
196009467b48Spatrick       !AttrClass::isSet(Callee, AttrClass::getKind()))
196109467b48Spatrick     AttrClass::set(Caller, AttrClass::getKind(), false);
196209467b48Spatrick }
196309467b48Spatrick 
196409467b48Spatrick /// Compute the logical OR of the attributes of the caller and the
196509467b48Spatrick /// callee.
196609467b48Spatrick ///
196709467b48Spatrick /// This function sets the caller's attribute to true if the callee's attribute
196809467b48Spatrick /// is true.
196909467b48Spatrick template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)197009467b48Spatrick static void setOR(Function &Caller, const Function &Callee) {
197109467b48Spatrick   if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
197209467b48Spatrick       AttrClass::isSet(Callee, AttrClass::getKind()))
197309467b48Spatrick     AttrClass::set(Caller, AttrClass::getKind(), true);
197409467b48Spatrick }
197509467b48Spatrick 
197609467b48Spatrick /// If the inlined function had a higher stack protection level than the
197709467b48Spatrick /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)197809467b48Spatrick static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1979*d415bd75Srobert   // If the calling function has *no* stack protection level (e.g. it was built
1980*d415bd75Srobert   // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
1981*d415bd75Srobert   // change it as that could change the program's semantics.
1982*d415bd75Srobert   if (!Caller.hasStackProtectorFnAttr())
1983*d415bd75Srobert     return;
1984*d415bd75Srobert 
198509467b48Spatrick   // If upgrading the SSP attribute, clear out the old SSP Attributes first.
198609467b48Spatrick   // Having multiple SSP attributes doesn't actually hurt, but it adds useless
198709467b48Spatrick   // clutter to the IR.
1988*d415bd75Srobert   AttributeMask OldSSPAttr;
198909467b48Spatrick   OldSSPAttr.addAttribute(Attribute::StackProtect)
199009467b48Spatrick       .addAttribute(Attribute::StackProtectStrong)
199109467b48Spatrick       .addAttribute(Attribute::StackProtectReq);
199209467b48Spatrick 
199309467b48Spatrick   if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1994*d415bd75Srobert     Caller.removeFnAttrs(OldSSPAttr);
199509467b48Spatrick     Caller.addFnAttr(Attribute::StackProtectReq);
199609467b48Spatrick   } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
199709467b48Spatrick              !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1998*d415bd75Srobert     Caller.removeFnAttrs(OldSSPAttr);
199909467b48Spatrick     Caller.addFnAttr(Attribute::StackProtectStrong);
200009467b48Spatrick   } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
200109467b48Spatrick              !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
200209467b48Spatrick              !Caller.hasFnAttribute(Attribute::StackProtectStrong))
200309467b48Spatrick     Caller.addFnAttr(Attribute::StackProtect);
200409467b48Spatrick }
200509467b48Spatrick 
200609467b48Spatrick /// If the inlined function required stack probes, then ensure that
200709467b48Spatrick /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)200809467b48Spatrick static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
200909467b48Spatrick   if (!Caller.hasFnAttribute("probe-stack") &&
201009467b48Spatrick       Callee.hasFnAttribute("probe-stack")) {
201109467b48Spatrick     Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
201209467b48Spatrick   }
201309467b48Spatrick }
201409467b48Spatrick 
201509467b48Spatrick /// If the inlined function defines the size of guard region
201609467b48Spatrick /// on the stack, then ensure that the calling function defines a guard region
201709467b48Spatrick /// that is no larger.
201809467b48Spatrick static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)201909467b48Spatrick adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
202073471bf0Spatrick   Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
202173471bf0Spatrick   if (CalleeAttr.isValid()) {
202273471bf0Spatrick     Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
202373471bf0Spatrick     if (CallerAttr.isValid()) {
202473471bf0Spatrick       uint64_t CallerStackProbeSize, CalleeStackProbeSize;
202573471bf0Spatrick       CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
202673471bf0Spatrick       CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
202773471bf0Spatrick 
202809467b48Spatrick       if (CallerStackProbeSize > CalleeStackProbeSize) {
202973471bf0Spatrick         Caller.addFnAttr(CalleeAttr);
203009467b48Spatrick       }
203109467b48Spatrick     } else {
203273471bf0Spatrick       Caller.addFnAttr(CalleeAttr);
203309467b48Spatrick     }
203409467b48Spatrick   }
203509467b48Spatrick }
203609467b48Spatrick 
203709467b48Spatrick /// If the inlined function defines a min legal vector width, then ensure
203809467b48Spatrick /// the calling function has the same or larger min legal vector width. If the
203909467b48Spatrick /// caller has the attribute, but the callee doesn't, we need to remove the
204009467b48Spatrick /// attribute from the caller since we can't make any guarantees about the
204109467b48Spatrick /// caller's requirements.
204209467b48Spatrick /// This function is called after the inlining decision has been made so we have
204309467b48Spatrick /// to merge the attribute this way. Heuristics that would use
204409467b48Spatrick /// min-legal-vector-width to determine inline compatibility would need to be
204509467b48Spatrick /// handled as part of inline cost analysis.
204609467b48Spatrick static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)204709467b48Spatrick adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
204873471bf0Spatrick   Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
204973471bf0Spatrick   if (CallerAttr.isValid()) {
205073471bf0Spatrick     Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
205173471bf0Spatrick     if (CalleeAttr.isValid()) {
205273471bf0Spatrick       uint64_t CallerVectorWidth, CalleeVectorWidth;
205373471bf0Spatrick       CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
205473471bf0Spatrick       CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
205509467b48Spatrick       if (CallerVectorWidth < CalleeVectorWidth)
205673471bf0Spatrick         Caller.addFnAttr(CalleeAttr);
205709467b48Spatrick     } else {
205809467b48Spatrick       // If the callee doesn't have the attribute then we don't know anything
205909467b48Spatrick       // and must drop the attribute from the caller.
206009467b48Spatrick       Caller.removeFnAttr("min-legal-vector-width");
206109467b48Spatrick     }
206209467b48Spatrick   }
206309467b48Spatrick }
206409467b48Spatrick 
2065097a140dSpatrick /// If the inlined function has null_pointer_is_valid attribute,
206609467b48Spatrick /// set this attribute in the caller post inlining.
206709467b48Spatrick static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)206809467b48Spatrick adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
206909467b48Spatrick   if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2070097a140dSpatrick     Caller.addFnAttr(Attribute::NullPointerIsValid);
207109467b48Spatrick   }
207209467b48Spatrick }
207309467b48Spatrick 
2074097a140dSpatrick struct EnumAttr {
isSetEnumAttr2075097a140dSpatrick   static bool isSet(const Function &Fn,
2076097a140dSpatrick                     Attribute::AttrKind Kind) {
2077097a140dSpatrick     return Fn.hasFnAttribute(Kind);
2078097a140dSpatrick   }
2079097a140dSpatrick 
setEnumAttr2080097a140dSpatrick   static void set(Function &Fn,
2081097a140dSpatrick                   Attribute::AttrKind Kind, bool Val) {
2082097a140dSpatrick     if (Val)
2083097a140dSpatrick       Fn.addFnAttr(Kind);
2084097a140dSpatrick     else
2085097a140dSpatrick       Fn.removeFnAttr(Kind);
2086097a140dSpatrick   }
2087097a140dSpatrick };
2088097a140dSpatrick 
2089097a140dSpatrick struct StrBoolAttr {
isSetStrBoolAttr2090097a140dSpatrick   static bool isSet(const Function &Fn,
2091097a140dSpatrick                     StringRef Kind) {
2092097a140dSpatrick     auto A = Fn.getFnAttribute(Kind);
2093097a140dSpatrick     return A.getValueAsString().equals("true");
2094097a140dSpatrick   }
2095097a140dSpatrick 
setStrBoolAttr2096097a140dSpatrick   static void set(Function &Fn,
2097097a140dSpatrick                   StringRef Kind, bool Val) {
2098097a140dSpatrick     Fn.addFnAttr(Kind, Val ? "true" : "false");
2099097a140dSpatrick   }
2100097a140dSpatrick };
2101097a140dSpatrick 
2102097a140dSpatrick #define GET_ATTR_NAMES
2103097a140dSpatrick #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
2104097a140dSpatrick   struct ENUM_NAME##Attr : EnumAttr {                                          \
2105097a140dSpatrick     static enum Attribute::AttrKind getKind() {                                \
2106097a140dSpatrick       return llvm::Attribute::ENUM_NAME;                                       \
2107097a140dSpatrick     }                                                                          \
2108097a140dSpatrick   };
2109097a140dSpatrick #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME)                             \
2110097a140dSpatrick   struct ENUM_NAME##Attr : StrBoolAttr {                                       \
2111097a140dSpatrick     static StringRef getKind() { return #DISPLAY_NAME; }                       \
2112097a140dSpatrick   };
2113097a140dSpatrick #include "llvm/IR/Attributes.inc"
2114097a140dSpatrick 
211509467b48Spatrick #define GET_ATTR_COMPAT_FUNC
2116097a140dSpatrick #include "llvm/IR/Attributes.inc"
211709467b48Spatrick 
areInlineCompatible(const Function & Caller,const Function & Callee)211809467b48Spatrick bool AttributeFuncs::areInlineCompatible(const Function &Caller,
211909467b48Spatrick                                          const Function &Callee) {
212009467b48Spatrick   return hasCompatibleFnAttrs(Caller, Callee);
212109467b48Spatrick }
212209467b48Spatrick 
areOutlineCompatible(const Function & A,const Function & B)212373471bf0Spatrick bool AttributeFuncs::areOutlineCompatible(const Function &A,
212473471bf0Spatrick                                           const Function &B) {
212573471bf0Spatrick   return hasCompatibleFnAttrs(A, B);
212673471bf0Spatrick }
212773471bf0Spatrick 
mergeAttributesForInlining(Function & Caller,const Function & Callee)212809467b48Spatrick void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
212909467b48Spatrick                                                 const Function &Callee) {
213009467b48Spatrick   mergeFnAttrs(Caller, Callee);
213109467b48Spatrick }
213273471bf0Spatrick 
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)213373471bf0Spatrick void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
213473471bf0Spatrick                                                 const Function &ToMerge) {
213573471bf0Spatrick 
213673471bf0Spatrick   // We merge functions so that they meet the most general case.
213773471bf0Spatrick   // For example, if the NoNansFPMathAttr is set in one function, but not in
213873471bf0Spatrick   // the other, in the merged function we can say that the NoNansFPMathAttr
213973471bf0Spatrick   // is not set.
214073471bf0Spatrick   // However if we have the SpeculativeLoadHardeningAttr set true in one
214173471bf0Spatrick   // function, but not the other, we make sure that the function retains
214273471bf0Spatrick   // that aspect in the merged function.
214373471bf0Spatrick   mergeFnAttrs(Base, ToMerge);
214473471bf0Spatrick }
2145*d415bd75Srobert 
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)2146*d415bd75Srobert void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2147*d415bd75Srobert                                                    uint64_t Width) {
2148*d415bd75Srobert   Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2149*d415bd75Srobert   if (Attr.isValid()) {
2150*d415bd75Srobert     uint64_t OldWidth;
2151*d415bd75Srobert     Attr.getValueAsString().getAsInteger(0, OldWidth);
2152*d415bd75Srobert     if (Width > OldWidth)
2153*d415bd75Srobert       Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2154*d415bd75Srobert   }
2155*d415bd75Srobert }
2156