1deaf6951SEugene Zelenko //===- Attributes.cpp - Implement AttributesList --------------------------===//
2ef860a24SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef860a24SChandler Carruth //
7ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
8ef860a24SChandler Carruth //
9ec454546SBill Wendling // \file
105f8f34e4SAdrian Prantl // This file implements the Attribute, AttributeImpl, AttrBuilder,
11b518054bSReid Kleckner // AttributeListImpl, and AttributeList classes.
12ef860a24SChandler Carruth //
13ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
14ef860a24SChandler Carruth
156bda14b3SChandler Carruth #include "llvm/IR/Attributes.h"
16ef860a24SChandler Carruth #include "AttributeImpl.h"
17ef860a24SChandler Carruth #include "LLVMContextImpl.h"
18deaf6951SEugene Zelenko #include "llvm/ADT/ArrayRef.h"
19deaf6951SEugene Zelenko #include "llvm/ADT/FoldingSet.h"
20deaf6951SEugene Zelenko #include "llvm/ADT/Optional.h"
21502b9e1dSBenjamin Kramer #include "llvm/ADT/STLExtras.h"
226bda14b3SChandler Carruth #include "llvm/ADT/SmallVector.h"
23ef860a24SChandler Carruth #include "llvm/ADT/StringExtras.h"
24deaf6951SEugene Zelenko #include "llvm/ADT/StringRef.h"
25af450eabSReid Kleckner #include "llvm/ADT/StringSwitch.h"
26432a3883SNico Weber #include "llvm/Config/llvm-config.h"
27deaf6951SEugene Zelenko #include "llvm/IR/Function.h"
28deaf6951SEugene Zelenko #include "llvm/IR/LLVMContext.h"
299fb823bbSChandler Carruth #include "llvm/IR/Type.h"
30deaf6951SEugene Zelenko #include "llvm/Support/Compiler.h"
31deaf6951SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
32ef860a24SChandler Carruth #include "llvm/Support/raw_ostream.h"
33d2e493bbSBill Wendling #include <algorithm>
34deaf6951SEugene Zelenko #include <cassert>
35d761e2c2SEugene Zelenko #include <cstddef>
36deaf6951SEugene Zelenko #include <cstdint>
37deaf6951SEugene Zelenko #include <limits>
38deaf6951SEugene Zelenko #include <string>
39deaf6951SEugene Zelenko #include <tuple>
40deaf6951SEugene Zelenko #include <utility>
41deaf6951SEugene Zelenko
42ef860a24SChandler Carruth using namespace llvm;
43ef860a24SChandler Carruth
44ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
457707c5a9SBill Wendling // Attribute Construction Methods
46ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
47ef860a24SChandler Carruth
48278199f6SGeorge Burgess IV // allocsize has two integer arguments, but because they're both 32 bits, we can
49278199f6SGeorge Burgess IV // pack them into one 64-bit value, at the cost of making said value
50278199f6SGeorge Burgess IV // nonsensical.
51278199f6SGeorge Burgess IV //
52278199f6SGeorge Burgess IV // In order to do this, we need to reserve one value of the second (optional)
53278199f6SGeorge Burgess IV // allocsize argument to signify "not present."
54381fc0eeSGeorge Burgess IV static const unsigned AllocSizeNumElemsNotPresent = -1;
55278199f6SGeorge Burgess IV
packAllocSizeArgs(unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)56278199f6SGeorge Burgess IV static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
57278199f6SGeorge Burgess IV const Optional<unsigned> &NumElemsArg) {
58*ad7ce1e7SKazu Hirata assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
59278199f6SGeorge Burgess IV "Attempting to pack a reserved value");
60278199f6SGeorge Burgess IV
61278199f6SGeorge Burgess IV return uint64_t(ElemSizeArg) << 32 |
62129b531cSKazu Hirata NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
63278199f6SGeorge Burgess IV }
64278199f6SGeorge Burgess IV
65278199f6SGeorge Burgess IV static std::pair<unsigned, Optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num)66278199f6SGeorge Burgess IV unpackAllocSizeArgs(uint64_t Num) {
67278199f6SGeorge Burgess IV unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
68278199f6SGeorge Burgess IV unsigned ElemSizeArg = Num >> 32;
69278199f6SGeorge Burgess IV
70278199f6SGeorge Burgess IV Optional<unsigned> NumElemsArg;
71278199f6SGeorge Burgess IV if (NumElems != AllocSizeNumElemsNotPresent)
72278199f6SGeorge Burgess IV NumElemsArg = NumElems;
73278199f6SGeorge Burgess IV return std::make_pair(ElemSizeArg, NumElemsArg);
74278199f6SGeorge Burgess IV }
75278199f6SGeorge Burgess IV
packVScaleRangeArgs(unsigned MinValue,Optional<unsigned> MaxValue)760395e015SCullen Rhodes static uint64_t packVScaleRangeArgs(unsigned MinValue,
770395e015SCullen Rhodes Optional<unsigned> MaxValue) {
78129b531cSKazu Hirata return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
7948f5a392SBradley Smith }
8048f5a392SBradley Smith
810395e015SCullen Rhodes static std::pair<unsigned, Optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value)820395e015SCullen Rhodes unpackVScaleRangeArgs(uint64_t Value) {
8348f5a392SBradley Smith unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
8448f5a392SBradley Smith unsigned MinValue = Value >> 32;
8548f5a392SBradley Smith
860395e015SCullen Rhodes return std::make_pair(MinValue,
870395e015SCullen Rhodes MaxValue > 0 ? MaxValue : Optional<unsigned>());
8848f5a392SBradley Smith }
8948f5a392SBradley Smith
get(LLVMContext & Context,Attribute::AttrKind Kind,uint64_t Val)90e1cef6e3SMatt Arsenault Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
91e1cef6e3SMatt Arsenault uint64_t Val) {
923fb0621fSNikita Popov if (Val)
933fb0621fSNikita Popov assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
943fb0621fSNikita Popov else
953fb0621fSNikita Popov assert(Attribute::isEnumAttrKind(Kind) && "Not an enum attribute");
963fb0621fSNikita Popov
97e1cef6e3SMatt Arsenault LLVMContextImpl *pImpl = Context.pImpl;
98e1cef6e3SMatt Arsenault FoldingSetNodeID ID;
99e1cef6e3SMatt Arsenault ID.AddInteger(Kind);
100fb4308edSMatt Arsenault if (Val) ID.AddInteger(Val);
101e1cef6e3SMatt Arsenault
102e1cef6e3SMatt Arsenault void *InsertPoint;
103e1cef6e3SMatt Arsenault AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
104e1cef6e3SMatt Arsenault
105e1cef6e3SMatt Arsenault if (!PA) {
106e1cef6e3SMatt Arsenault // If we didn't find any existing attributes of the same shape then create a
107e1cef6e3SMatt Arsenault // new one and insert it.
108fb4308edSMatt Arsenault if (!Val)
1091c3fe86fSBenjamin Kramer PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
110fb4308edSMatt Arsenault else
1111c3fe86fSBenjamin Kramer PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
1123f12ac21SBill Wendling pImpl->AttrsSet.InsertNode(PA, InsertPoint);
1133f12ac21SBill Wendling }
1143f12ac21SBill Wendling
1153f12ac21SBill Wendling // Return the Attribute that we found or created.
1163f12ac21SBill Wendling return Attribute(PA);
1173f12ac21SBill Wendling }
1183f12ac21SBill Wendling
get(LLVMContext & Context,StringRef Kind,StringRef Val)1193f12ac21SBill Wendling Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
1203f12ac21SBill Wendling LLVMContextImpl *pImpl = Context.pImpl;
1213f12ac21SBill Wendling FoldingSetNodeID ID;
1223f12ac21SBill Wendling ID.AddString(Kind);
1233f12ac21SBill Wendling if (!Val.empty()) ID.AddString(Val);
124ef860a24SChandler Carruth
125ef860a24SChandler Carruth void *InsertPoint;
126ef860a24SChandler Carruth AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
127ef860a24SChandler Carruth
128ef860a24SChandler Carruth if (!PA) {
129ef860a24SChandler Carruth // If we didn't find any existing attributes of the same shape then create a
130ef860a24SChandler Carruth // new one and insert it.
1311c3fe86fSBenjamin Kramer void *Mem =
1321c3fe86fSBenjamin Kramer pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
1331c3fe86fSBenjamin Kramer alignof(StringAttributeImpl));
1341c3fe86fSBenjamin Kramer PA = new (Mem) StringAttributeImpl(Kind, Val);
135ef860a24SChandler Carruth pImpl->AttrsSet.InsertNode(PA, InsertPoint);
136ef860a24SChandler Carruth }
137ef860a24SChandler Carruth
138b9c5b1a5SBill Wendling // Return the Attribute that we found or created.
139ef860a24SChandler Carruth return Attribute(PA);
140ef860a24SChandler Carruth }
141ef860a24SChandler Carruth
get(LLVMContext & Context,Attribute::AttrKind Kind,Type * Ty)142b7141207STim Northover Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
143b7141207STim Northover Type *Ty) {
1445d1464cbSNikita Popov assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
145b7141207STim Northover LLVMContextImpl *pImpl = Context.pImpl;
146b7141207STim Northover FoldingSetNodeID ID;
147b7141207STim Northover ID.AddInteger(Kind);
148b7141207STim Northover ID.AddPointer(Ty);
149b7141207STim Northover
150b7141207STim Northover void *InsertPoint;
151b7141207STim Northover AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
152b7141207STim Northover
153b7141207STim Northover if (!PA) {
154b7141207STim Northover // If we didn't find any existing attributes of the same shape then create a
155b7141207STim Northover // new one and insert it.
1561c3fe86fSBenjamin Kramer PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
157b7141207STim Northover pImpl->AttrsSet.InsertNode(PA, InsertPoint);
158b7141207STim Northover }
159b7141207STim Northover
160b7141207STim Northover // Return the Attribute that we found or created.
161b7141207STim Northover return Attribute(PA);
162b7141207STim Northover }
163b7141207STim Northover
getWithAlignment(LLVMContext & Context,Align A)164b65fa483SGuillaume Chatelet Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
165d096f8d3SRoman Lebedev assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
166b65fa483SGuillaume Chatelet return get(Context, Alignment, A.value());
1674bbe9db4SBill Wendling }
1684bbe9db4SBill Wendling
getWithStackAlignment(LLVMContext & Context,Align A)169b65fa483SGuillaume Chatelet Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
170b65fa483SGuillaume Chatelet assert(A <= 0x100 && "Alignment too large.");
171b65fa483SGuillaume Chatelet return get(Context, StackAlignment, A.value());
1724bbe9db4SBill Wendling }
1734bbe9db4SBill Wendling
getWithDereferenceableBytes(LLVMContext & Context,uint64_t Bytes)174b0407ba0SHal Finkel Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
175b0407ba0SHal Finkel uint64_t Bytes) {
176b0407ba0SHal Finkel assert(Bytes && "Bytes must be non-zero.");
177b0407ba0SHal Finkel return get(Context, Dereferenceable, Bytes);
178b0407ba0SHal Finkel }
179b0407ba0SHal Finkel
getWithDereferenceableOrNullBytes(LLVMContext & Context,uint64_t Bytes)18031ea6d15SSanjoy Das Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
18131ea6d15SSanjoy Das uint64_t Bytes) {
18231ea6d15SSanjoy Das assert(Bytes && "Bytes must be non-zero.");
18331ea6d15SSanjoy Das return get(Context, DereferenceableOrNull, Bytes);
18431ea6d15SSanjoy Das }
18531ea6d15SSanjoy Das
getWithByValType(LLVMContext & Context,Type * Ty)186b7141207STim Northover Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
187b7141207STim Northover return get(Context, ByVal, Ty);
188b7141207STim Northover }
189b7141207STim Northover
getWithStructRetType(LLVMContext & Context,Type * Ty)1900a7cd99aSMatt Arsenault Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
1910a7cd99aSMatt Arsenault return get(Context, StructRet, Ty);
1920a7cd99aSMatt Arsenault }
1930a7cd99aSMatt Arsenault
getWithByRefType(LLVMContext & Context,Type * Ty)1945e999cbeSMatt Arsenault Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
1955e999cbeSMatt Arsenault return get(Context, ByRef, Ty);
1965e999cbeSMatt Arsenault }
1975e999cbeSMatt Arsenault
getWithPreallocatedType(LLVMContext & Context,Type * Ty)1983b0450acSArthur Eubanks Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
1993b0450acSArthur Eubanks return get(Context, Preallocated, Ty);
2003b0450acSArthur Eubanks }
2013b0450acSArthur Eubanks
getWithInAllocaType(LLVMContext & Context,Type * Ty)2029a0c9402SMatt Arsenault Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
2039a0c9402SMatt Arsenault return get(Context, InAlloca, Ty);
2049a0c9402SMatt Arsenault }
2059a0c9402SMatt Arsenault
getWithUWTableKind(LLVMContext & Context,UWTableKind Kind)2066398903aSMomchil Velikov Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
2076398903aSMomchil Velikov UWTableKind Kind) {
2086398903aSMomchil Velikov return get(Context, UWTable, uint64_t(Kind));
2096398903aSMomchil Velikov }
2106398903aSMomchil Velikov
211278199f6SGeorge Burgess IV Attribute
getWithAllocSizeArgs(LLVMContext & Context,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)212278199f6SGeorge Burgess IV Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
213278199f6SGeorge Burgess IV const Optional<unsigned> &NumElemsArg) {
214278199f6SGeorge Burgess IV assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
215278199f6SGeorge Burgess IV "Invalid allocsize arguments -- given allocsize(0, 0)");
216278199f6SGeorge Burgess IV return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
217278199f6SGeorge Burgess IV }
218278199f6SGeorge Burgess IV
getWithVScaleRangeArgs(LLVMContext & Context,unsigned MinValue,unsigned MaxValue)21948f5a392SBradley Smith Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
22048f5a392SBradley Smith unsigned MinValue,
22148f5a392SBradley Smith unsigned MaxValue) {
22248f5a392SBradley Smith return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
22348f5a392SBradley Smith }
22448f5a392SBradley Smith
getAttrKindFromName(StringRef AttrName)225a7bbe45aSTyker Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
226a7bbe45aSTyker return StringSwitch<Attribute::AttrKind>(AttrName)
227a7bbe45aSTyker #define GET_ATTR_NAMES
228a7bbe45aSTyker #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
229a7bbe45aSTyker .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
230a7bbe45aSTyker #include "llvm/IR/Attributes.inc"
231a7bbe45aSTyker .Default(Attribute::None);
232a7bbe45aSTyker }
233a7bbe45aSTyker
getNameFromAttrKind(Attribute::AttrKind AttrKind)234a7bbe45aSTyker StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
235a7bbe45aSTyker switch (AttrKind) {
236a7bbe45aSTyker #define GET_ATTR_NAMES
237a7bbe45aSTyker #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
238a7bbe45aSTyker case Attribute::ENUM_NAME: \
239a7bbe45aSTyker return #DISPLAY_NAME;
240a7bbe45aSTyker #include "llvm/IR/Attributes.inc"
241a7bbe45aSTyker case Attribute::None:
242a7bbe45aSTyker return "none";
243a7bbe45aSTyker default:
244a7bbe45aSTyker llvm_unreachable("invalid Kind");
245a7bbe45aSTyker }
246a7bbe45aSTyker }
247a7bbe45aSTyker
isExistingAttribute(StringRef Name)24870c0a967STyker bool Attribute::isExistingAttribute(StringRef Name) {
24970c0a967STyker return StringSwitch<bool>(Name)
25070c0a967STyker #define GET_ATTR_NAMES
25170c0a967STyker #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
25270c0a967STyker #include "llvm/IR/Attributes.inc"
25370c0a967STyker .Default(false);
25470c0a967STyker }
25570c0a967STyker
2567707c5a9SBill Wendling //===----------------------------------------------------------------------===//
2577707c5a9SBill Wendling // Attribute Accessor Methods
2587707c5a9SBill Wendling //===----------------------------------------------------------------------===//
2597707c5a9SBill Wendling
isEnumAttribute() const2603f12ac21SBill Wendling bool Attribute::isEnumAttribute() const {
2613f12ac21SBill Wendling return pImpl && pImpl->isEnumAttribute();
2623f12ac21SBill Wendling }
2633f12ac21SBill Wendling
isIntAttribute() const264e15442c8SHal Finkel bool Attribute::isIntAttribute() const {
265e15442c8SHal Finkel return pImpl && pImpl->isIntAttribute();
2663f12ac21SBill Wendling }
2673f12ac21SBill Wendling
isStringAttribute() const2683f12ac21SBill Wendling bool Attribute::isStringAttribute() const {
2693f12ac21SBill Wendling return pImpl && pImpl->isStringAttribute();
2703f12ac21SBill Wendling }
2713f12ac21SBill Wendling
isTypeAttribute() const272b7141207STim Northover bool Attribute::isTypeAttribute() const {
273b7141207STim Northover return pImpl && pImpl->isTypeAttribute();
274b7141207STim Northover }
275b7141207STim Northover
getKindAsEnum() const2763f12ac21SBill Wendling Attribute::AttrKind Attribute::getKindAsEnum() const {
277440e9d81SBill Wendling if (!pImpl) return None;
278b7141207STim Northover assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
2793f12ac21SBill Wendling "Invalid attribute type to get the kind as an enum!");
280500d3039SGeorge Burgess IV return pImpl->getKindAsEnum();
2813f12ac21SBill Wendling }
2823f12ac21SBill Wendling
getValueAsInt() const2833f12ac21SBill Wendling uint64_t Attribute::getValueAsInt() const {
284440e9d81SBill Wendling if (!pImpl) return 0;
285e15442c8SHal Finkel assert(isIntAttribute() &&
286e15442c8SHal Finkel "Expected the attribute to be an integer attribute!");
287500d3039SGeorge Burgess IV return pImpl->getValueAsInt();
2883f12ac21SBill Wendling }
2893f12ac21SBill Wendling
getValueAsBool() const290d6de1e1aSSerge Guelton bool Attribute::getValueAsBool() const {
291d6de1e1aSSerge Guelton if (!pImpl) return false;
292d6de1e1aSSerge Guelton assert(isStringAttribute() &&
293d6de1e1aSSerge Guelton "Expected the attribute to be a string attribute!");
294d6de1e1aSSerge Guelton return pImpl->getValueAsBool();
295d6de1e1aSSerge Guelton }
296d6de1e1aSSerge Guelton
getKindAsString() const2973f12ac21SBill Wendling StringRef Attribute::getKindAsString() const {
2987fb5d41eSEugene Zelenko if (!pImpl) return {};
2993f12ac21SBill Wendling assert(isStringAttribute() &&
3003f12ac21SBill Wendling "Invalid attribute type to get the kind as a string!");
301500d3039SGeorge Burgess IV return pImpl->getKindAsString();
3023f12ac21SBill Wendling }
3033f12ac21SBill Wendling
getValueAsString() const3043f12ac21SBill Wendling StringRef Attribute::getValueAsString() const {
3057fb5d41eSEugene Zelenko if (!pImpl) return {};
3063f12ac21SBill Wendling assert(isStringAttribute() &&
3073f12ac21SBill Wendling "Invalid attribute type to get the value as a string!");
308500d3039SGeorge Burgess IV return pImpl->getValueAsString();
3093f12ac21SBill Wendling }
3103f12ac21SBill Wendling
getValueAsType() const311b7141207STim Northover Type *Attribute::getValueAsType() const {
312b7141207STim Northover if (!pImpl) return {};
313b7141207STim Northover assert(isTypeAttribute() &&
314b7141207STim Northover "Invalid attribute type to get the value as a type!");
315b7141207STim Northover return pImpl->getValueAsType();
316b7141207STim Northover }
317b7141207STim Northover
318b7141207STim Northover
hasAttribute(AttrKind Kind) const319ae89a0fbSBill Wendling bool Attribute::hasAttribute(AttrKind Kind) const {
320ae89a0fbSBill Wendling return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
321ae89a0fbSBill Wendling }
322ae89a0fbSBill Wendling
hasAttribute(StringRef Kind) const323ae89a0fbSBill Wendling bool Attribute::hasAttribute(StringRef Kind) const {
324ae89a0fbSBill Wendling if (!isStringAttribute()) return false;
325ae89a0fbSBill Wendling return pImpl && pImpl->hasAttribute(Kind);
32603eefb3aSBill Wendling }
32703eefb3aSBill Wendling
getAlignment() const32817f5d2b1SGuillaume Chatelet MaybeAlign Attribute::getAlignment() const {
329c79cdff1SBill Wendling assert(hasAttribute(Attribute::Alignment) &&
330c79cdff1SBill Wendling "Trying to get alignment from non-alignment attribute!");
33117f5d2b1SGuillaume Chatelet return MaybeAlign(pImpl->getValueAsInt());
332ef860a24SChandler Carruth }
333ef860a24SChandler Carruth
getStackAlignment() const33417f5d2b1SGuillaume Chatelet MaybeAlign Attribute::getStackAlignment() const {
335c79cdff1SBill Wendling assert(hasAttribute(Attribute::StackAlignment) &&
336c79cdff1SBill Wendling "Trying to get alignment from non-alignment attribute!");
33717f5d2b1SGuillaume Chatelet return MaybeAlign(pImpl->getValueAsInt());
338ef860a24SChandler Carruth }
339ef860a24SChandler Carruth
getDereferenceableBytes() const340b0407ba0SHal Finkel uint64_t Attribute::getDereferenceableBytes() const {
341b0407ba0SHal Finkel assert(hasAttribute(Attribute::Dereferenceable) &&
342b0407ba0SHal Finkel "Trying to get dereferenceable bytes from "
343b0407ba0SHal Finkel "non-dereferenceable attribute!");
344b0407ba0SHal Finkel return pImpl->getValueAsInt();
345b0407ba0SHal Finkel }
346b0407ba0SHal Finkel
getDereferenceableOrNullBytes() const34731ea6d15SSanjoy Das uint64_t Attribute::getDereferenceableOrNullBytes() const {
34831ea6d15SSanjoy Das assert(hasAttribute(Attribute::DereferenceableOrNull) &&
34931ea6d15SSanjoy Das "Trying to get dereferenceable bytes from "
35031ea6d15SSanjoy Das "non-dereferenceable attribute!");
35131ea6d15SSanjoy Das return pImpl->getValueAsInt();
35231ea6d15SSanjoy Das }
35331ea6d15SSanjoy Das
getAllocSizeArgs() const354278199f6SGeorge Burgess IV std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
355278199f6SGeorge Burgess IV assert(hasAttribute(Attribute::AllocSize) &&
356278199f6SGeorge Burgess IV "Trying to get allocsize args from non-allocsize attribute");
357278199f6SGeorge Burgess IV return unpackAllocSizeArgs(pImpl->getValueAsInt());
358278199f6SGeorge Burgess IV }
359278199f6SGeorge Burgess IV
getVScaleRangeMin() const3600395e015SCullen Rhodes unsigned Attribute::getVScaleRangeMin() const {
36148f5a392SBradley Smith assert(hasAttribute(Attribute::VScaleRange) &&
36248f5a392SBradley Smith "Trying to get vscale args from non-vscale attribute");
3630395e015SCullen Rhodes return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
3640395e015SCullen Rhodes }
3650395e015SCullen Rhodes
getVScaleRangeMax() const3660395e015SCullen Rhodes Optional<unsigned> Attribute::getVScaleRangeMax() const {
3670395e015SCullen Rhodes assert(hasAttribute(Attribute::VScaleRange) &&
3680395e015SCullen Rhodes "Trying to get vscale args from non-vscale attribute");
3690395e015SCullen Rhodes return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
37048f5a392SBradley Smith }
37148f5a392SBradley Smith
getUWTableKind() const3726398903aSMomchil Velikov UWTableKind Attribute::getUWTableKind() const {
3736398903aSMomchil Velikov assert(hasAttribute(Attribute::UWTable) &&
3746398903aSMomchil Velikov "Trying to get unwind table kind from non-uwtable attribute");
3756398903aSMomchil Velikov return UWTableKind(pImpl->getValueAsInt());
3766398903aSMomchil Velikov }
3776398903aSMomchil Velikov
getAllocKind() const37842861faaSAugie Fackler AllocFnKind Attribute::getAllocKind() const {
37942861faaSAugie Fackler assert(hasAttribute(Attribute::AllocKind) &&
38042861faaSAugie Fackler "Trying to get allockind value from non-allockind attribute");
38142861faaSAugie Fackler return AllocFnKind(pImpl->getValueAsInt());
38242861faaSAugie Fackler }
38342861faaSAugie Fackler
getAsString(bool InAttrGrp) const384829b4789SBill Wendling std::string Attribute::getAsString(bool InAttrGrp) const {
3857fb5d41eSEugene Zelenko if (!pImpl) return {};
3869c2eba95SBill Wendling
387e000b848SNikita Popov if (isEnumAttribute())
388e000b848SNikita Popov return getNameFromAttrKind(getKindAsEnum()).str();
3899c2eba95SBill Wendling
3909a0c9402SMatt Arsenault if (isTypeAttribute()) {
391e000b848SNikita Popov std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
3923b0450acSArthur Eubanks Result += '(';
393e000b848SNikita Popov raw_string_ostream OS(Result);
3943b0450acSArthur Eubanks getValueAsType()->print(OS, false, true);
3953b0450acSArthur Eubanks OS.flush();
3963b0450acSArthur Eubanks Result += ')';
3973b0450acSArthur Eubanks return Result;
3983b0450acSArthur Eubanks }
3993b0450acSArthur Eubanks
4009c2eba95SBill Wendling // FIXME: These should be output like this:
4019c2eba95SBill Wendling //
4029c2eba95SBill Wendling // align=4
4039c2eba95SBill Wendling // alignstack=8
4049c2eba95SBill Wendling //
4055a90b1e4SMomchil Velikov if (hasAttribute(Attribute::Alignment))
4065a90b1e4SMomchil Velikov return (InAttrGrp ? "align=" + Twine(getValueAsInt())
4075a90b1e4SMomchil Velikov : "align " + Twine(getValueAsInt()))
4085a90b1e4SMomchil Velikov .str();
409829b4789SBill Wendling
41031ea6d15SSanjoy Das auto AttrWithBytesToString = [&](const char *Name) {
4115a90b1e4SMomchil Velikov return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
4125a90b1e4SMomchil Velikov : Name + ("(" + Twine(getValueAsInt())) + ")")
4135a90b1e4SMomchil Velikov .str();
41431ea6d15SSanjoy Das };
4159c2eba95SBill Wendling
41631ea6d15SSanjoy Das if (hasAttribute(Attribute::StackAlignment))
41731ea6d15SSanjoy Das return AttrWithBytesToString("alignstack");
41831ea6d15SSanjoy Das
41931ea6d15SSanjoy Das if (hasAttribute(Attribute::Dereferenceable))
42031ea6d15SSanjoy Das return AttrWithBytesToString("dereferenceable");
42131ea6d15SSanjoy Das
42231ea6d15SSanjoy Das if (hasAttribute(Attribute::DereferenceableOrNull))
42331ea6d15SSanjoy Das return AttrWithBytesToString("dereferenceable_or_null");
424b0407ba0SHal Finkel
425278199f6SGeorge Burgess IV if (hasAttribute(Attribute::AllocSize)) {
426278199f6SGeorge Burgess IV unsigned ElemSize;
427278199f6SGeorge Burgess IV Optional<unsigned> NumElems;
428278199f6SGeorge Burgess IV std::tie(ElemSize, NumElems) = getAllocSizeArgs();
429278199f6SGeorge Burgess IV
4305a90b1e4SMomchil Velikov return (NumElems
4315a90b1e4SMomchil Velikov ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
4325a90b1e4SMomchil Velikov : "allocsize(" + Twine(ElemSize) + ")")
4335a90b1e4SMomchil Velikov .str();
434278199f6SGeorge Burgess IV }
435278199f6SGeorge Burgess IV
43648f5a392SBradley Smith if (hasAttribute(Attribute::VScaleRange)) {
4370395e015SCullen Rhodes unsigned MinValue = getVScaleRangeMin();
4380395e015SCullen Rhodes Optional<unsigned> MaxValue = getVScaleRangeMax();
4395a90b1e4SMomchil Velikov return ("vscale_range(" + Twine(MinValue) + "," +
440129b531cSKazu Hirata Twine(MaxValue.value_or(0)) + ")")
4415a90b1e4SMomchil Velikov .str();
44248f5a392SBradley Smith }
44348f5a392SBradley Smith
4446398903aSMomchil Velikov if (hasAttribute(Attribute::UWTable)) {
4456398903aSMomchil Velikov UWTableKind Kind = getUWTableKind();
4466398903aSMomchil Velikov if (Kind != UWTableKind::None) {
4476398903aSMomchil Velikov return Kind == UWTableKind::Default
4486398903aSMomchil Velikov ? "uwtable"
4496398903aSMomchil Velikov : ("uwtable(" +
4506398903aSMomchil Velikov Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
4516398903aSMomchil Velikov .str();
4526398903aSMomchil Velikov }
4536398903aSMomchil Velikov }
4546398903aSMomchil Velikov
45542861faaSAugie Fackler if (hasAttribute(Attribute::AllocKind)) {
45642861faaSAugie Fackler AllocFnKind Kind = getAllocKind();
45742861faaSAugie Fackler SmallVector<StringRef> parts;
45842861faaSAugie Fackler if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
45942861faaSAugie Fackler parts.push_back("alloc");
46042861faaSAugie Fackler if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
46142861faaSAugie Fackler parts.push_back("realloc");
46242861faaSAugie Fackler if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
46342861faaSAugie Fackler parts.push_back("free");
46442861faaSAugie Fackler if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
46542861faaSAugie Fackler parts.push_back("uninitialized");
46642861faaSAugie Fackler if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
46742861faaSAugie Fackler parts.push_back("zeroed");
46842861faaSAugie Fackler if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
46942861faaSAugie Fackler parts.push_back("aligned");
47042861faaSAugie Fackler return ("allockind(\"" +
47142861faaSAugie Fackler Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
47242861faaSAugie Fackler .str();
47342861faaSAugie Fackler }
47442861faaSAugie Fackler
4759c2eba95SBill Wendling // Convert target-dependent attributes to strings of the form:
4769c2eba95SBill Wendling //
4779c2eba95SBill Wendling // "kind"
4789c2eba95SBill Wendling // "kind" = "value"
4799c2eba95SBill Wendling //
4803f12ac21SBill Wendling if (isStringAttribute()) {
4819c2eba95SBill Wendling std::string Result;
4829eb6a102SHonggyu Kim {
4839eb6a102SHonggyu Kim raw_string_ostream OS(Result);
484d93ad3aeSBenjamin Kramer OS << '"' << getKindAsString() << '"';
485d93ad3aeSBenjamin Kramer
486d93ad3aeSBenjamin Kramer // Since some attribute strings contain special characters that cannot be
487d93ad3aeSBenjamin Kramer // printable, those have to be escaped to make the attribute value
488d93ad3aeSBenjamin Kramer // printable as is. e.g. "\01__gnu_mcount_nc"
489d93ad3aeSBenjamin Kramer const auto &AttrVal = pImpl->getValueAsString();
490d93ad3aeSBenjamin Kramer if (!AttrVal.empty()) {
4919eb6a102SHonggyu Kim OS << "=\"";
492745918ffSJonas Devlieghere printEscapedString(AttrVal, OS);
4939eb6a102SHonggyu Kim OS << "\"";
4949eb6a102SHonggyu Kim }
495d93ad3aeSBenjamin Kramer }
496c79cdff1SBill Wendling return Result;
4979c2eba95SBill Wendling }
498f2955aa3SBill Wendling
499f2955aa3SBill Wendling llvm_unreachable("Unknown attribute");
500ef860a24SChandler Carruth }
501ef860a24SChandler Carruth
hasParentContext(LLVMContext & C) const502244d9d6eSNick Lewycky bool Attribute::hasParentContext(LLVMContext &C) const {
503244d9d6eSNick Lewycky assert(isValid() && "invalid Attribute doesn't refer to any context");
504244d9d6eSNick Lewycky FoldingSetNodeID ID;
505244d9d6eSNick Lewycky pImpl->Profile(ID);
506244d9d6eSNick Lewycky void *Unused;
507244d9d6eSNick Lewycky return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
508244d9d6eSNick Lewycky }
509244d9d6eSNick Lewycky
operator <(Attribute A) const510d509a665SBill Wendling bool Attribute::operator<(Attribute A) const {
511d509a665SBill Wendling if (!pImpl && !A.pImpl) return false;
512d509a665SBill Wendling if (!pImpl) return true;
513d509a665SBill Wendling if (!A.pImpl) return false;
514d509a665SBill Wendling return *pImpl < *A.pImpl;
515d509a665SBill Wendling }
516d509a665SBill Wendling
Profile(FoldingSetNodeID & ID) const517423e3db6SReid Kleckner void Attribute::Profile(FoldingSetNodeID &ID) const {
518423e3db6SReid Kleckner ID.AddPointer(pImpl);
519423e3db6SReid Kleckner }
520423e3db6SReid Kleckner
5217ed3e878SNikita Popov enum AttributeProperty {
5227ed3e878SNikita Popov FnAttr = (1 << 0),
5237ed3e878SNikita Popov ParamAttr = (1 << 1),
5247ed3e878SNikita Popov RetAttr = (1 << 2),
5257ed3e878SNikita Popov };
5267ed3e878SNikita Popov
5277ed3e878SNikita Popov #define GET_ATTR_PROP_TABLE
5287ed3e878SNikita Popov #include "llvm/IR/Attributes.inc"
5297ed3e878SNikita Popov
hasAttributeProperty(Attribute::AttrKind Kind,AttributeProperty Prop)5307ed3e878SNikita Popov static bool hasAttributeProperty(Attribute::AttrKind Kind,
5317ed3e878SNikita Popov AttributeProperty Prop) {
5327ed3e878SNikita Popov unsigned Index = Kind - 1;
5337ed3e878SNikita Popov assert(Index < sizeof(AttrPropTable) / sizeof(AttrPropTable[0]) &&
5347ed3e878SNikita Popov "Invalid attribute kind");
5357ed3e878SNikita Popov return AttrPropTable[Index] & Prop;
5367ed3e878SNikita Popov }
5377ed3e878SNikita Popov
canUseAsFnAttr(AttrKind Kind)5387ed3e878SNikita Popov bool Attribute::canUseAsFnAttr(AttrKind Kind) {
5397ed3e878SNikita Popov return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
5407ed3e878SNikita Popov }
5417ed3e878SNikita Popov
canUseAsParamAttr(AttrKind Kind)5427ed3e878SNikita Popov bool Attribute::canUseAsParamAttr(AttrKind Kind) {
5437ed3e878SNikita Popov return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
5447ed3e878SNikita Popov }
5457ed3e878SNikita Popov
canUseAsRetAttr(AttrKind Kind)5467ed3e878SNikita Popov bool Attribute::canUseAsRetAttr(AttrKind Kind) {
5477ed3e878SNikita Popov return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
5487ed3e878SNikita Popov }
5497ed3e878SNikita Popov
550d509a665SBill Wendling //===----------------------------------------------------------------------===//
551d509a665SBill Wendling // AttributeImpl Definition
552d509a665SBill Wendling //===----------------------------------------------------------------------===//
553d509a665SBill Wendling
hasAttribute(Attribute::AttrKind A) const554d509a665SBill Wendling bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
5553f12ac21SBill Wendling if (isStringAttribute()) return false;
5563f12ac21SBill Wendling return getKindAsEnum() == A;
557d509a665SBill Wendling }
558d509a665SBill Wendling
hasAttribute(StringRef Kind) const5593f12ac21SBill Wendling bool AttributeImpl::hasAttribute(StringRef Kind) const {
5603f12ac21SBill Wendling if (!isStringAttribute()) return false;
5613f12ac21SBill Wendling return getKindAsString() == Kind;
562d509a665SBill Wendling }
563d509a665SBill Wendling
getKindAsEnum() const5643f12ac21SBill Wendling Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
565b7141207STim Northover assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
566741146b8SBenjamin Kramer return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
567d509a665SBill Wendling }
568d509a665SBill Wendling
getValueAsInt() const5693f12ac21SBill Wendling uint64_t AttributeImpl::getValueAsInt() const {
570e15442c8SHal Finkel assert(isIntAttribute());
571e15442c8SHal Finkel return static_cast<const IntAttributeImpl *>(this)->getValue();
572d509a665SBill Wendling }
573d509a665SBill Wendling
getValueAsBool() const574d6de1e1aSSerge Guelton bool AttributeImpl::getValueAsBool() const {
575d6de1e1aSSerge Guelton assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
576d6de1e1aSSerge Guelton return getValueAsString() == "true";
577d6de1e1aSSerge Guelton }
578d6de1e1aSSerge Guelton
getKindAsString() const5793f12ac21SBill Wendling StringRef AttributeImpl::getKindAsString() const {
580741146b8SBenjamin Kramer assert(isStringAttribute());
581741146b8SBenjamin Kramer return static_cast<const StringAttributeImpl *>(this)->getStringKind();
582d509a665SBill Wendling }
583d509a665SBill Wendling
getValueAsString() const5843f12ac21SBill Wendling StringRef AttributeImpl::getValueAsString() const {
585741146b8SBenjamin Kramer assert(isStringAttribute());
586741146b8SBenjamin Kramer return static_cast<const StringAttributeImpl *>(this)->getStringValue();
587d509a665SBill Wendling }
588d509a665SBill Wendling
getValueAsType() const589b7141207STim Northover Type *AttributeImpl::getValueAsType() const {
590b7141207STim Northover assert(isTypeAttribute());
591b7141207STim Northover return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
592b7141207STim Northover }
593b7141207STim Northover
operator <(const AttributeImpl & AI) const594d509a665SBill Wendling bool AttributeImpl::operator<(const AttributeImpl &AI) const {
59538909f31SDanila Malyutin if (this == &AI)
59638909f31SDanila Malyutin return false;
597363e12aeSNikita Popov
598c79cdff1SBill Wendling // This sorts the attributes with Attribute::AttrKinds coming first (sorted
599c79cdff1SBill Wendling // relative to their enum value) and then strings.
600363e12aeSNikita Popov if (!isStringAttribute()) {
601363e12aeSNikita Popov if (AI.isStringAttribute())
602363e12aeSNikita Popov return true;
603363e12aeSNikita Popov if (getKindAsEnum() != AI.getKindAsEnum())
604b7141207STim Northover return getKindAsEnum() < AI.getKindAsEnum();
605363e12aeSNikita Popov assert(!AI.isEnumAttribute() && "Non-unique attribute");
606363e12aeSNikita Popov assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
607363e12aeSNikita Popov // TODO: Is this actually needed?
608363e12aeSNikita Popov assert(AI.isIntAttribute() && "Only possibility left");
6097de67615SReid Kleckner return getValueAsInt() < AI.getValueAsInt();
6103f12ac21SBill Wendling }
611d509a665SBill Wendling
612363e12aeSNikita Popov if (!AI.isStringAttribute())
613363e12aeSNikita Popov return false;
6143f12ac21SBill Wendling if (getKindAsString() == AI.getKindAsString())
6153f12ac21SBill Wendling return getValueAsString() < AI.getValueAsString();
61626b95756SBill Wendling return getKindAsString() < AI.getKindAsString();
617d509a665SBill Wendling }
618d509a665SBill Wendling
619d509a665SBill Wendling //===----------------------------------------------------------------------===//
620c2cb5600SReid Kleckner // AttributeSet Definition
621c2cb5600SReid Kleckner //===----------------------------------------------------------------------===//
622c2cb5600SReid Kleckner
get(LLVMContext & C,const AttrBuilder & B)623c2cb5600SReid Kleckner AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
624c2cb5600SReid Kleckner return AttributeSet(AttributeSetNode::get(C, B));
625c2cb5600SReid Kleckner }
626c2cb5600SReid Kleckner
get(LLVMContext & C,ArrayRef<Attribute> Attrs)627c2cb5600SReid Kleckner AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
628c2cb5600SReid Kleckner return AttributeSet(AttributeSetNode::get(C, Attrs));
629c2cb5600SReid Kleckner }
630c2cb5600SReid Kleckner
addAttribute(LLVMContext & C,Attribute::AttrKind Kind) const631f3d7904dSJaved Absar AttributeSet AttributeSet::addAttribute(LLVMContext &C,
632f3d7904dSJaved Absar Attribute::AttrKind Kind) const {
633f3d7904dSJaved Absar if (hasAttribute(Kind)) return *this;
634d2cc6c2dSSerge Guelton AttrBuilder B(C);
635f3d7904dSJaved Absar B.addAttribute(Kind);
636f3d7904dSJaved Absar return addAttributes(C, AttributeSet::get(C, B));
637f3d7904dSJaved Absar }
638f3d7904dSJaved Absar
addAttribute(LLVMContext & C,StringRef Kind,StringRef Value) const639f3d7904dSJaved Absar AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
640f3d7904dSJaved Absar StringRef Value) const {
641d2cc6c2dSSerge Guelton AttrBuilder B(C);
642f3d7904dSJaved Absar B.addAttribute(Kind, Value);
643f3d7904dSJaved Absar return addAttributes(C, AttributeSet::get(C, B));
644f3d7904dSJaved Absar }
645f3d7904dSJaved Absar
addAttributes(LLVMContext & C,const AttributeSet AS) const646f3d7904dSJaved Absar AttributeSet AttributeSet::addAttributes(LLVMContext &C,
647f3d7904dSJaved Absar const AttributeSet AS) const {
648f3d7904dSJaved Absar if (!hasAttributes())
649f3d7904dSJaved Absar return AS;
650f3d7904dSJaved Absar
651f3d7904dSJaved Absar if (!AS.hasAttributes())
652f3d7904dSJaved Absar return *this;
653f3d7904dSJaved Absar
654da61cb01SNikita Popov AttrBuilder B(C, *this);
655da61cb01SNikita Popov B.merge(AttrBuilder(C, AS));
656f3d7904dSJaved Absar return get(C, B);
657f3d7904dSJaved Absar }
658f3d7904dSJaved Absar
removeAttribute(LLVMContext & C,Attribute::AttrKind Kind) const659f3d7904dSJaved Absar AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
660f3d7904dSJaved Absar Attribute::AttrKind Kind) const {
661f3d7904dSJaved Absar if (!hasAttribute(Kind)) return *this;
662d2cc6c2dSSerge Guelton AttrBuilder B(C, *this);
66388dddb89SDaniel Neilson B.removeAttribute(Kind);
66488dddb89SDaniel Neilson return get(C, B);
665f3d7904dSJaved Absar }
666f3d7904dSJaved Absar
removeAttribute(LLVMContext & C,StringRef Kind) const667f3d7904dSJaved Absar AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
668f3d7904dSJaved Absar StringRef Kind) const {
669f3d7904dSJaved Absar if (!hasAttribute(Kind)) return *this;
670d2cc6c2dSSerge Guelton AttrBuilder B(C, *this);
67188dddb89SDaniel Neilson B.removeAttribute(Kind);
67288dddb89SDaniel Neilson return get(C, B);
673f3d7904dSJaved Absar }
674f3d7904dSJaved Absar
removeAttributes(LLVMContext & C,const AttributeMask & Attrs) const675f3d7904dSJaved Absar AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
6769290ccc3Sserge-sans-paille const AttributeMask &Attrs) const {
677d2cc6c2dSSerge Guelton AttrBuilder B(C, *this);
678fd46ed3fSNikita Popov // If there is nothing to remove, directly return the original set.
679fd46ed3fSNikita Popov if (!B.overlaps(Attrs))
680fd46ed3fSNikita Popov return *this;
681fd46ed3fSNikita Popov
682f3d7904dSJaved Absar B.remove(Attrs);
683f3d7904dSJaved Absar return get(C, B);
684f3d7904dSJaved Absar }
685f3d7904dSJaved Absar
getNumAttributes() const686c2cb5600SReid Kleckner unsigned AttributeSet::getNumAttributes() const {
687c2cb5600SReid Kleckner return SetNode ? SetNode->getNumAttributes() : 0;
688c2cb5600SReid Kleckner }
689c2cb5600SReid Kleckner
hasAttribute(Attribute::AttrKind Kind) const690c2cb5600SReid Kleckner bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
691d761e2c2SEugene Zelenko return SetNode ? SetNode->hasAttribute(Kind) : false;
692c2cb5600SReid Kleckner }
693c2cb5600SReid Kleckner
hasAttribute(StringRef Kind) const694c2cb5600SReid Kleckner bool AttributeSet::hasAttribute(StringRef Kind) const {
695d761e2c2SEugene Zelenko return SetNode ? SetNode->hasAttribute(Kind) : false;
696c2cb5600SReid Kleckner }
697c2cb5600SReid Kleckner
getAttribute(Attribute::AttrKind Kind) const698c2cb5600SReid Kleckner Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
699c2cb5600SReid Kleckner return SetNode ? SetNode->getAttribute(Kind) : Attribute();
700c2cb5600SReid Kleckner }
701c2cb5600SReid Kleckner
getAttribute(StringRef Kind) const702c2cb5600SReid Kleckner Attribute AttributeSet::getAttribute(StringRef Kind) const {
703c2cb5600SReid Kleckner return SetNode ? SetNode->getAttribute(Kind) : Attribute();
704c2cb5600SReid Kleckner }
705c2cb5600SReid Kleckner
getAlignment() const70617f5d2b1SGuillaume Chatelet MaybeAlign AttributeSet::getAlignment() const {
70717f5d2b1SGuillaume Chatelet return SetNode ? SetNode->getAlignment() : None;
708c2cb5600SReid Kleckner }
709c2cb5600SReid Kleckner
getStackAlignment() const71017f5d2b1SGuillaume Chatelet MaybeAlign AttributeSet::getStackAlignment() const {
71117f5d2b1SGuillaume Chatelet return SetNode ? SetNode->getStackAlignment() : None;
712c2cb5600SReid Kleckner }
713c2cb5600SReid Kleckner
getDereferenceableBytes() const714c2cb5600SReid Kleckner uint64_t AttributeSet::getDereferenceableBytes() const {
715c2cb5600SReid Kleckner return SetNode ? SetNode->getDereferenceableBytes() : 0;
716c2cb5600SReid Kleckner }
717c2cb5600SReid Kleckner
getDereferenceableOrNullBytes() const718c2cb5600SReid Kleckner uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
719c2cb5600SReid Kleckner return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
720c2cb5600SReid Kleckner }
721c2cb5600SReid Kleckner
getByRefType() const7225e999cbeSMatt Arsenault Type *AttributeSet::getByRefType() const {
723cd88a01cSNikita Popov return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
7245e999cbeSMatt Arsenault }
7255e999cbeSMatt Arsenault
getByValType() const726b7141207STim Northover Type *AttributeSet::getByValType() const {
727cd88a01cSNikita Popov return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
728b7141207STim Northover }
729b7141207STim Northover
getStructRetType() const7300a7cd99aSMatt Arsenault Type *AttributeSet::getStructRetType() const {
731cd88a01cSNikita Popov return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
7320a7cd99aSMatt Arsenault }
7330a7cd99aSMatt Arsenault
getPreallocatedType() const7343b0450acSArthur Eubanks Type *AttributeSet::getPreallocatedType() const {
735cd88a01cSNikita Popov return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
7363b0450acSArthur Eubanks }
7373b0450acSArthur Eubanks
getInAllocaType() const7389a0c9402SMatt Arsenault Type *AttributeSet::getInAllocaType() const {
739cd88a01cSNikita Popov return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
7409a0c9402SMatt Arsenault }
7419a0c9402SMatt Arsenault
getElementType() const742c191035fSNikita Popov Type *AttributeSet::getElementType() const {
743c191035fSNikita Popov return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
744c191035fSNikita Popov }
745c191035fSNikita Popov
getAllocSizeArgs() const746c2cb5600SReid Kleckner std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
7476df95b7cSKonstantin Zhuravlyov return SetNode ? SetNode->getAllocSizeArgs()
7486df95b7cSKonstantin Zhuravlyov : std::pair<unsigned, Optional<unsigned>>(0, 0);
749c2cb5600SReid Kleckner }
750c2cb5600SReid Kleckner
getVScaleRangeMin() const7510395e015SCullen Rhodes unsigned AttributeSet::getVScaleRangeMin() const {
7520395e015SCullen Rhodes return SetNode ? SetNode->getVScaleRangeMin() : 1;
7530395e015SCullen Rhodes }
7540395e015SCullen Rhodes
getVScaleRangeMax() const7550395e015SCullen Rhodes Optional<unsigned> AttributeSet::getVScaleRangeMax() const {
7560395e015SCullen Rhodes return SetNode ? SetNode->getVScaleRangeMax() : None;
75748f5a392SBradley Smith }
75848f5a392SBradley Smith
getUWTableKind() const7596398903aSMomchil Velikov UWTableKind AttributeSet::getUWTableKind() const {
7606398903aSMomchil Velikov return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
7616398903aSMomchil Velikov }
7626398903aSMomchil Velikov
getAllocKind() const76342861faaSAugie Fackler AllocFnKind AttributeSet::getAllocKind() const {
76442861faaSAugie Fackler return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
76542861faaSAugie Fackler }
76642861faaSAugie Fackler
getAsString(bool InAttrGrp) const767c2cb5600SReid Kleckner std::string AttributeSet::getAsString(bool InAttrGrp) const {
768c2cb5600SReid Kleckner return SetNode ? SetNode->getAsString(InAttrGrp) : "";
769c2cb5600SReid Kleckner }
770c2cb5600SReid Kleckner
hasParentContext(LLVMContext & C) const771244d9d6eSNick Lewycky bool AttributeSet::hasParentContext(LLVMContext &C) const {
772244d9d6eSNick Lewycky assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
773244d9d6eSNick Lewycky FoldingSetNodeID ID;
774244d9d6eSNick Lewycky SetNode->Profile(ID);
775244d9d6eSNick Lewycky void *Unused;
776244d9d6eSNick Lewycky return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
777244d9d6eSNick Lewycky }
778244d9d6eSNick Lewycky
begin() const779c2cb5600SReid Kleckner AttributeSet::iterator AttributeSet::begin() const {
780c2cb5600SReid Kleckner return SetNode ? SetNode->begin() : nullptr;
781c2cb5600SReid Kleckner }
782c2cb5600SReid Kleckner
end() const783c2cb5600SReid Kleckner AttributeSet::iterator AttributeSet::end() const {
784c2cb5600SReid Kleckner return SetNode ? SetNode->end() : nullptr;
785c2cb5600SReid Kleckner }
786c2cb5600SReid Kleckner
787615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const788f3d7904dSJaved Absar LLVM_DUMP_METHOD void AttributeSet::dump() const {
789f3d7904dSJaved Absar dbgs() << "AS =\n";
790f3d7904dSJaved Absar dbgs() << " { ";
791f3d7904dSJaved Absar dbgs() << getAsString(true) << " }\n";
792f3d7904dSJaved Absar }
793f3d7904dSJaved Absar #endif
794f3d7904dSJaved Absar
795c2cb5600SReid Kleckner //===----------------------------------------------------------------------===//
796d509a665SBill Wendling // AttributeSetNode Definition
797d509a665SBill Wendling //===----------------------------------------------------------------------===//
798d509a665SBill Wendling
AttributeSetNode(ArrayRef<Attribute> Attrs)7998ff7785eSReid Kleckner AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
80041c22b43SEvgeniy Stepanov : NumAttrs(Attrs.size()) {
8018ff7785eSReid Kleckner // There's memory after the node where we can store the entries in.
80275709329SFangrui Song llvm::copy(Attrs, getTrailingObjects<Attribute>());
8038ff7785eSReid Kleckner
8041a8ff896SMark de Wever for (const auto &I : *this) {
80535651fddSNikita Popov if (I.isStringAttribute())
8068f4c78dcSNikita Popov StringAttrs.insert({ I.getKindAsString(), I });
80735651fddSNikita Popov else
80835651fddSNikita Popov AvailableAttrs.addAttribute(I.getKindAsEnum());
8098ff7785eSReid Kleckner }
8108ff7785eSReid Kleckner }
8118ff7785eSReid Kleckner
get(LLVMContext & C,ArrayRef<Attribute> Attrs)812d509a665SBill Wendling AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
813d509a665SBill Wendling ArrayRef<Attribute> Attrs) {
814ed766f1bSBenjamin Kramer SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
815ed766f1bSBenjamin Kramer llvm::sort(SortedAttrs);
816ed766f1bSBenjamin Kramer return getSorted(C, SortedAttrs);
817ed766f1bSBenjamin Kramer }
818ed766f1bSBenjamin Kramer
getSorted(LLVMContext & C,ArrayRef<Attribute> SortedAttrs)819ed766f1bSBenjamin Kramer AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
820ed766f1bSBenjamin Kramer ArrayRef<Attribute> SortedAttrs) {
821ed766f1bSBenjamin Kramer if (SortedAttrs.empty())
822c620761cSCraig Topper return nullptr;
823d509a665SBill Wendling
824ed766f1bSBenjamin Kramer // Build a key to look up the existing attributes.
825d509a665SBill Wendling LLVMContextImpl *pImpl = C.pImpl;
826d509a665SBill Wendling FoldingSetNodeID ID;
827d509a665SBill Wendling
828ed766f1bSBenjamin Kramer assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
8291a8ff896SMark de Wever for (const auto &Attr : SortedAttrs)
830500d3039SGeorge Burgess IV Attr.Profile(ID);
831d509a665SBill Wendling
832d509a665SBill Wendling void *InsertPoint;
833d509a665SBill Wendling AttributeSetNode *PA =
834d509a665SBill Wendling pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
835d509a665SBill Wendling
836d509a665SBill Wendling // If we didn't find any existing attributes of the same shape then create a
837d509a665SBill Wendling // new one and insert it.
838d509a665SBill Wendling if (!PA) {
839741146b8SBenjamin Kramer // Coallocate entries after the AttributeSetNode itself.
840aa365b2fSJames Y Knight void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
841741146b8SBenjamin Kramer PA = new (Mem) AttributeSetNode(SortedAttrs);
842d509a665SBill Wendling pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
843d509a665SBill Wendling }
844d509a665SBill Wendling
845b518054bSReid Kleckner // Return the AttributeSetNode that we found or created.
846d509a665SBill Wendling return PA;
847d509a665SBill Wendling }
848d509a665SBill Wendling
get(LLVMContext & C,const AttrBuilder & B)849eb9dd5b8SReid Kleckner AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
85042a68215SNikita Popov return getSorted(C, B.attrs());
851eb9dd5b8SReid Kleckner }
852eb9dd5b8SReid Kleckner
hasAttribute(StringRef Kind) const853bce7b97cSBill Wendling bool AttributeSetNode::hasAttribute(StringRef Kind) const {
8548f4c78dcSNikita Popov return StringAttrs.count(Kind);
855bce7b97cSBill Wendling }
856bce7b97cSBill Wendling
857e3306c56SBenjamin Kramer Optional<Attribute>
findEnumAttribute(Attribute::AttrKind Kind) const858e3306c56SBenjamin Kramer AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
859e3306c56SBenjamin Kramer // Do a quick presence check.
860e3306c56SBenjamin Kramer if (!hasAttribute(Kind))
861e3306c56SBenjamin Kramer return None;
862e3306c56SBenjamin Kramer
863e3306c56SBenjamin Kramer // Attributes in a set are sorted by enum value, followed by string
864e3306c56SBenjamin Kramer // attributes. Binary search the one we want.
865e3306c56SBenjamin Kramer const Attribute *I =
866e3306c56SBenjamin Kramer std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
867e3306c56SBenjamin Kramer [](Attribute A, Attribute::AttrKind Kind) {
868e3306c56SBenjamin Kramer return A.getKindAsEnum() < Kind;
869e3306c56SBenjamin Kramer });
870e3306c56SBenjamin Kramer assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
871e3306c56SBenjamin Kramer return *I;
87231eeb76fSMatthias Braun }
873e3306c56SBenjamin Kramer
getAttribute(Attribute::AttrKind Kind) const874e3306c56SBenjamin Kramer Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
875e3306c56SBenjamin Kramer if (auto A = findEnumAttribute(Kind))
876e3306c56SBenjamin Kramer return *A;
8777fb5d41eSEugene Zelenko return {};
878bce7b97cSBill Wendling }
879bce7b97cSBill Wendling
getAttribute(StringRef Kind) const880bce7b97cSBill Wendling Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
8818f4c78dcSNikita Popov return StringAttrs.lookup(Kind);
882bce7b97cSBill Wendling }
883bce7b97cSBill Wendling
getAlignment() const88417f5d2b1SGuillaume Chatelet MaybeAlign AttributeSetNode::getAlignment() const {
885e3306c56SBenjamin Kramer if (auto A = findEnumAttribute(Attribute::Alignment))
886e3306c56SBenjamin Kramer return A->getAlignment();
88717f5d2b1SGuillaume Chatelet return None;
888f2955aa3SBill Wendling }
889f2955aa3SBill Wendling
getStackAlignment() const89017f5d2b1SGuillaume Chatelet MaybeAlign AttributeSetNode::getStackAlignment() const {
891e3306c56SBenjamin Kramer if (auto A = findEnumAttribute(Attribute::StackAlignment))
892e3306c56SBenjamin Kramer return A->getStackAlignment();
89317f5d2b1SGuillaume Chatelet return None;
894f2955aa3SBill Wendling }
895f2955aa3SBill Wendling
getAttributeType(Attribute::AttrKind Kind) const896cd88a01cSNikita Popov Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
897cd88a01cSNikita Popov if (auto A = findEnumAttribute(Kind))
8989a0c9402SMatt Arsenault return A->getValueAsType();
8999a0c9402SMatt Arsenault return nullptr;
9009a0c9402SMatt Arsenault }
9019a0c9402SMatt Arsenault
getDereferenceableBytes() const902b0407ba0SHal Finkel uint64_t AttributeSetNode::getDereferenceableBytes() const {
903e3306c56SBenjamin Kramer if (auto A = findEnumAttribute(Attribute::Dereferenceable))
904e3306c56SBenjamin Kramer return A->getDereferenceableBytes();
905b0407ba0SHal Finkel return 0;
906b0407ba0SHal Finkel }
907b0407ba0SHal Finkel
getDereferenceableOrNullBytes() const90806cf33fbSSanjoy Das uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
909e3306c56SBenjamin Kramer if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
910e3306c56SBenjamin Kramer return A->getDereferenceableOrNullBytes();
91106cf33fbSSanjoy Das return 0;
91206cf33fbSSanjoy Das }
91306cf33fbSSanjoy Das
914278199f6SGeorge Burgess IV std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs() const915278199f6SGeorge Burgess IV AttributeSetNode::getAllocSizeArgs() const {
916e3306c56SBenjamin Kramer if (auto A = findEnumAttribute(Attribute::AllocSize))
917e3306c56SBenjamin Kramer return A->getAllocSizeArgs();
918278199f6SGeorge Burgess IV return std::make_pair(0, 0);
919278199f6SGeorge Burgess IV }
920278199f6SGeorge Burgess IV
getVScaleRangeMin() const9210395e015SCullen Rhodes unsigned AttributeSetNode::getVScaleRangeMin() const {
92248f5a392SBradley Smith if (auto A = findEnumAttribute(Attribute::VScaleRange))
9230395e015SCullen Rhodes return A->getVScaleRangeMin();
9240395e015SCullen Rhodes return 1;
9250395e015SCullen Rhodes }
9260395e015SCullen Rhodes
getVScaleRangeMax() const9270395e015SCullen Rhodes Optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
9280395e015SCullen Rhodes if (auto A = findEnumAttribute(Attribute::VScaleRange))
9290395e015SCullen Rhodes return A->getVScaleRangeMax();
9300395e015SCullen Rhodes return None;
93148f5a392SBradley Smith }
93248f5a392SBradley Smith
getUWTableKind() const9336398903aSMomchil Velikov UWTableKind AttributeSetNode::getUWTableKind() const {
9346398903aSMomchil Velikov if (auto A = findEnumAttribute(Attribute::UWTable))
9356398903aSMomchil Velikov return A->getUWTableKind();
9366398903aSMomchil Velikov return UWTableKind::None;
9376398903aSMomchil Velikov }
9386398903aSMomchil Velikov
getAllocKind() const93942861faaSAugie Fackler AllocFnKind AttributeSetNode::getAllocKind() const {
94042861faaSAugie Fackler if (auto A = findEnumAttribute(Attribute::AllocKind))
94142861faaSAugie Fackler return A->getAllocKind();
94242861faaSAugie Fackler return AllocFnKind::Unknown;
94342861faaSAugie Fackler }
94442861faaSAugie Fackler
getAsString(bool InAttrGrp) const945cbf5a7adSRafael Espindola std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
9460baf8f42SBenjamin Kramer std::string Str;
947741146b8SBenjamin Kramer for (iterator I = begin(), E = end(); I != E; ++I) {
948741146b8SBenjamin Kramer if (I != begin())
9490baf8f42SBenjamin Kramer Str += ' ';
950829b4789SBill Wendling Str += I->getAsString(InAttrGrp);
951877cf534SBill Wendling }
952f2955aa3SBill Wendling return Str;
953f2955aa3SBill Wendling }
954f2955aa3SBill Wendling
955d509a665SBill Wendling //===----------------------------------------------------------------------===//
956b518054bSReid Kleckner // AttributeListImpl Definition
957d509a665SBill Wendling //===----------------------------------------------------------------------===//
958d509a665SBill Wendling
95951b2cd8fSReid Kleckner /// Map from AttributeList index to the internal array index. Adding one happens
9606904c712SNikita Popov /// to work, because -1 wraps around to 0.
attrIdxToArrayIdx(unsigned Index)961f7dce889SNikita Popov static unsigned attrIdxToArrayIdx(unsigned Index) {
9626904c712SNikita Popov return Index + 1;
963a82be60dSReid Kleckner }
9648bf67fe9SReid Kleckner
AttributeListImpl(ArrayRef<AttributeSet> Sets)9657a5a1e94SBenjamin Kramer AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
9667a5a1e94SBenjamin Kramer : NumAttrSets(Sets.size()) {
9678bf67fe9SReid Kleckner assert(!Sets.empty() && "pointless AttributeListImpl");
968a82be60dSReid Kleckner
969a82be60dSReid Kleckner // There's memory after the node where we can store the entries in.
97075709329SFangrui Song llvm::copy(Sets, getTrailingObjects<AttributeSet>());
971a82be60dSReid Kleckner
9729a334a4dSNikita Popov // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
9739a334a4dSNikita Popov // summary bitsets.
974f7dce889SNikita Popov for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
97535651fddSNikita Popov if (!I.isStringAttribute())
97635651fddSNikita Popov AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
9779a334a4dSNikita Popov
9789a334a4dSNikita Popov for (const auto &Set : Sets)
9799a334a4dSNikita Popov for (const auto &I : Set)
9809a334a4dSNikita Popov if (!I.isStringAttribute())
9819a334a4dSNikita Popov AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
982a82be60dSReid Kleckner }
983a82be60dSReid Kleckner
Profile(FoldingSetNodeID & ID) const984a82be60dSReid Kleckner void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
9858bf67fe9SReid Kleckner Profile(ID, makeArrayRef(begin(), end()));
986a82be60dSReid Kleckner }
987a82be60dSReid Kleckner
Profile(FoldingSetNodeID & ID,ArrayRef<AttributeSet> Sets)9888bf67fe9SReid Kleckner void AttributeListImpl::Profile(FoldingSetNodeID &ID,
9898bf67fe9SReid Kleckner ArrayRef<AttributeSet> Sets) {
9908bf67fe9SReid Kleckner for (const auto &Set : Sets)
9918bf67fe9SReid Kleckner ID.AddPointer(Set.SetNode);
992a82be60dSReid Kleckner }
993a82be60dSReid Kleckner
hasAttrSomewhere(Attribute::AttrKind Kind,unsigned * Index) const9949a334a4dSNikita Popov bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
9959a334a4dSNikita Popov unsigned *Index) const {
9969a334a4dSNikita Popov if (!AvailableSomewhereAttrs.hasAttribute(Kind))
9979a334a4dSNikita Popov return false;
9989a334a4dSNikita Popov
9999a334a4dSNikita Popov if (Index) {
10009a334a4dSNikita Popov for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
10019a334a4dSNikita Popov if (begin()[I].hasAttribute(Kind)) {
10029a334a4dSNikita Popov *Index = I - 1;
10039a334a4dSNikita Popov break;
10049a334a4dSNikita Popov }
10059a334a4dSNikita Popov }
10069a334a4dSNikita Popov }
10079a334a4dSNikita Popov
10089a334a4dSNikita Popov return true;
10099a334a4dSNikita Popov }
10109a334a4dSNikita Popov
10119a334a4dSNikita Popov
1012615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1013b518054bSReid Kleckner LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
1014b518054bSReid Kleckner AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1015abca2ecaSPeter Collingbourne }
10168c209aa8SMatthias Braun #endif
1017abca2ecaSPeter Collingbourne
1018d509a665SBill Wendling //===----------------------------------------------------------------------===//
1019b518054bSReid Kleckner // AttributeList Construction and Mutation Methods
1020d509a665SBill Wendling //===----------------------------------------------------------------------===//
1021d509a665SBill Wendling
getImpl(LLVMContext & C,ArrayRef<AttributeSet> AttrSets)10228bf67fe9SReid Kleckner AttributeList AttributeList::getImpl(LLVMContext &C,
10238bf67fe9SReid Kleckner ArrayRef<AttributeSet> AttrSets) {
10248bf67fe9SReid Kleckner assert(!AttrSets.empty() && "pointless AttributeListImpl");
1025eb9dd5b8SReid Kleckner
1026d509a665SBill Wendling LLVMContextImpl *pImpl = C.pImpl;
1027d509a665SBill Wendling FoldingSetNodeID ID;
10288bf67fe9SReid Kleckner AttributeListImpl::Profile(ID, AttrSets);
1029d509a665SBill Wendling
1030d509a665SBill Wendling void *InsertPoint;
1031b518054bSReid Kleckner AttributeListImpl *PA =
1032b518054bSReid Kleckner pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1033d509a665SBill Wendling
1034d509a665SBill Wendling // If we didn't find any existing attributes of the same shape then
1035d509a665SBill Wendling // create a new one and insert it.
1036d509a665SBill Wendling if (!PA) {
1037b518054bSReid Kleckner // Coallocate entries after the AttributeListImpl itself.
10381c3fe86fSBenjamin Kramer void *Mem = pImpl->Alloc.Allocate(
10391c3fe86fSBenjamin Kramer AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
10401c3fe86fSBenjamin Kramer alignof(AttributeListImpl));
10417a5a1e94SBenjamin Kramer PA = new (Mem) AttributeListImpl(AttrSets);
1042d509a665SBill Wendling pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1043d509a665SBill Wendling }
1044d509a665SBill Wendling
1045d509a665SBill Wendling // Return the AttributesList that we found or created.
1046b518054bSReid Kleckner return AttributeList(PA);
1047d509a665SBill Wendling }
1048d509a665SBill Wendling
1049b518054bSReid Kleckner AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,Attribute>> Attrs)1050b518054bSReid Kleckner AttributeList::get(LLVMContext &C,
1051d509a665SBill Wendling ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1052d509a665SBill Wendling // If there are no attributes then return a null AttributesList pointer.
1053d509a665SBill Wendling if (Attrs.empty())
10547fb5d41eSEugene Zelenko return {};
1055d509a665SBill Wendling
10564969a692SKazu Hirata assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
10571647ff6eSGeorgii Rymar "Misordered Attributes list!");
1058aab90384SCraig Topper assert(llvm::all_of(Attrs,
1059e30b8ca1SCraig Topper [](const std::pair<unsigned, Attribute> &Pair) {
1060aab90384SCraig Topper return Pair.second.isValid();
10610a16c228SDavid Majnemer }) &&
10620a16c228SDavid Majnemer "Pointless attribute!");
1063d509a665SBill Wendling
1064d509a665SBill Wendling // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1065d509a665SBill Wendling // list.
1066c2cb5600SReid Kleckner SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1067d509a665SBill Wendling for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1068d509a665SBill Wendling E = Attrs.end(); I != E; ) {
1069d509a665SBill Wendling unsigned Index = I->first;
1070d509a665SBill Wendling SmallVector<Attribute, 4> AttrVec;
1071f05d2f25SNAKAMURA Takumi while (I != E && I->first == Index) {
1072d509a665SBill Wendling AttrVec.push_back(I->second);
1073d509a665SBill Wendling ++I;
1074d509a665SBill Wendling }
1075d509a665SBill Wendling
1076c2cb5600SReid Kleckner AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1077d509a665SBill Wendling }
1078d509a665SBill Wendling
10798bf67fe9SReid Kleckner return get(C, AttrPairVec);
1080d509a665SBill Wendling }
1081d509a665SBill Wendling
1082b518054bSReid Kleckner AttributeList
get(LLVMContext & C,ArrayRef<std::pair<unsigned,AttributeSet>> Attrs)1083b518054bSReid Kleckner AttributeList::get(LLVMContext &C,
1084c2cb5600SReid Kleckner ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1085d509a665SBill Wendling // If there are no attributes then return a null AttributesList pointer.
1086d509a665SBill Wendling if (Attrs.empty())
10877fb5d41eSEugene Zelenko return {};
1088d509a665SBill Wendling
10894969a692SKazu Hirata assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
10908bf67fe9SReid Kleckner "Misordered Attributes list!");
10917fb5d41eSEugene Zelenko assert(llvm::none_of(Attrs,
10928bf67fe9SReid Kleckner [](const std::pair<unsigned, AttributeSet> &Pair) {
10938bf67fe9SReid Kleckner return !Pair.second.hasAttributes();
10948bf67fe9SReid Kleckner }) &&
10958bf67fe9SReid Kleckner "Pointless attribute!");
10968bf67fe9SReid Kleckner
10978bf67fe9SReid Kleckner unsigned MaxIndex = Attrs.back().first;
1098f8642505SCraig Topper // If the MaxIndex is FunctionIndex and there are other indices in front
1099f8642505SCraig Topper // of it, we need to use the largest of those to get the right size.
1100f8642505SCraig Topper if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1101f8642505SCraig Topper MaxIndex = Attrs[Attrs.size() - 2].first;
11028bf67fe9SReid Kleckner
11038bf67fe9SReid Kleckner SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
11041a8ff896SMark de Wever for (const auto &Pair : Attrs)
11058bf67fe9SReid Kleckner AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
11068bf67fe9SReid Kleckner
11078bf67fe9SReid Kleckner return getImpl(C, AttrVec);
1108d509a665SBill Wendling }
1109d509a665SBill Wendling
get(LLVMContext & C,AttributeSet FnAttrs,AttributeSet RetAttrs,ArrayRef<AttributeSet> ArgAttrs)11107f72033eSReid Kleckner AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
11117f72033eSReid Kleckner AttributeSet RetAttrs,
11127f72033eSReid Kleckner ArrayRef<AttributeSet> ArgAttrs) {
11138bf67fe9SReid Kleckner // Scan from the end to find the last argument with attributes. Most
11148bf67fe9SReid Kleckner // arguments don't have attributes, so it's nice if we can have fewer unique
11158bf67fe9SReid Kleckner // AttributeListImpls by dropping empty attribute sets at the end of the list.
11168bf67fe9SReid Kleckner unsigned NumSets = 0;
11178bf67fe9SReid Kleckner for (size_t I = ArgAttrs.size(); I != 0; --I) {
11188bf67fe9SReid Kleckner if (ArgAttrs[I - 1].hasAttributes()) {
11198bf67fe9SReid Kleckner NumSets = I + 2;
11208bf67fe9SReid Kleckner break;
1121eb9dd5b8SReid Kleckner }
11228bf67fe9SReid Kleckner }
11238bf67fe9SReid Kleckner if (NumSets == 0) {
11248bf67fe9SReid Kleckner // Check function and return attributes if we didn't have argument
11258bf67fe9SReid Kleckner // attributes.
11268bf67fe9SReid Kleckner if (RetAttrs.hasAttributes())
11278bf67fe9SReid Kleckner NumSets = 2;
11288bf67fe9SReid Kleckner else if (FnAttrs.hasAttributes())
11298bf67fe9SReid Kleckner NumSets = 1;
11308bf67fe9SReid Kleckner }
11318bf67fe9SReid Kleckner
11328bf67fe9SReid Kleckner // If all attribute sets were empty, we can use the empty attribute list.
11338bf67fe9SReid Kleckner if (NumSets == 0)
11347fb5d41eSEugene Zelenko return {};
11358bf67fe9SReid Kleckner
11368bf67fe9SReid Kleckner SmallVector<AttributeSet, 8> AttrSets;
11378bf67fe9SReid Kleckner AttrSets.reserve(NumSets);
11388bf67fe9SReid Kleckner // If we have any attributes, we always have function attributes.
11398bf67fe9SReid Kleckner AttrSets.push_back(FnAttrs);
11408bf67fe9SReid Kleckner if (NumSets > 1)
11418bf67fe9SReid Kleckner AttrSets.push_back(RetAttrs);
11428bf67fe9SReid Kleckner if (NumSets > 2) {
11438bf67fe9SReid Kleckner // Drop the empty argument attribute sets at the end.
11448bf67fe9SReid Kleckner ArgAttrs = ArgAttrs.take_front(NumSets - 2);
11451d0bc055SKazu Hirata llvm::append_range(AttrSets, ArgAttrs);
11468bf67fe9SReid Kleckner }
11478bf67fe9SReid Kleckner
11488bf67fe9SReid Kleckner return getImpl(C, AttrSets);
1149eb9dd5b8SReid Kleckner }
1150eb9dd5b8SReid Kleckner
get(LLVMContext & C,unsigned Index,AttributeSet Attrs)1151b518054bSReid Kleckner AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
11526e30cb76SNikita Popov AttributeSet Attrs) {
11536e30cb76SNikita Popov if (!Attrs.hasAttributes())
11547fb5d41eSEugene Zelenko return {};
11558bf67fe9SReid Kleckner Index = attrIdxToArrayIdx(Index);
11568bf67fe9SReid Kleckner SmallVector<AttributeSet, 8> AttrSets(Index + 1);
11576e30cb76SNikita Popov AttrSets[Index] = Attrs;
11588bf67fe9SReid Kleckner return getImpl(C, AttrSets);
1159d509a665SBill Wendling }
1160d509a665SBill Wendling
get(LLVMContext & C,unsigned Index,const AttrBuilder & B)1161b518054bSReid Kleckner AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
11626e30cb76SNikita Popov const AttrBuilder &B) {
11636e30cb76SNikita Popov return get(C, Index, AttributeSet::get(C, B));
11646e30cb76SNikita Popov }
11656e30cb76SNikita Popov
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds)11666e30cb76SNikita Popov AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1167392638d7SAmaury Sechet ArrayRef<Attribute::AttrKind> Kinds) {
1168d509a665SBill Wendling SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
11697fb5d41eSEugene Zelenko for (const auto K : Kinds)
11700a16c228SDavid Majnemer Attrs.emplace_back(Index, Attribute::get(C, K));
1171d509a665SBill Wendling return get(C, Attrs);
1172d509a665SBill Wendling }
1173d509a665SBill Wendling
get(LLVMContext & C,unsigned Index,ArrayRef<Attribute::AttrKind> Kinds,ArrayRef<uint64_t> Values)1174b518054bSReid Kleckner AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1175fa342b5cSMichael Liao ArrayRef<Attribute::AttrKind> Kinds,
1176fa342b5cSMichael Liao ArrayRef<uint64_t> Values) {
1177fa342b5cSMichael Liao assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1178fa342b5cSMichael Liao SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1179fa342b5cSMichael Liao auto VI = Values.begin();
1180fa342b5cSMichael Liao for (const auto K : Kinds)
1181fa342b5cSMichael Liao Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1182fa342b5cSMichael Liao return get(C, Attrs);
1183fa342b5cSMichael Liao }
1184fa342b5cSMichael Liao
get(LLVMContext & C,unsigned Index,ArrayRef<StringRef> Kinds)1185fa342b5cSMichael Liao AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
11866100adfeSAmaury Sechet ArrayRef<StringRef> Kinds) {
11876100adfeSAmaury Sechet SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
11881a8ff896SMark de Wever for (const auto &K : Kinds)
11890a16c228SDavid Majnemer Attrs.emplace_back(Index, Attribute::get(C, K));
11906100adfeSAmaury Sechet return get(C, Attrs);
11916100adfeSAmaury Sechet }
11926100adfeSAmaury Sechet
get(LLVMContext & C,ArrayRef<AttributeList> Attrs)1193b518054bSReid Kleckner AttributeList AttributeList::get(LLVMContext &C,
1194b518054bSReid Kleckner ArrayRef<AttributeList> Attrs) {
1195b518054bSReid Kleckner if (Attrs.empty())
11967fb5d41eSEugene Zelenko return {};
11978bf67fe9SReid Kleckner if (Attrs.size() == 1)
11988bf67fe9SReid Kleckner return Attrs[0];
1199d509a665SBill Wendling
12008bf67fe9SReid Kleckner unsigned MaxSize = 0;
12011a8ff896SMark de Wever for (const auto &List : Attrs)
12028bf67fe9SReid Kleckner MaxSize = std::max(MaxSize, List.getNumAttrSets());
12038bf67fe9SReid Kleckner
12041d7cbdfcSReid Kleckner // If every list was empty, there is no point in merging the lists.
12051d7cbdfcSReid Kleckner if (MaxSize == 0)
12067fb5d41eSEugene Zelenko return {};
12071d7cbdfcSReid Kleckner
12088bf67fe9SReid Kleckner SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
12098bf67fe9SReid Kleckner for (unsigned I = 0; I < MaxSize; ++I) {
1210d2cc6c2dSSerge Guelton AttrBuilder CurBuilder(C);
12111a8ff896SMark de Wever for (const auto &List : Attrs)
1212d2cc6c2dSSerge Guelton CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
12138bf67fe9SReid Kleckner NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1214d509a665SBill Wendling }
1215d509a665SBill Wendling
12168bf67fe9SReid Kleckner return getImpl(C, NewAttrSets);
1217d509a665SBill Wendling }
1218d509a665SBill Wendling
1219c9693492SArthur Eubanks AttributeList
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1220c9693492SArthur Eubanks AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1221392638d7SAmaury Sechet Attribute::AttrKind Kind) const {
1222c9693492SArthur Eubanks if (hasAttributeAtIndex(Index, Kind))
1223c9693492SArthur Eubanks return *this;
1224176c7f22SNikita Popov AttributeSet Attrs = getAttributes(Index);
1225176c7f22SNikita Popov // TODO: Insert at correct position and avoid sort.
1226176c7f22SNikita Popov SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1227176c7f22SNikita Popov NewAttrs.push_back(Attribute::get(C, Kind));
1228c9693492SArthur Eubanks return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1229795c7b45SReed Kotler }
1230795c7b45SReed Kotler
addAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind,StringRef Value) const1231c9693492SArthur Eubanks AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1232b518054bSReid Kleckner StringRef Kind,
1233b518054bSReid Kleckner StringRef Value) const {
1234d2cc6c2dSSerge Guelton AttrBuilder B(C);
12353b2f6106SBill Wendling B.addAttribute(Kind, Value);
1236c9693492SArthur Eubanks return addAttributesAtIndex(C, Index, B);
12373b2f6106SBill Wendling }
12383b2f6106SBill Wendling
addAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute A) const1239c9693492SArthur Eubanks AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1240237916b5SAkira Hatanaka Attribute A) const {
1241d2cc6c2dSSerge Guelton AttrBuilder B(C);
1242eb9dd5b8SReid Kleckner B.addAttribute(A);
1243c9693492SArthur Eubanks return addAttributesAtIndex(C, Index, B);
1244237916b5SAkira Hatanaka }
1245237916b5SAkira Hatanaka
setAttributesAtIndex(LLVMContext & C,unsigned Index,AttributeSet Attrs) const1246c9693492SArthur Eubanks AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1247c9693492SArthur Eubanks unsigned Index,
1248176c7f22SNikita Popov AttributeSet Attrs) const {
1249176c7f22SNikita Popov Index = attrIdxToArrayIdx(Index);
1250176c7f22SNikita Popov SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1251176c7f22SNikita Popov if (Index >= AttrSets.size())
1252176c7f22SNikita Popov AttrSets.resize(Index + 1);
1253176c7f22SNikita Popov AttrSets[Index] = Attrs;
1254176c7f22SNikita Popov return AttributeList::getImpl(C, AttrSets);
1255176c7f22SNikita Popov }
1256176c7f22SNikita Popov
addAttributesAtIndex(LLVMContext & C,unsigned Index,const AttrBuilder & B) const1257c9693492SArthur Eubanks AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1258c9693492SArthur Eubanks unsigned Index,
125961906253SReid Kleckner const AttrBuilder &B) const {
126061906253SReid Kleckner if (!B.hasAttributes())
1261eb9dd5b8SReid Kleckner return *this;
1262eb9dd5b8SReid Kleckner
1263fe64c013SReid Kleckner if (!pImpl)
126461906253SReid Kleckner return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1265fe64c013SReid Kleckner
1266d2cc6c2dSSerge Guelton AttrBuilder Merged(C, getAttributes(Index));
12678bf67fe9SReid Kleckner Merged.merge(B);
1268c9693492SArthur Eubanks return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1269eb9dd5b8SReid Kleckner }
1270eb9dd5b8SReid Kleckner
addParamAttribute(LLVMContext & C,ArrayRef<unsigned> ArgNos,Attribute A) const12715fbdd177SReid Kleckner AttributeList AttributeList::addParamAttribute(LLVMContext &C,
12725fbdd177SReid Kleckner ArrayRef<unsigned> ArgNos,
12735fbdd177SReid Kleckner Attribute A) const {
12741647ff6eSGeorgii Rymar assert(llvm::is_sorted(ArgNos));
12755fbdd177SReid Kleckner
12765fbdd177SReid Kleckner SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
12775fbdd177SReid Kleckner unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
12785fbdd177SReid Kleckner if (MaxIndex >= AttrSets.size())
12795fbdd177SReid Kleckner AttrSets.resize(MaxIndex + 1);
12805fbdd177SReid Kleckner
12815fbdd177SReid Kleckner for (unsigned ArgNo : ArgNos) {
12825fbdd177SReid Kleckner unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1283d2cc6c2dSSerge Guelton AttrBuilder B(C, AttrSets[Index]);
12845fbdd177SReid Kleckner B.addAttribute(A);
12855fbdd177SReid Kleckner AttrSets[Index] = AttributeSet::get(C, B);
12865fbdd177SReid Kleckner }
12875fbdd177SReid Kleckner
12885fbdd177SReid Kleckner return getImpl(C, AttrSets);
12895fbdd177SReid Kleckner }
12905fbdd177SReid Kleckner
1291c9693492SArthur Eubanks AttributeList
removeAttributeAtIndex(LLVMContext & C,unsigned Index,Attribute::AttrKind Kind) const1292c9693492SArthur Eubanks AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1293392638d7SAmaury Sechet Attribute::AttrKind Kind) const {
1294c9693492SArthur Eubanks if (!hasAttributeAtIndex(Index, Kind))
1295c9693492SArthur Eubanks return *this;
129688dddb89SDaniel Neilson
129788dddb89SDaniel Neilson Index = attrIdxToArrayIdx(Index);
129888dddb89SDaniel Neilson SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
129988dddb89SDaniel Neilson assert(Index < AttrSets.size());
130088dddb89SDaniel Neilson
130188dddb89SDaniel Neilson AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
130288dddb89SDaniel Neilson
130388dddb89SDaniel Neilson return getImpl(C, AttrSets);
1304d509a665SBill Wendling }
1305d509a665SBill Wendling
removeAttributeAtIndex(LLVMContext & C,unsigned Index,StringRef Kind) const1306c9693492SArthur Eubanks AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1307c9693492SArthur Eubanks unsigned Index,
13086100adfeSAmaury Sechet StringRef Kind) const {
1309c9693492SArthur Eubanks if (!hasAttributeAtIndex(Index, Kind))
1310c9693492SArthur Eubanks return *this;
131188dddb89SDaniel Neilson
131288dddb89SDaniel Neilson Index = attrIdxToArrayIdx(Index);
131388dddb89SDaniel Neilson SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
131488dddb89SDaniel Neilson assert(Index < AttrSets.size());
131588dddb89SDaniel Neilson
131688dddb89SDaniel Neilson AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
131788dddb89SDaniel Neilson
131888dddb89SDaniel Neilson return getImpl(C, AttrSets);
1319d509a665SBill Wendling }
1320d509a665SBill Wendling
removeAttributesAtIndex(LLVMContext & C,unsigned Index,const AttributeMask & AttrsToRemove) const13219290ccc3Sserge-sans-paille AttributeList AttributeList::removeAttributesAtIndex(
13229290ccc3Sserge-sans-paille LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
132305738ffcSNikita Popov AttributeSet Attrs = getAttributes(Index);
132405738ffcSNikita Popov AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
132505738ffcSNikita Popov // If nothing was removed, return the original list.
132605738ffcSNikita Popov if (Attrs == NewAttrs)
132705738ffcSNikita Popov return *this;
1328c9693492SArthur Eubanks return setAttributesAtIndex(C, Index, NewAttrs);
1329d2a44619SPete Cooper }
1330d2a44619SPete Cooper
1331c9693492SArthur Eubanks AttributeList
removeAttributesAtIndex(LLVMContext & C,unsigned WithoutIndex) const1332c9693492SArthur Eubanks AttributeList::removeAttributesAtIndex(LLVMContext &C,
1333eb9dd5b8SReid Kleckner unsigned WithoutIndex) const {
1334eb9dd5b8SReid Kleckner if (!pImpl)
13357fb5d41eSEugene Zelenko return {};
13368bf67fe9SReid Kleckner WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
13378bf67fe9SReid Kleckner if (WithoutIndex >= getNumAttrSets())
13388bf67fe9SReid Kleckner return *this;
13398bf67fe9SReid Kleckner SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
13408bf67fe9SReid Kleckner AttrSets[WithoutIndex] = AttributeSet();
13418bf67fe9SReid Kleckner return getImpl(C, AttrSets);
1342eb9dd5b8SReid Kleckner }
1343eb9dd5b8SReid Kleckner
addDereferenceableRetAttr(LLVMContext & C,uint64_t Bytes) const134444a3241fSArthur Eubanks AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
134544a3241fSArthur Eubanks uint64_t Bytes) const {
1346d2cc6c2dSSerge Guelton AttrBuilder B(C);
134744a3241fSArthur Eubanks B.addDereferenceableAttr(Bytes);
134844a3241fSArthur Eubanks return addRetAttributes(C, B);
134944a3241fSArthur Eubanks }
135044a3241fSArthur Eubanks
addDereferenceableParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const135144a3241fSArthur Eubanks AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
135231ea6d15SSanjoy Das unsigned Index,
135331ea6d15SSanjoy Das uint64_t Bytes) const {
1354d2cc6c2dSSerge Guelton AttrBuilder B(C);
1355b518054bSReid Kleckner B.addDereferenceableAttr(Bytes);
135644a3241fSArthur Eubanks return addParamAttributes(C, Index, B);
135731ea6d15SSanjoy Das }
135831ea6d15SSanjoy Das
1359b518054bSReid Kleckner AttributeList
addDereferenceableOrNullParamAttr(LLVMContext & C,unsigned Index,uint64_t Bytes) const1360d7df8127SArthur Eubanks AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1361b518054bSReid Kleckner uint64_t Bytes) const {
1362d2cc6c2dSSerge Guelton AttrBuilder B(C);
1363b518054bSReid Kleckner B.addDereferenceableOrNullAttr(Bytes);
1364d7df8127SArthur Eubanks return addParamAttributes(C, Index, B);
1365b518054bSReid Kleckner }
1366b518054bSReid Kleckner
1367b518054bSReid Kleckner AttributeList
addAllocSizeParamAttr(LLVMContext & C,unsigned Index,unsigned ElemSizeArg,const Optional<unsigned> & NumElemsArg)1368d7df8127SArthur Eubanks AttributeList::addAllocSizeParamAttr(LLVMContext &C, unsigned Index,
1369278199f6SGeorge Burgess IV unsigned ElemSizeArg,
1370278199f6SGeorge Burgess IV const Optional<unsigned> &NumElemsArg) {
1371d2cc6c2dSSerge Guelton AttrBuilder B(C);
1372278199f6SGeorge Burgess IV B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1373d7df8127SArthur Eubanks return addParamAttributes(C, Index, B);
137448f5a392SBradley Smith }
137548f5a392SBradley Smith
1376d509a665SBill Wendling //===----------------------------------------------------------------------===//
1377b518054bSReid Kleckner // AttributeList Accessor Methods
1378d509a665SBill Wendling //===----------------------------------------------------------------------===//
1379d509a665SBill Wendling
getParamAttrs(unsigned ArgNo) const138080ea2bb5SArthur Eubanks AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1381a0b45f4bSReid Kleckner return getAttributes(ArgNo + FirstArgIndex);
1382d509a665SBill Wendling }
1383d509a665SBill Wendling
getRetAttrs() const138480ea2bb5SArthur Eubanks AttributeSet AttributeList::getRetAttrs() const {
1385eb9dd5b8SReid Kleckner return getAttributes(ReturnIndex);
1386d509a665SBill Wendling }
1387d509a665SBill Wendling
getFnAttrs() const138880ea2bb5SArthur Eubanks AttributeSet AttributeList::getFnAttrs() const {
1389eb9dd5b8SReid Kleckner return getAttributes(FunctionIndex);
1390d509a665SBill Wendling }
1391d509a665SBill Wendling
hasAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1392c9693492SArthur Eubanks bool AttributeList::hasAttributeAtIndex(unsigned Index,
1393b518054bSReid Kleckner Attribute::AttrKind Kind) const {
1394c2cb5600SReid Kleckner return getAttributes(Index).hasAttribute(Kind);
1395d509a665SBill Wendling }
1396d509a665SBill Wendling
hasAttributeAtIndex(unsigned Index,StringRef Kind) const1397c9693492SArthur Eubanks bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1398c2cb5600SReid Kleckner return getAttributes(Index).hasAttribute(Kind);
1399bce7b97cSBill Wendling }
1400bce7b97cSBill Wendling
hasAttributesAtIndex(unsigned Index) const1401c9693492SArthur Eubanks bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1402c2cb5600SReid Kleckner return getAttributes(Index).hasAttributes();
1403d509a665SBill Wendling }
1404d509a665SBill Wendling
hasFnAttr(Attribute::AttrKind Kind) const140592ce6db9SArthur Eubanks bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
140633282815SMatthias Braun return pImpl && pImpl->hasFnAttribute(Kind);
140733282815SMatthias Braun }
140833282815SMatthias Braun
hasFnAttr(StringRef Kind) const140992ce6db9SArthur Eubanks bool AttributeList::hasFnAttr(StringRef Kind) const {
1410c9693492SArthur Eubanks return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
14115f04d819SAmaury Sechet }
14125f04d819SAmaury Sechet
hasAttrSomewhere(Attribute::AttrKind Attr,unsigned * Index) const1413b518054bSReid Kleckner bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1414e87ad547SHal Finkel unsigned *Index) const {
14159a334a4dSNikita Popov return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1416d509a665SBill Wendling }
1417d509a665SBill Wendling
getAttributeAtIndex(unsigned Index,Attribute::AttrKind Kind) const1418c9693492SArthur Eubanks Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1419bce7b97cSBill Wendling Attribute::AttrKind Kind) const {
1420c2cb5600SReid Kleckner return getAttributes(Index).getAttribute(Kind);
1421bce7b97cSBill Wendling }
1422bce7b97cSBill Wendling
getAttributeAtIndex(unsigned Index,StringRef Kind) const1423c9693492SArthur Eubanks Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1424c9693492SArthur Eubanks StringRef Kind) const {
1425c2cb5600SReid Kleckner return getAttributes(Index).getAttribute(Kind);
1426bce7b97cSBill Wendling }
1427bce7b97cSBill Wendling
getRetAlignment() const142817f5d2b1SGuillaume Chatelet MaybeAlign AttributeList::getRetAlignment() const {
1429859f8b54SReid Kleckner return getAttributes(ReturnIndex).getAlignment();
1430859f8b54SReid Kleckner }
1431859f8b54SReid Kleckner
getParamAlignment(unsigned ArgNo) const143217f5d2b1SGuillaume Chatelet MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1433a0b45f4bSReid Kleckner return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1434d509a665SBill Wendling }
1435d509a665SBill Wendling
getParamStackAlignment(unsigned ArgNo) const1436f9d932e6SMomchil Velikov MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1437f9d932e6SMomchil Velikov return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1438f9d932e6SMomchil Velikov }
1439f9d932e6SMomchil Velikov
getParamByValType(unsigned Index) const1440b7141207STim Northover Type *AttributeList::getParamByValType(unsigned Index) const {
1441b7141207STim Northover return getAttributes(Index+FirstArgIndex).getByValType();
1442b7141207STim Northover }
1443b7141207STim Northover
getParamStructRetType(unsigned Index) const14440a7cd99aSMatt Arsenault Type *AttributeList::getParamStructRetType(unsigned Index) const {
14450a7cd99aSMatt Arsenault return getAttributes(Index + FirstArgIndex).getStructRetType();
14460a7cd99aSMatt Arsenault }
14470a7cd99aSMatt Arsenault
getParamByRefType(unsigned Index) const14485e999cbeSMatt Arsenault Type *AttributeList::getParamByRefType(unsigned Index) const {
14495e999cbeSMatt Arsenault return getAttributes(Index + FirstArgIndex).getByRefType();
14505e999cbeSMatt Arsenault }
14515e999cbeSMatt Arsenault
getParamPreallocatedType(unsigned Index) const14528a887556SArthur Eubanks Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
14538a887556SArthur Eubanks return getAttributes(Index + FirstArgIndex).getPreallocatedType();
14548a887556SArthur Eubanks }
14558a887556SArthur Eubanks
getParamInAllocaType(unsigned Index) const14569a0c9402SMatt Arsenault Type *AttributeList::getParamInAllocaType(unsigned Index) const {
14579a0c9402SMatt Arsenault return getAttributes(Index + FirstArgIndex).getInAllocaType();
14589a0c9402SMatt Arsenault }
14599a0c9402SMatt Arsenault
getParamElementType(unsigned Index) const1460be5af50eSNikita Popov Type *AttributeList::getParamElementType(unsigned Index) const {
1461be5af50eSNikita Popov return getAttributes(Index + FirstArgIndex).getElementType();
1462be5af50eSNikita Popov }
1463be5af50eSNikita Popov
getFnStackAlignment() const14647c8206cdSArthur Eubanks MaybeAlign AttributeList::getFnStackAlignment() const {
14657c8206cdSArthur Eubanks return getFnAttrs().getStackAlignment();
14667c8206cdSArthur Eubanks }
14677c8206cdSArthur Eubanks
getRetStackAlignment() const14687c8206cdSArthur Eubanks MaybeAlign AttributeList::getRetStackAlignment() const {
14697c8206cdSArthur Eubanks return getRetAttrs().getStackAlignment();
1470d509a665SBill Wendling }
1471d509a665SBill Wendling
getRetDereferenceableBytes() const147244a3241fSArthur Eubanks uint64_t AttributeList::getRetDereferenceableBytes() const {
147344a3241fSArthur Eubanks return getRetAttrs().getDereferenceableBytes();
1474b0407ba0SHal Finkel }
1475b0407ba0SHal Finkel
getParamDereferenceableBytes(unsigned Index) const147644a3241fSArthur Eubanks uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
147744a3241fSArthur Eubanks return getParamAttrs(Index).getDereferenceableBytes();
147844a3241fSArthur Eubanks }
147944a3241fSArthur Eubanks
getRetDereferenceableOrNullBytes() const148044a3241fSArthur Eubanks uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
148144a3241fSArthur Eubanks return getRetAttrs().getDereferenceableOrNullBytes();
148244a3241fSArthur Eubanks }
148344a3241fSArthur Eubanks
148444a3241fSArthur Eubanks uint64_t
getParamDereferenceableOrNullBytes(unsigned Index) const148544a3241fSArthur Eubanks AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
148644a3241fSArthur Eubanks return getParamAttrs(Index).getDereferenceableOrNullBytes();
148706cf33fbSSanjoy Das }
148806cf33fbSSanjoy Das
getUWTableKind() const14896398903aSMomchil Velikov UWTableKind AttributeList::getUWTableKind() const {
14906398903aSMomchil Velikov return getFnAttrs().getUWTableKind();
14916398903aSMomchil Velikov }
14926398903aSMomchil Velikov
getAllocKind() const149342861faaSAugie Fackler AllocFnKind AttributeList::getAllocKind() const {
149442861faaSAugie Fackler return getFnAttrs().getAllocKind();
149542861faaSAugie Fackler }
149642861faaSAugie Fackler
getAsString(unsigned Index,bool InAttrGrp) const1497b518054bSReid Kleckner std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1498c2cb5600SReid Kleckner return getAttributes(Index).getAsString(InAttrGrp);
1499d509a665SBill Wendling }
1500d509a665SBill Wendling
getAttributes(unsigned Index) const1501c2cb5600SReid Kleckner AttributeSet AttributeList::getAttributes(unsigned Index) const {
15028bf67fe9SReid Kleckner Index = attrIdxToArrayIdx(Index);
15038bf67fe9SReid Kleckner if (!pImpl || Index >= getNumAttrSets())
15047fb5d41eSEugene Zelenko return {};
15058bf67fe9SReid Kleckner return pImpl->begin()[Index];
1506d509a665SBill Wendling }
1507d509a665SBill Wendling
hasParentContext(LLVMContext & C) const1508244d9d6eSNick Lewycky bool AttributeList::hasParentContext(LLVMContext &C) const {
1509244d9d6eSNick Lewycky assert(!isEmpty() && "an empty attribute list has no parent context");
1510244d9d6eSNick Lewycky FoldingSetNodeID ID;
1511244d9d6eSNick Lewycky pImpl->Profile(ID);
1512244d9d6eSNick Lewycky void *Unused;
1513244d9d6eSNick Lewycky return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1514244d9d6eSNick Lewycky }
1515244d9d6eSNick Lewycky
begin() const15168bf67fe9SReid Kleckner AttributeList::iterator AttributeList::begin() const {
15178bf67fe9SReid Kleckner return pImpl ? pImpl->begin() : nullptr;
1518a9174860SBill Wendling }
1519a9174860SBill Wendling
end() const15208bf67fe9SReid Kleckner AttributeList::iterator AttributeList::end() const {
15218bf67fe9SReid Kleckner return pImpl ? pImpl->end() : nullptr;
1522a9174860SBill Wendling }
1523a9174860SBill Wendling
1524d509a665SBill Wendling //===----------------------------------------------------------------------===//
1525b518054bSReid Kleckner // AttributeList Introspection Methods
1526d509a665SBill Wendling //===----------------------------------------------------------------------===//
1527d509a665SBill Wendling
getNumAttrSets() const15288bf67fe9SReid Kleckner unsigned AttributeList::getNumAttrSets() const {
15298bf67fe9SReid Kleckner return pImpl ? pImpl->NumAttrSets : 0;
1530d509a665SBill Wendling }
1531d509a665SBill Wendling
print(raw_ostream & O) const1532244d9d6eSNick Lewycky void AttributeList::print(raw_ostream &O) const {
153330bbfda0SNick Lewycky O << "AttributeList[\n";
1534d509a665SBill Wendling
1535a7b4ce9cSArthur Eubanks for (unsigned i : indexes()) {
153630bbfda0SNick Lewycky if (!getAttributes(i).hasAttributes())
153730bbfda0SNick Lewycky continue;
153830bbfda0SNick Lewycky O << " { ";
153930bbfda0SNick Lewycky switch (i) {
154030bbfda0SNick Lewycky case AttrIndex::ReturnIndex:
154130bbfda0SNick Lewycky O << "return";
154230bbfda0SNick Lewycky break;
154330bbfda0SNick Lewycky case AttrIndex::FunctionIndex:
154430bbfda0SNick Lewycky O << "function";
154530bbfda0SNick Lewycky break;
154630bbfda0SNick Lewycky default:
154730bbfda0SNick Lewycky O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
154830bbfda0SNick Lewycky }
154930bbfda0SNick Lewycky O << " => " << getAsString(i) << " }\n";
1550d509a665SBill Wendling }
1551d509a665SBill Wendling
1552244d9d6eSNick Lewycky O << "]\n";
1553d509a665SBill Wendling }
1554244d9d6eSNick Lewycky
1555244d9d6eSNick Lewycky #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1556244d9d6eSNick Lewycky LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
15578c209aa8SMatthias Braun #endif
1558d509a665SBill Wendling
1559ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
1560cd330348SBill Wendling // AttrBuilder Method Implementations
1561ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
1562ef860a24SChandler Carruth
AttrBuilder(LLVMContext & Ctx,AttributeSet AS)1563d2cc6c2dSSerge Guelton AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
156442a68215SNikita Popov append_range(Attrs, AS);
156542a68215SNikita Popov assert(is_sorted(Attrs) && "AttributeSet should be sorted");
1566eb9dd5b8SReid Kleckner }
1567eb9dd5b8SReid Kleckner
clear()156842a68215SNikita Popov void AttrBuilder::clear() { Attrs.clear(); }
156942cc7f3cSNikita Popov
157042a68215SNikita Popov /// Attribute comparator that only compares attribute keys. Enum attributes are
157142a68215SNikita Popov /// sorted before string attributes.
157242a68215SNikita Popov struct AttributeComparator {
operator ()AttributeComparator1573d2cc6c2dSSerge Guelton bool operator()(Attribute A0, Attribute A1) const {
157442a68215SNikita Popov bool A0IsString = A0.isStringAttribute();
157542a68215SNikita Popov bool A1IsString = A1.isStringAttribute();
157642a68215SNikita Popov if (A0IsString) {
157742a68215SNikita Popov if (A1IsString)
1578d2cc6c2dSSerge Guelton return A0.getKindAsString() < A1.getKindAsString();
157942a68215SNikita Popov else
158042a68215SNikita Popov return false;
158142a68215SNikita Popov }
158242a68215SNikita Popov if (A1IsString)
158342a68215SNikita Popov return true;
158442a68215SNikita Popov return A0.getKindAsEnum() < A1.getKindAsEnum();
158542a68215SNikita Popov }
operator ()AttributeComparator158642a68215SNikita Popov bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
158742a68215SNikita Popov if (A0.isStringAttribute())
158842a68215SNikita Popov return false;
158942a68215SNikita Popov return A0.getKindAsEnum() < Kind;
1590d2cc6c2dSSerge Guelton }
operator ()AttributeComparator1591d2cc6c2dSSerge Guelton bool operator()(Attribute A0, StringRef Kind) const {
159242a68215SNikita Popov if (A0.isStringAttribute())
1593d2cc6c2dSSerge Guelton return A0.getKindAsString() < Kind;
159442a68215SNikita Popov return true;
1595d2cc6c2dSSerge Guelton }
1596d2cc6c2dSSerge Guelton };
1597d2cc6c2dSSerge Guelton
159842a68215SNikita Popov template <typename K>
addAttributeImpl(SmallVectorImpl<Attribute> & Attrs,K Kind,Attribute Attr)159942a68215SNikita Popov static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
160042a68215SNikita Popov Attribute Attr) {
160142a68215SNikita Popov auto It = lower_bound(Attrs, Kind, AttributeComparator());
160242a68215SNikita Popov if (It != Attrs.end() && It->hasAttribute(Kind))
1603d2cc6c2dSSerge Guelton std::swap(*It, Attr);
1604d2cc6c2dSSerge Guelton else
160542a68215SNikita Popov Attrs.insert(It, Attr);
160642a68215SNikita Popov }
160742a68215SNikita Popov
addAttribute(Attribute Attr)160842a68215SNikita Popov AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
160942a68215SNikita Popov if (Attr.isStringAttribute())
161042a68215SNikita Popov addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
161142a68215SNikita Popov else
161242a68215SNikita Popov addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
16130a437305SBill Wendling return *this;
16140a437305SBill Wendling }
16150a437305SBill Wendling
addAttribute(Attribute::AttrKind Kind)161642a68215SNikita Popov AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
161742a68215SNikita Popov addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
16181aa9d9e2SBill Wendling return *this;
16191aa9d9e2SBill Wendling }
16201aa9d9e2SBill Wendling
addAttribute(StringRef A,StringRef V)1621b9c5b1a5SBill Wendling AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
162242a68215SNikita Popov addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
162342a68215SNikita Popov return *this;
1624b9c5b1a5SBill Wendling }
1625b9c5b1a5SBill Wendling
removeAttribute(Attribute::AttrKind Val)162623804daaSBill Wendling AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1627eaf706beSBenjamin Kramer assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
162842a68215SNikita Popov auto It = lower_bound(Attrs, Val, AttributeComparator());
162942a68215SNikita Popov if (It != Attrs.end() && It->hasAttribute(Val))
163042a68215SNikita Popov Attrs.erase(It);
163123804daaSBill Wendling return *this;
163223804daaSBill Wendling }
163323804daaSBill Wendling
removeAttribute(StringRef A)1634b9c5b1a5SBill Wendling AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
163542a68215SNikita Popov auto It = lower_bound(Attrs, A, AttributeComparator());
163642a68215SNikita Popov if (It != Attrs.end() && It->hasAttribute(A))
163742a68215SNikita Popov Attrs.erase(It);
1638b9c5b1a5SBill Wendling return *this;
1639b9c5b1a5SBill Wendling }
1640b9c5b1a5SBill Wendling
getRawIntAttr(Attribute::AttrKind Kind) const16415ddf49b9SNikita Popov uint64_t AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
164242a68215SNikita Popov assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
164342a68215SNikita Popov Attribute A = getAttribute(Kind);
164442a68215SNikita Popov return A.isValid() ? A.getValueAsInt() : 0;
16455ddf49b9SNikita Popov }
16465ddf49b9SNikita Popov
addRawIntAttr(Attribute::AttrKind Kind,uint64_t Value)16475ddf49b9SNikita Popov AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
16485ddf49b9SNikita Popov uint64_t Value) {
164942a68215SNikita Popov return addAttribute(Attribute::get(Ctx, Kind, Value));
16505ddf49b9SNikita Popov }
16515ddf49b9SNikita Popov
getAllocSizeArgs() const1652278199f6SGeorge Burgess IV std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
16535ddf49b9SNikita Popov return unpackAllocSizeArgs(getRawIntAttr(Attribute::AllocSize));
1654278199f6SGeorge Burgess IV }
1655278199f6SGeorge Burgess IV
getVScaleRangeMin() const16560395e015SCullen Rhodes unsigned AttrBuilder::getVScaleRangeMin() const {
16570395e015SCullen Rhodes return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)).first;
16580395e015SCullen Rhodes }
16590395e015SCullen Rhodes
getVScaleRangeMax() const16600395e015SCullen Rhodes Optional<unsigned> AttrBuilder::getVScaleRangeMax() const {
16610395e015SCullen Rhodes return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)).second;
166248f5a392SBradley Smith }
166348f5a392SBradley Smith
addAlignmentAttr(MaybeAlign Align)166417f5d2b1SGuillaume Chatelet AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1665a7b6a7c8SGuillaume Chatelet if (!Align)
1666a7b6a7c8SGuillaume Chatelet return *this;
1667cd330348SBill Wendling
1668d096f8d3SRoman Lebedev assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
16695ddf49b9SNikita Popov return addRawIntAttr(Attribute::Alignment, Align->value());
1670ef860a24SChandler Carruth }
1671ef860a24SChandler Carruth
addStackAlignmentAttr(MaybeAlign Align)167217f5d2b1SGuillaume Chatelet AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1673cd330348SBill Wendling // Default alignment, allow the target to define how to align it.
1674a7b6a7c8SGuillaume Chatelet if (!Align)
1675a7b6a7c8SGuillaume Chatelet return *this;
1676cd330348SBill Wendling
1677a7b6a7c8SGuillaume Chatelet assert(*Align <= 0x100 && "Alignment too large.");
16785ddf49b9SNikita Popov return addRawIntAttr(Attribute::StackAlignment, Align->value());
1679cd330348SBill Wendling }
1680cd330348SBill Wendling
addDereferenceableAttr(uint64_t Bytes)1681b0407ba0SHal Finkel AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1682b0407ba0SHal Finkel if (Bytes == 0) return *this;
1683b0407ba0SHal Finkel
16845ddf49b9SNikita Popov return addRawIntAttr(Attribute::Dereferenceable, Bytes);
1685b0407ba0SHal Finkel }
1686b0407ba0SHal Finkel
addDereferenceableOrNullAttr(uint64_t Bytes)168731ea6d15SSanjoy Das AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
168831ea6d15SSanjoy Das if (Bytes == 0)
168931ea6d15SSanjoy Das return *this;
169031ea6d15SSanjoy Das
16915ddf49b9SNikita Popov return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
169231ea6d15SSanjoy Das }
169331ea6d15SSanjoy Das
addAllocSizeAttr(unsigned ElemSize,const Optional<unsigned> & NumElems)1694278199f6SGeorge Burgess IV AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1695278199f6SGeorge Burgess IV const Optional<unsigned> &NumElems) {
1696278199f6SGeorge Burgess IV return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1697278199f6SGeorge Burgess IV }
1698278199f6SGeorge Burgess IV
addAllocSizeAttrFromRawRepr(uint64_t RawArgs)1699278199f6SGeorge Burgess IV AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1700278199f6SGeorge Burgess IV // (0, 0) is our "not present" value, so we need to check for it here.
1701278199f6SGeorge Burgess IV assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
17025ddf49b9SNikita Popov return addRawIntAttr(Attribute::AllocSize, RawArgs);
1703278199f6SGeorge Burgess IV }
1704278199f6SGeorge Burgess IV
addVScaleRangeAttr(unsigned MinValue,Optional<unsigned> MaxValue)170548f5a392SBradley Smith AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
17060395e015SCullen Rhodes Optional<unsigned> MaxValue) {
170748f5a392SBradley Smith return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
170848f5a392SBradley Smith }
170948f5a392SBradley Smith
addVScaleRangeAttrFromRawRepr(uint64_t RawArgs)171048f5a392SBradley Smith AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
171148f5a392SBradley Smith // (0, 0) is not present hence ignore this case
171248f5a392SBradley Smith if (RawArgs == 0)
171348f5a392SBradley Smith return *this;
171448f5a392SBradley Smith
17155ddf49b9SNikita Popov return addRawIntAttr(Attribute::VScaleRange, RawArgs);
171648f5a392SBradley Smith }
171748f5a392SBradley Smith
addUWTableAttr(UWTableKind Kind)17186398903aSMomchil Velikov AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
17196398903aSMomchil Velikov if (Kind == UWTableKind::None)
17206398903aSMomchil Velikov return *this;
17216398903aSMomchil Velikov return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
17226398903aSMomchil Velikov }
17236398903aSMomchil Velikov
addAllocKindAttr(AllocFnKind Kind)172442861faaSAugie Fackler AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
172542861faaSAugie Fackler return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
172642861faaSAugie Fackler }
172742861faaSAugie Fackler
getTypeAttr(Attribute::AttrKind Kind) const17285d1464cbSNikita Popov Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
172942a68215SNikita Popov assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
173042a68215SNikita Popov Attribute A = getAttribute(Kind);
173142a68215SNikita Popov return A.isValid() ? A.getValueAsType() : nullptr;
17325d1464cbSNikita Popov }
17335d1464cbSNikita Popov
addTypeAttr(Attribute::AttrKind Kind,Type * Ty)173442cc7f3cSNikita Popov AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
173542a68215SNikita Popov return addAttribute(Attribute::get(Ctx, Kind, Ty));
1736b7141207STim Northover }
1737b7141207STim Northover
addByValAttr(Type * Ty)173842cc7f3cSNikita Popov AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
173942cc7f3cSNikita Popov return addTypeAttr(Attribute::ByVal, Ty);
174042cc7f3cSNikita Popov }
174142cc7f3cSNikita Popov
addStructRetAttr(Type * Ty)17420a7cd99aSMatt Arsenault AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
174342cc7f3cSNikita Popov return addTypeAttr(Attribute::StructRet, Ty);
17440a7cd99aSMatt Arsenault }
17450a7cd99aSMatt Arsenault
addByRefAttr(Type * Ty)17465e999cbeSMatt Arsenault AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
174742cc7f3cSNikita Popov return addTypeAttr(Attribute::ByRef, Ty);
17485e999cbeSMatt Arsenault }
17495e999cbeSMatt Arsenault
addPreallocatedAttr(Type * Ty)17503b0450acSArthur Eubanks AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
175142cc7f3cSNikita Popov return addTypeAttr(Attribute::Preallocated, Ty);
17523b0450acSArthur Eubanks }
17533b0450acSArthur Eubanks
addInAllocaAttr(Type * Ty)17549a0c9402SMatt Arsenault AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
175542cc7f3cSNikita Popov return addTypeAttr(Attribute::InAlloca, Ty);
17569a0c9402SMatt Arsenault }
17579a0c9402SMatt Arsenault
merge(const AttrBuilder & B)1758e261492fSBill Wendling AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
175942a68215SNikita Popov // TODO: Could make this O(n) as we're merging two sorted lists.
176042a68215SNikita Popov for (const auto &I : B.attrs())
1761d2cc6c2dSSerge Guelton addAttribute(I);
1762e261492fSBill Wendling
1763e261492fSBill Wendling return *this;
1764e261492fSBill Wendling }
1765e261492fSBill Wendling
remove(const AttributeMask & AM)17669290ccc3Sserge-sans-paille AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
176742a68215SNikita Popov erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
1768d2a44619SPete Cooper return *this;
1769d2a44619SPete Cooper }
1770d2a44619SPete Cooper
overlaps(const AttributeMask & AM) const17719290ccc3Sserge-sans-paille bool AttrBuilder::overlaps(const AttributeMask &AM) const {
177242a68215SNikita Popov return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
1773d2a44619SPete Cooper }
1774d2a44619SPete Cooper
getAttribute(Attribute::AttrKind A) const177542a68215SNikita Popov Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
177642a68215SNikita Popov assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
177742a68215SNikita Popov auto It = lower_bound(Attrs, A, AttributeComparator());
177842a68215SNikita Popov if (It != Attrs.end() && It->hasAttribute(A))
177954132254SNikita Popov return *It;
178054132254SNikita Popov return {};
178154132254SNikita Popov }
178254132254SNikita Popov
getAttribute(StringRef A) const178342a68215SNikita Popov Attribute AttrBuilder::getAttribute(StringRef A) const {
178442a68215SNikita Popov auto It = lower_bound(Attrs, A, AttributeComparator());
178542a68215SNikita Popov if (It != Attrs.end() && It->hasAttribute(A))
178642a68215SNikita Popov return *It;
178742a68215SNikita Popov return {};
178842a68215SNikita Popov }
178942a68215SNikita Popov
contains(Attribute::AttrKind A) const179042a68215SNikita Popov bool AttrBuilder::contains(Attribute::AttrKind A) const {
179154132254SNikita Popov return getAttribute(A).isValid();
17924b00144eSBill Wendling }
17934b00144eSBill Wendling
contains(StringRef A) const179442a68215SNikita Popov bool AttrBuilder::contains(StringRef A) const {
179542a68215SNikita Popov return getAttribute(A).isValid();
1796ef860a24SChandler Carruth }
17979ac69f9dSBill Wendling
hasAlignmentAttr() const1798ef860a24SChandler Carruth bool AttrBuilder::hasAlignmentAttr() const {
17995ddf49b9SNikita Popov return getRawIntAttr(Attribute::Alignment) != 0;
1800ef860a24SChandler Carruth }
1801ef860a24SChandler Carruth
operator ==(const AttrBuilder & B) const180292310454SBarry Revzin bool AttrBuilder::operator==(const AttrBuilder &B) const {
180342a68215SNikita Popov return Attrs == B.Attrs;
1804d509a665SBill Wendling }
1805d509a665SBill Wendling
180657625a49SBill Wendling //===----------------------------------------------------------------------===//
180757625a49SBill Wendling // AttributeFuncs Function Defintions
180857625a49SBill Wendling //===----------------------------------------------------------------------===//
180957625a49SBill Wendling
18105f8f34e4SAdrian Prantl /// Which attributes cannot be applied to a type.
typeIncompatible(Type * Ty,AttributeSafetyKind ASK)1811bb0b2317SJohannes Doerfert AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
1812bb0b2317SJohannes Doerfert AttributeSafetyKind ASK) {
18139290ccc3Sserge-sans-paille AttributeMask Incompatible;
181457625a49SBill Wendling
1815bb0b2317SJohannes Doerfert if (!Ty->isIntegerTy()) {
1816d7627940SFraser Cormack // Attributes that only apply to integers.
1817bb0b2317SJohannes Doerfert if (ASK & ASK_SAFE_TO_DROP)
1818bb0b2317SJohannes Doerfert Incompatible.addAttribute(Attribute::AllocAlign);
1819bb0b2317SJohannes Doerfert if (ASK & ASK_UNSAFE_TO_DROP)
1820bb0b2317SJohannes Doerfert Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
1821bb0b2317SJohannes Doerfert }
182257625a49SBill Wendling
1823bb0b2317SJohannes Doerfert if (!Ty->isPointerTy()) {
1824d7627940SFraser Cormack // Attributes that only apply to pointers.
1825bb0b2317SJohannes Doerfert if (ASK & ASK_SAFE_TO_DROP)
1826bb0b2317SJohannes Doerfert Incompatible.addAttribute(Attribute::NoAlias)
182757625a49SBill Wendling .addAttribute(Attribute::NoCapture)
1828d52b1528SNick Lewycky .addAttribute(Attribute::NonNull)
18295e4b33feSNikita Popov .addAttribute(Attribute::ReadNone)
18305e4b33feSNikita Popov .addAttribute(Attribute::ReadOnly)
18319290ccc3Sserge-sans-paille .addAttribute(Attribute::Dereferenceable)
1832bb0b2317SJohannes Doerfert .addAttribute(Attribute::DereferenceableOrNull);
1833bb0b2317SJohannes Doerfert if (ASK & ASK_UNSAFE_TO_DROP)
1834bb0b2317SJohannes Doerfert Incompatible.addAttribute(Attribute::Nest)
1835bb0b2317SJohannes Doerfert .addAttribute(Attribute::SwiftError)
18369290ccc3Sserge-sans-paille .addAttribute(Attribute::Preallocated)
18379290ccc3Sserge-sans-paille .addAttribute(Attribute::InAlloca)
18389290ccc3Sserge-sans-paille .addAttribute(Attribute::ByVal)
18399290ccc3Sserge-sans-paille .addAttribute(Attribute::StructRet)
18409290ccc3Sserge-sans-paille .addAttribute(Attribute::ByRef)
1841a907d36cSAugie Fackler .addAttribute(Attribute::ElementType)
1842a907d36cSAugie Fackler .addAttribute(Attribute::AllocatedPointer);
1843bb0b2317SJohannes Doerfert }
184457625a49SBill Wendling
1845d7627940SFraser Cormack // Attributes that only apply to pointers or vectors of pointers.
1846bb0b2317SJohannes Doerfert if (!Ty->isPtrOrPtrVectorTy()) {
1847bb0b2317SJohannes Doerfert if (ASK & ASK_SAFE_TO_DROP)
18489290ccc3Sserge-sans-paille Incompatible.addAttribute(Attribute::Alignment);
1849bb0b2317SJohannes Doerfert }
1850d7627940SFraser Cormack
1851ef48436eSJohannes Doerfert // Some attributes can apply to all "values" but there are no `void` values.
1852bb0b2317SJohannes Doerfert if (Ty->isVoidTy()) {
1853bb0b2317SJohannes Doerfert if (ASK & ASK_SAFE_TO_DROP)
1854ef48436eSJohannes Doerfert Incompatible.addAttribute(Attribute::NoUndef);
1855bb0b2317SJohannes Doerfert }
1856ef48436eSJohannes Doerfert
18572777d887SPete Cooper return Incompatible;
185857625a49SBill Wendling }
18591cb242ebSAkira Hatanaka
getUBImplyingAttributes()18609290ccc3Sserge-sans-paille AttributeMask AttributeFuncs::getUBImplyingAttributes() {
18619290ccc3Sserge-sans-paille AttributeMask AM;
18629290ccc3Sserge-sans-paille AM.addAttribute(Attribute::NoUndef);
18639290ccc3Sserge-sans-paille AM.addAttribute(Attribute::Dereferenceable);
18649290ccc3Sserge-sans-paille AM.addAttribute(Attribute::DereferenceableOrNull);
18659290ccc3Sserge-sans-paille return AM;
1866087a8eeaSNikita Popov }
1867087a8eeaSNikita Popov
18681cb242ebSAkira Hatanaka template<typename AttrClass>
isEqual(const Function & Caller,const Function & Callee)18691cb242ebSAkira Hatanaka static bool isEqual(const Function &Caller, const Function &Callee) {
18701cb242ebSAkira Hatanaka return Caller.getFnAttribute(AttrClass::getKind()) ==
18711cb242ebSAkira Hatanaka Callee.getFnAttribute(AttrClass::getKind());
18721cb242ebSAkira Hatanaka }
18731cb242ebSAkira Hatanaka
18745f8f34e4SAdrian Prantl /// Compute the logical AND of the attributes of the caller and the
18751cb242ebSAkira Hatanaka /// callee.
18761cb242ebSAkira Hatanaka ///
18771cb242ebSAkira Hatanaka /// This function sets the caller's attribute to false if the callee's attribute
18781cb242ebSAkira Hatanaka /// is false.
18791cb242ebSAkira Hatanaka template<typename AttrClass>
setAND(Function & Caller,const Function & Callee)18801cb242ebSAkira Hatanaka static void setAND(Function &Caller, const Function &Callee) {
18811cb242ebSAkira Hatanaka if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
18821cb242ebSAkira Hatanaka !AttrClass::isSet(Callee, AttrClass::getKind()))
18831cb242ebSAkira Hatanaka AttrClass::set(Caller, AttrClass::getKind(), false);
18841cb242ebSAkira Hatanaka }
18851cb242ebSAkira Hatanaka
18865f8f34e4SAdrian Prantl /// Compute the logical OR of the attributes of the caller and the
18871cb242ebSAkira Hatanaka /// callee.
18881cb242ebSAkira Hatanaka ///
18891cb242ebSAkira Hatanaka /// This function sets the caller's attribute to true if the callee's attribute
18901cb242ebSAkira Hatanaka /// is true.
18911cb242ebSAkira Hatanaka template<typename AttrClass>
setOR(Function & Caller,const Function & Callee)18921cb242ebSAkira Hatanaka static void setOR(Function &Caller, const Function &Callee) {
18931cb242ebSAkira Hatanaka if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
18941cb242ebSAkira Hatanaka AttrClass::isSet(Callee, AttrClass::getKind()))
18951cb242ebSAkira Hatanaka AttrClass::set(Caller, AttrClass::getKind(), true);
18961cb242ebSAkira Hatanaka }
18971cb242ebSAkira Hatanaka
18985f8f34e4SAdrian Prantl /// If the inlined function had a higher stack protection level than the
18991cb242ebSAkira Hatanaka /// calling function, then bump up the caller's stack protection level.
adjustCallerSSPLevel(Function & Caller,const Function & Callee)19001cb242ebSAkira Hatanaka static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
19012bc57d85SHans Wennborg // If the calling function has *no* stack protection level (e.g. it was built
19022bc57d85SHans Wennborg // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
19032bc57d85SHans Wennborg // change it as that could change the program's semantics.
19042bc57d85SHans Wennborg if (!Caller.hasStackProtectorFnAttr())
19052bc57d85SHans Wennborg return;
19062bc57d85SHans Wennborg
19071cb242ebSAkira Hatanaka // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1908f4c6080aSNick Desaulniers // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1909f4c6080aSNick Desaulniers // clutter to the IR.
19109290ccc3Sserge-sans-paille AttributeMask OldSSPAttr;
1911ee4930b6SReid Kleckner OldSSPAttr.addAttribute(Attribute::StackProtect)
19121cb242ebSAkira Hatanaka .addAttribute(Attribute::StackProtectStrong)
19131cb242ebSAkira Hatanaka .addAttribute(Attribute::StackProtectReq);
19141cb242ebSAkira Hatanaka
1915f17120a8SEvgeniy Stepanov if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1916ad727ab7SArthur Eubanks Caller.removeFnAttrs(OldSSPAttr);
19171cb242ebSAkira Hatanaka Caller.addFnAttr(Attribute::StackProtectReq);
19181cb242ebSAkira Hatanaka } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
19191cb242ebSAkira Hatanaka !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1920ad727ab7SArthur Eubanks Caller.removeFnAttrs(OldSSPAttr);
19211cb242ebSAkira Hatanaka Caller.addFnAttr(Attribute::StackProtectStrong);
19221cb242ebSAkira Hatanaka } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
19231cb242ebSAkira Hatanaka !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
19241cb242ebSAkira Hatanaka !Caller.hasFnAttribute(Attribute::StackProtectStrong))
19251cb242ebSAkira Hatanaka Caller.addFnAttr(Attribute::StackProtect);
19261cb242ebSAkira Hatanaka }
19271cb242ebSAkira Hatanaka
19285f8f34e4SAdrian Prantl /// If the inlined function required stack probes, then ensure that
1929ed54b4a7Swhitequark /// the calling function has those too.
adjustCallerStackProbes(Function & Caller,const Function & Callee)1930ed54b4a7Swhitequark static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
193108b20356Swhitequark if (!Caller.hasFnAttribute("probe-stack") &&
193208b20356Swhitequark Callee.hasFnAttribute("probe-stack")) {
193308b20356Swhitequark Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
193408b20356Swhitequark }
193508b20356Swhitequark }
193608b20356Swhitequark
19375f8f34e4SAdrian Prantl /// If the inlined function defines the size of guard region
193808b20356Swhitequark /// on the stack, then ensure that the calling function defines a guard region
193908b20356Swhitequark /// that is no larger.
194008b20356Swhitequark static void
adjustCallerStackProbeSize(Function & Caller,const Function & Callee)194108b20356Swhitequark adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
19426dcd9f51SCraig Topper Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
19436dcd9f51SCraig Topper if (CalleeAttr.isValid()) {
19446dcd9f51SCraig Topper Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
19456dcd9f51SCraig Topper if (CallerAttr.isValid()) {
19466dcd9f51SCraig Topper uint64_t CallerStackProbeSize, CalleeStackProbeSize;
19476dcd9f51SCraig Topper CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
19486dcd9f51SCraig Topper CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
19496dcd9f51SCraig Topper
195008b20356Swhitequark if (CallerStackProbeSize > CalleeStackProbeSize) {
19516dcd9f51SCraig Topper Caller.addFnAttr(CalleeAttr);
195208b20356Swhitequark }
195308b20356Swhitequark } else {
19546dcd9f51SCraig Topper Caller.addFnAttr(CalleeAttr);
195508b20356Swhitequark }
195608b20356Swhitequark }
1957ed54b4a7Swhitequark }
1958ed54b4a7Swhitequark
19591d504f77SCraig Topper /// If the inlined function defines a min legal vector width, then ensure
1960961b956eSCraig Topper /// the calling function has the same or larger min legal vector width. If the
1961961b956eSCraig Topper /// caller has the attribute, but the callee doesn't, we need to remove the
1962961b956eSCraig Topper /// attribute from the caller since we can't make any guarantees about the
1963961b956eSCraig Topper /// caller's requirements.
1964961b956eSCraig Topper /// This function is called after the inlining decision has been made so we have
1965961b956eSCraig Topper /// to merge the attribute this way. Heuristics that would use
19661d504f77SCraig Topper /// min-legal-vector-width to determine inline compatibility would need to be
19671d504f77SCraig Topper /// handled as part of inline cost analysis.
19681d504f77SCraig Topper static void
adjustMinLegalVectorWidth(Function & Caller,const Function & Callee)19691d504f77SCraig Topper adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
19706dcd9f51SCraig Topper Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
19716dcd9f51SCraig Topper if (CallerAttr.isValid()) {
19726dcd9f51SCraig Topper Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
19736dcd9f51SCraig Topper if (CalleeAttr.isValid()) {
19746dcd9f51SCraig Topper uint64_t CallerVectorWidth, CalleeVectorWidth;
19756dcd9f51SCraig Topper CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
19766dcd9f51SCraig Topper CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
1977961b956eSCraig Topper if (CallerVectorWidth < CalleeVectorWidth)
19786dcd9f51SCraig Topper Caller.addFnAttr(CalleeAttr);
19791d504f77SCraig Topper } else {
1980961b956eSCraig Topper // If the callee doesn't have the attribute then we don't know anything
1981961b956eSCraig Topper // and must drop the attribute from the caller.
1982961b956eSCraig Topper Caller.removeFnAttr("min-legal-vector-width");
19831d504f77SCraig Topper }
19841d504f77SCraig Topper }
19851d504f77SCraig Topper }
19861d504f77SCraig Topper
1987f89f7da9SNikita Popov /// If the inlined function has null_pointer_is_valid attribute,
19889d83ce90SManoj Gupta /// set this attribute in the caller post inlining.
19899d83ce90SManoj Gupta static void
adjustNullPointerValidAttr(Function & Caller,const Function & Callee)19909d83ce90SManoj Gupta adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
19919d83ce90SManoj Gupta if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
1992f89f7da9SNikita Popov Caller.addFnAttr(Attribute::NullPointerIsValid);
19939d83ce90SManoj Gupta }
19949d83ce90SManoj Gupta }
19959d83ce90SManoj Gupta
1996cfe87a4aSTyker struct EnumAttr {
isSetEnumAttr1997cfe87a4aSTyker static bool isSet(const Function &Fn,
1998cfe87a4aSTyker Attribute::AttrKind Kind) {
1999cfe87a4aSTyker return Fn.hasFnAttribute(Kind);
2000cfe87a4aSTyker }
2001cfe87a4aSTyker
setEnumAttr2002cfe87a4aSTyker static void set(Function &Fn,
2003cfe87a4aSTyker Attribute::AttrKind Kind, bool Val) {
2004cfe87a4aSTyker if (Val)
2005cfe87a4aSTyker Fn.addFnAttr(Kind);
2006cfe87a4aSTyker else
2007cfe87a4aSTyker Fn.removeFnAttr(Kind);
2008cfe87a4aSTyker }
2009cfe87a4aSTyker };
2010cfe87a4aSTyker
2011cfe87a4aSTyker struct StrBoolAttr {
isSetStrBoolAttr2012cfe87a4aSTyker static bool isSet(const Function &Fn,
2013cfe87a4aSTyker StringRef Kind) {
2014cfe87a4aSTyker auto A = Fn.getFnAttribute(Kind);
2015cfe87a4aSTyker return A.getValueAsString().equals("true");
2016cfe87a4aSTyker }
2017cfe87a4aSTyker
setStrBoolAttr2018cfe87a4aSTyker static void set(Function &Fn,
2019cfe87a4aSTyker StringRef Kind, bool Val) {
2020cfe87a4aSTyker Fn.addFnAttr(Kind, Val ? "true" : "false");
2021cfe87a4aSTyker }
2022cfe87a4aSTyker };
2023cfe87a4aSTyker
2024cfe87a4aSTyker #define GET_ATTR_NAMES
2025cfe87a4aSTyker #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2026cfe87a4aSTyker struct ENUM_NAME##Attr : EnumAttr { \
2027cfe87a4aSTyker static enum Attribute::AttrKind getKind() { \
2028cfe87a4aSTyker return llvm::Attribute::ENUM_NAME; \
2029cfe87a4aSTyker } \
2030cfe87a4aSTyker };
2031cfe87a4aSTyker #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2032cfe87a4aSTyker struct ENUM_NAME##Attr : StrBoolAttr { \
2033cfe87a4aSTyker static StringRef getKind() { return #DISPLAY_NAME; } \
2034cfe87a4aSTyker };
2035cfe87a4aSTyker #include "llvm/IR/Attributes.inc"
2036cfe87a4aSTyker
20371cb242ebSAkira Hatanaka #define GET_ATTR_COMPAT_FUNC
2038cfe87a4aSTyker #include "llvm/IR/Attributes.inc"
20391cb242ebSAkira Hatanaka
areInlineCompatible(const Function & Caller,const Function & Callee)20401cb242ebSAkira Hatanaka bool AttributeFuncs::areInlineCompatible(const Function &Caller,
20411cb242ebSAkira Hatanaka const Function &Callee) {
20421cb242ebSAkira Hatanaka return hasCompatibleFnAttrs(Caller, Callee);
20431cb242ebSAkira Hatanaka }
20441cb242ebSAkira Hatanaka
areOutlineCompatible(const Function & A,const Function & B)20451a9eb19aSAndrew Litteken bool AttributeFuncs::areOutlineCompatible(const Function &A,
20461a9eb19aSAndrew Litteken const Function &B) {
20471a9eb19aSAndrew Litteken return hasCompatibleFnAttrs(A, B);
20481a9eb19aSAndrew Litteken }
20491a9eb19aSAndrew Litteken
mergeAttributesForInlining(Function & Caller,const Function & Callee)20501cb242ebSAkira Hatanaka void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
20511cb242ebSAkira Hatanaka const Function &Callee) {
20521cb242ebSAkira Hatanaka mergeFnAttrs(Caller, Callee);
20531cb242ebSAkira Hatanaka }
20541a9eb19aSAndrew Litteken
mergeAttributesForOutlining(Function & Base,const Function & ToMerge)20551a9eb19aSAndrew Litteken void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
20561a9eb19aSAndrew Litteken const Function &ToMerge) {
20571a9eb19aSAndrew Litteken
20581a9eb19aSAndrew Litteken // We merge functions so that they meet the most general case.
20591a9eb19aSAndrew Litteken // For example, if the NoNansFPMathAttr is set in one function, but not in
20601a9eb19aSAndrew Litteken // the other, in the merged function we can say that the NoNansFPMathAttr
20611a9eb19aSAndrew Litteken // is not set.
20621a9eb19aSAndrew Litteken // However if we have the SpeculativeLoadHardeningAttr set true in one
20631a9eb19aSAndrew Litteken // function, but not the other, we make sure that the function retains
20641a9eb19aSAndrew Litteken // that aspect in the merged function.
20651a9eb19aSAndrew Litteken mergeFnAttrs(Base, ToMerge);
20661a9eb19aSAndrew Litteken }
20677c044542SPhoebe Wang
updateMinLegalVectorWidthAttr(Function & Fn,uint64_t Width)20687c044542SPhoebe Wang void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
20697c044542SPhoebe Wang uint64_t Width) {
20707c044542SPhoebe Wang Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
20717c044542SPhoebe Wang if (Attr.isValid()) {
20727c044542SPhoebe Wang uint64_t OldWidth;
20737c044542SPhoebe Wang Attr.getValueAsString().getAsInteger(0, OldWidth);
20747c044542SPhoebe Wang if (Width > OldWidth)
20757c044542SPhoebe Wang Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
20767c044542SPhoebe Wang }
20777c044542SPhoebe Wang }
2078