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