10b57cec5SDimitry Andric //===- Attributes.cpp - Implement AttributesList --------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // \file 100b57cec5SDimitry Andric // This file implements the Attribute, AttributeImpl, AttrBuilder, 110b57cec5SDimitry Andric // AttributeListImpl, and AttributeList classes. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 160b57cec5SDimitry Andric #include "AttributeImpl.h" 170b57cec5SDimitry Andric #include "LLVMContextImpl.h" 180b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 190b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h" 200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 220b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 245ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 250b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 2606c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h" 27*0fca6ea1SDimitry Andric #include "llvm/IR/ConstantRange.h" 28*0fca6ea1SDimitry Andric #include "llvm/IR/ConstantRangeList.h" 290b57cec5SDimitry Andric #include "llvm/IR/Function.h" 300b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 310b57cec5SDimitry Andric #include "llvm/IR/Type.h" 320b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 34bdd1243dSDimitry Andric #include "llvm/Support/ModRef.h" 350b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 360b57cec5SDimitry Andric #include <algorithm> 370b57cec5SDimitry Andric #include <cassert> 380b57cec5SDimitry Andric #include <cstddef> 390b57cec5SDimitry Andric #include <cstdint> 400b57cec5SDimitry Andric #include <limits> 41bdd1243dSDimitry Andric #include <optional> 420b57cec5SDimitry Andric #include <string> 430b57cec5SDimitry Andric #include <tuple> 440b57cec5SDimitry Andric #include <utility> 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric using namespace llvm; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 490b57cec5SDimitry Andric // Attribute Construction Methods 500b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // allocsize has two integer arguments, but because they're both 32 bits, we can 530b57cec5SDimitry Andric // pack them into one 64-bit value, at the cost of making said value 540b57cec5SDimitry Andric // nonsensical. 550b57cec5SDimitry Andric // 560b57cec5SDimitry Andric // In order to do this, we need to reserve one value of the second (optional) 570b57cec5SDimitry Andric // allocsize argument to signify "not present." 580b57cec5SDimitry Andric static const unsigned AllocSizeNumElemsNotPresent = -1; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric static uint64_t packAllocSizeArgs(unsigned ElemSizeArg, 61bdd1243dSDimitry Andric const std::optional<unsigned> &NumElemsArg) { 6281ad6265SDimitry Andric assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) && 630b57cec5SDimitry Andric "Attempting to pack a reserved value"); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric return uint64_t(ElemSizeArg) << 32 | 6681ad6265SDimitry Andric NumElemsArg.value_or(AllocSizeNumElemsNotPresent); 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 69bdd1243dSDimitry Andric static std::pair<unsigned, std::optional<unsigned>> 700b57cec5SDimitry Andric unpackAllocSizeArgs(uint64_t Num) { 710b57cec5SDimitry Andric unsigned NumElems = Num & std::numeric_limits<unsigned>::max(); 720b57cec5SDimitry Andric unsigned ElemSizeArg = Num >> 32; 730b57cec5SDimitry Andric 74bdd1243dSDimitry Andric std::optional<unsigned> NumElemsArg; 750b57cec5SDimitry Andric if (NumElems != AllocSizeNumElemsNotPresent) 760b57cec5SDimitry Andric NumElemsArg = NumElems; 770b57cec5SDimitry Andric return std::make_pair(ElemSizeArg, NumElemsArg); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800eae32dcSDimitry Andric static uint64_t packVScaleRangeArgs(unsigned MinValue, 81bdd1243dSDimitry Andric std::optional<unsigned> MaxValue) { 8281ad6265SDimitry Andric return uint64_t(MinValue) << 32 | MaxValue.value_or(0); 83fe6060f1SDimitry Andric } 84fe6060f1SDimitry Andric 85bdd1243dSDimitry Andric static std::pair<unsigned, std::optional<unsigned>> 860eae32dcSDimitry Andric unpackVScaleRangeArgs(uint64_t Value) { 87fe6060f1SDimitry Andric unsigned MaxValue = Value & std::numeric_limits<unsigned>::max(); 88fe6060f1SDimitry Andric unsigned MinValue = Value >> 32; 89fe6060f1SDimitry Andric 900eae32dcSDimitry Andric return std::make_pair(MinValue, 91bdd1243dSDimitry Andric MaxValue > 0 ? MaxValue : std::optional<unsigned>()); 92fe6060f1SDimitry Andric } 93fe6060f1SDimitry Andric 940b57cec5SDimitry Andric Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, 950b57cec5SDimitry Andric uint64_t Val) { 96bdd1243dSDimitry Andric bool IsIntAttr = Attribute::isIntAttrKind(Kind); 97bdd1243dSDimitry Andric assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) && 98bdd1243dSDimitry Andric "Not an enum or int attribute"); 99fe6060f1SDimitry Andric 1000b57cec5SDimitry Andric LLVMContextImpl *pImpl = Context.pImpl; 1010b57cec5SDimitry Andric FoldingSetNodeID ID; 1020b57cec5SDimitry Andric ID.AddInteger(Kind); 103bdd1243dSDimitry Andric if (IsIntAttr) 104bdd1243dSDimitry Andric ID.AddInteger(Val); 105bdd1243dSDimitry Andric else 106bdd1243dSDimitry Andric assert(Val == 0 && "Value must be zero for enum attributes"); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric void *InsertPoint; 1090b57cec5SDimitry Andric AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric if (!PA) { 1120b57cec5SDimitry Andric // If we didn't find any existing attributes of the same shape then create a 1130b57cec5SDimitry Andric // new one and insert it. 114bdd1243dSDimitry Andric if (!IsIntAttr) 1155ffd83dbSDimitry Andric PA = new (pImpl->Alloc) EnumAttributeImpl(Kind); 1160b57cec5SDimitry Andric else 1175ffd83dbSDimitry Andric PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val); 1180b57cec5SDimitry Andric pImpl->AttrsSet.InsertNode(PA, InsertPoint); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // Return the Attribute that we found or created. 1220b57cec5SDimitry Andric return Attribute(PA); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { 1260b57cec5SDimitry Andric LLVMContextImpl *pImpl = Context.pImpl; 1270b57cec5SDimitry Andric FoldingSetNodeID ID; 1280b57cec5SDimitry Andric ID.AddString(Kind); 1290b57cec5SDimitry Andric if (!Val.empty()) ID.AddString(Val); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric void *InsertPoint; 1320b57cec5SDimitry Andric AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric if (!PA) { 1350b57cec5SDimitry Andric // If we didn't find any existing attributes of the same shape then create a 1360b57cec5SDimitry Andric // new one and insert it. 1375ffd83dbSDimitry Andric void *Mem = 1385ffd83dbSDimitry Andric pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val), 1395ffd83dbSDimitry Andric alignof(StringAttributeImpl)); 1405ffd83dbSDimitry Andric PA = new (Mem) StringAttributeImpl(Kind, Val); 1410b57cec5SDimitry Andric pImpl->AttrsSet.InsertNode(PA, InsertPoint); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // Return the Attribute that we found or created. 1450b57cec5SDimitry Andric return Attribute(PA); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, 1490b57cec5SDimitry Andric Type *Ty) { 150fe6060f1SDimitry Andric assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute"); 1510b57cec5SDimitry Andric LLVMContextImpl *pImpl = Context.pImpl; 1520b57cec5SDimitry Andric FoldingSetNodeID ID; 1530b57cec5SDimitry Andric ID.AddInteger(Kind); 1540b57cec5SDimitry Andric ID.AddPointer(Ty); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric void *InsertPoint; 1570b57cec5SDimitry Andric AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric if (!PA) { 1600b57cec5SDimitry Andric // If we didn't find any existing attributes of the same shape then create a 1610b57cec5SDimitry Andric // new one and insert it. 1625ffd83dbSDimitry Andric PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty); 1630b57cec5SDimitry Andric pImpl->AttrsSet.InsertNode(PA, InsertPoint); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric // Return the Attribute that we found or created. 1670b57cec5SDimitry Andric return Attribute(PA); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 170*0fca6ea1SDimitry Andric Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, 171*0fca6ea1SDimitry Andric const ConstantRange &CR) { 172*0fca6ea1SDimitry Andric assert(Attribute::isConstantRangeAttrKind(Kind) && 173*0fca6ea1SDimitry Andric "Not a ConstantRange attribute"); 174*0fca6ea1SDimitry Andric LLVMContextImpl *pImpl = Context.pImpl; 175*0fca6ea1SDimitry Andric FoldingSetNodeID ID; 176*0fca6ea1SDimitry Andric ID.AddInteger(Kind); 177*0fca6ea1SDimitry Andric CR.getLower().Profile(ID); 178*0fca6ea1SDimitry Andric CR.getUpper().Profile(ID); 179*0fca6ea1SDimitry Andric 180*0fca6ea1SDimitry Andric void *InsertPoint; 181*0fca6ea1SDimitry Andric AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 182*0fca6ea1SDimitry Andric 183*0fca6ea1SDimitry Andric if (!PA) { 184*0fca6ea1SDimitry Andric // If we didn't find any existing attributes of the same shape then create a 185*0fca6ea1SDimitry Andric // new one and insert it. 186*0fca6ea1SDimitry Andric PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate()) 187*0fca6ea1SDimitry Andric ConstantRangeAttributeImpl(Kind, CR); 188*0fca6ea1SDimitry Andric pImpl->AttrsSet.InsertNode(PA, InsertPoint); 189*0fca6ea1SDimitry Andric } 190*0fca6ea1SDimitry Andric 191*0fca6ea1SDimitry Andric // Return the Attribute that we found or created. 192*0fca6ea1SDimitry Andric return Attribute(PA); 193*0fca6ea1SDimitry Andric } 194*0fca6ea1SDimitry Andric 195*0fca6ea1SDimitry Andric Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, 196*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> Val) { 197*0fca6ea1SDimitry Andric assert(Attribute::isConstantRangeListAttrKind(Kind) && 198*0fca6ea1SDimitry Andric "Not a ConstantRangeList attribute"); 199*0fca6ea1SDimitry Andric LLVMContextImpl *pImpl = Context.pImpl; 200*0fca6ea1SDimitry Andric FoldingSetNodeID ID; 201*0fca6ea1SDimitry Andric ID.AddInteger(Kind); 202*0fca6ea1SDimitry Andric ID.AddInteger(Val.size()); 203*0fca6ea1SDimitry Andric for (auto &CR : Val) { 204*0fca6ea1SDimitry Andric CR.getLower().Profile(ID); 205*0fca6ea1SDimitry Andric CR.getUpper().Profile(ID); 206*0fca6ea1SDimitry Andric } 207*0fca6ea1SDimitry Andric 208*0fca6ea1SDimitry Andric void *InsertPoint; 209*0fca6ea1SDimitry Andric AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 210*0fca6ea1SDimitry Andric 211*0fca6ea1SDimitry Andric if (!PA) { 212*0fca6ea1SDimitry Andric // If we didn't find any existing attributes of the same shape then create a 213*0fca6ea1SDimitry Andric // new one and insert it. 214*0fca6ea1SDimitry Andric // ConstantRangeListAttributeImpl is a dynamically sized class and cannot 215*0fca6ea1SDimitry Andric // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for 216*0fca6ea1SDimitry Andric // allocation and record the allocated pointer in 217*0fca6ea1SDimitry Andric // `ConstantRangeListAttributes`. LLVMContext destructor will call the 218*0fca6ea1SDimitry Andric // destructor of the allocated pointer explicitly. 219*0fca6ea1SDimitry Andric void *Mem = pImpl->Alloc.Allocate( 220*0fca6ea1SDimitry Andric ConstantRangeListAttributeImpl::totalSizeToAlloc(Val), 221*0fca6ea1SDimitry Andric alignof(ConstantRangeListAttributeImpl)); 222*0fca6ea1SDimitry Andric PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val); 223*0fca6ea1SDimitry Andric pImpl->AttrsSet.InsertNode(PA, InsertPoint); 224*0fca6ea1SDimitry Andric pImpl->ConstantRangeListAttributes.push_back( 225*0fca6ea1SDimitry Andric reinterpret_cast<ConstantRangeListAttributeImpl *>(PA)); 226*0fca6ea1SDimitry Andric } 227*0fca6ea1SDimitry Andric 228*0fca6ea1SDimitry Andric // Return the Attribute that we found or created. 229*0fca6ea1SDimitry Andric return Attribute(PA); 230*0fca6ea1SDimitry Andric } 231*0fca6ea1SDimitry Andric 2328bcb0991SDimitry Andric Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) { 2335ffd83dbSDimitry Andric assert(A <= llvm::Value::MaximumAlignment && "Alignment too large."); 2348bcb0991SDimitry Andric return get(Context, Alignment, A.value()); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2378bcb0991SDimitry Andric Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) { 2388bcb0991SDimitry Andric assert(A <= 0x100 && "Alignment too large."); 2398bcb0991SDimitry Andric return get(Context, StackAlignment, A.value()); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context, 2430b57cec5SDimitry Andric uint64_t Bytes) { 2440b57cec5SDimitry Andric assert(Bytes && "Bytes must be non-zero."); 2450b57cec5SDimitry Andric return get(Context, Dereferenceable, Bytes); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context, 2490b57cec5SDimitry Andric uint64_t Bytes) { 2500b57cec5SDimitry Andric assert(Bytes && "Bytes must be non-zero."); 2510b57cec5SDimitry Andric return get(Context, DereferenceableOrNull, Bytes); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) { 2550b57cec5SDimitry Andric return get(Context, ByVal, Ty); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 258e8d8bef9SDimitry Andric Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) { 259e8d8bef9SDimitry Andric return get(Context, StructRet, Ty); 260e8d8bef9SDimitry Andric } 261e8d8bef9SDimitry Andric 262e8d8bef9SDimitry Andric Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) { 263e8d8bef9SDimitry Andric return get(Context, ByRef, Ty); 264e8d8bef9SDimitry Andric } 265e8d8bef9SDimitry Andric 2665ffd83dbSDimitry Andric Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) { 2675ffd83dbSDimitry Andric return get(Context, Preallocated, Ty); 2685ffd83dbSDimitry Andric } 2695ffd83dbSDimitry Andric 270fe6060f1SDimitry Andric Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) { 271fe6060f1SDimitry Andric return get(Context, InAlloca, Ty); 272fe6060f1SDimitry Andric } 273fe6060f1SDimitry Andric 27481ad6265SDimitry Andric Attribute Attribute::getWithUWTableKind(LLVMContext &Context, 27581ad6265SDimitry Andric UWTableKind Kind) { 27681ad6265SDimitry Andric return get(Context, UWTable, uint64_t(Kind)); 27781ad6265SDimitry Andric } 27881ad6265SDimitry Andric 279bdd1243dSDimitry Andric Attribute Attribute::getWithMemoryEffects(LLVMContext &Context, 280bdd1243dSDimitry Andric MemoryEffects ME) { 281bdd1243dSDimitry Andric return get(Context, Memory, ME.toIntValue()); 282bdd1243dSDimitry Andric } 283bdd1243dSDimitry Andric 28406c3fb27SDimitry Andric Attribute Attribute::getWithNoFPClass(LLVMContext &Context, 28506c3fb27SDimitry Andric FPClassTest ClassMask) { 28606c3fb27SDimitry Andric return get(Context, NoFPClass, ClassMask); 28706c3fb27SDimitry Andric } 28806c3fb27SDimitry Andric 2890b57cec5SDimitry Andric Attribute 2900b57cec5SDimitry Andric Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, 291bdd1243dSDimitry Andric const std::optional<unsigned> &NumElemsArg) { 2920b57cec5SDimitry Andric assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) && 2930b57cec5SDimitry Andric "Invalid allocsize arguments -- given allocsize(0, 0)"); 2940b57cec5SDimitry Andric return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg)); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 297fe6060f1SDimitry Andric Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context, 298fe6060f1SDimitry Andric unsigned MinValue, 299fe6060f1SDimitry Andric unsigned MaxValue) { 300fe6060f1SDimitry Andric return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue)); 301fe6060f1SDimitry Andric } 302fe6060f1SDimitry Andric 3035ffd83dbSDimitry Andric Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) { 3045ffd83dbSDimitry Andric return StringSwitch<Attribute::AttrKind>(AttrName) 3055ffd83dbSDimitry Andric #define GET_ATTR_NAMES 3065ffd83dbSDimitry Andric #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \ 3075ffd83dbSDimitry Andric .Case(#DISPLAY_NAME, Attribute::ENUM_NAME) 3085ffd83dbSDimitry Andric #include "llvm/IR/Attributes.inc" 3095ffd83dbSDimitry Andric .Default(Attribute::None); 3105ffd83dbSDimitry Andric } 3115ffd83dbSDimitry Andric 3125ffd83dbSDimitry Andric StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) { 3135ffd83dbSDimitry Andric switch (AttrKind) { 3145ffd83dbSDimitry Andric #define GET_ATTR_NAMES 3155ffd83dbSDimitry Andric #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \ 3165ffd83dbSDimitry Andric case Attribute::ENUM_NAME: \ 3175ffd83dbSDimitry Andric return #DISPLAY_NAME; 3185ffd83dbSDimitry Andric #include "llvm/IR/Attributes.inc" 3195ffd83dbSDimitry Andric case Attribute::None: 3205ffd83dbSDimitry Andric return "none"; 3215ffd83dbSDimitry Andric default: 3225ffd83dbSDimitry Andric llvm_unreachable("invalid Kind"); 3235ffd83dbSDimitry Andric } 3245ffd83dbSDimitry Andric } 3255ffd83dbSDimitry Andric 3265ffd83dbSDimitry Andric bool Attribute::isExistingAttribute(StringRef Name) { 3275ffd83dbSDimitry Andric return StringSwitch<bool>(Name) 3285ffd83dbSDimitry Andric #define GET_ATTR_NAMES 3295ffd83dbSDimitry Andric #define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true) 3305ffd83dbSDimitry Andric #include "llvm/IR/Attributes.inc" 3315ffd83dbSDimitry Andric .Default(false); 3325ffd83dbSDimitry Andric } 3335ffd83dbSDimitry Andric 3340b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3350b57cec5SDimitry Andric // Attribute Accessor Methods 3360b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric bool Attribute::isEnumAttribute() const { 3390b57cec5SDimitry Andric return pImpl && pImpl->isEnumAttribute(); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric bool Attribute::isIntAttribute() const { 3430b57cec5SDimitry Andric return pImpl && pImpl->isIntAttribute(); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric bool Attribute::isStringAttribute() const { 3470b57cec5SDimitry Andric return pImpl && pImpl->isStringAttribute(); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool Attribute::isTypeAttribute() const { 3510b57cec5SDimitry Andric return pImpl && pImpl->isTypeAttribute(); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 354*0fca6ea1SDimitry Andric bool Attribute::isConstantRangeAttribute() const { 355*0fca6ea1SDimitry Andric return pImpl && pImpl->isConstantRangeAttribute(); 356*0fca6ea1SDimitry Andric } 357*0fca6ea1SDimitry Andric 358*0fca6ea1SDimitry Andric bool Attribute::isConstantRangeListAttribute() const { 359*0fca6ea1SDimitry Andric return pImpl && pImpl->isConstantRangeListAttribute(); 360*0fca6ea1SDimitry Andric } 361*0fca6ea1SDimitry Andric 3620b57cec5SDimitry Andric Attribute::AttrKind Attribute::getKindAsEnum() const { 3630b57cec5SDimitry Andric if (!pImpl) return None; 364*0fca6ea1SDimitry Andric assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute() || 365*0fca6ea1SDimitry Andric isConstantRangeAttribute() || isConstantRangeListAttribute()) && 3660b57cec5SDimitry Andric "Invalid attribute type to get the kind as an enum!"); 3670b57cec5SDimitry Andric return pImpl->getKindAsEnum(); 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric uint64_t Attribute::getValueAsInt() const { 3710b57cec5SDimitry Andric if (!pImpl) return 0; 3720b57cec5SDimitry Andric assert(isIntAttribute() && 3730b57cec5SDimitry Andric "Expected the attribute to be an integer attribute!"); 3740b57cec5SDimitry Andric return pImpl->getValueAsInt(); 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 377fe6060f1SDimitry Andric bool Attribute::getValueAsBool() const { 378fe6060f1SDimitry Andric if (!pImpl) return false; 379fe6060f1SDimitry Andric assert(isStringAttribute() && 380fe6060f1SDimitry Andric "Expected the attribute to be a string attribute!"); 381fe6060f1SDimitry Andric return pImpl->getValueAsBool(); 382fe6060f1SDimitry Andric } 383fe6060f1SDimitry Andric 3840b57cec5SDimitry Andric StringRef Attribute::getKindAsString() const { 3850b57cec5SDimitry Andric if (!pImpl) return {}; 3860b57cec5SDimitry Andric assert(isStringAttribute() && 3870b57cec5SDimitry Andric "Invalid attribute type to get the kind as a string!"); 3880b57cec5SDimitry Andric return pImpl->getKindAsString(); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric StringRef Attribute::getValueAsString() const { 3920b57cec5SDimitry Andric if (!pImpl) return {}; 3930b57cec5SDimitry Andric assert(isStringAttribute() && 3940b57cec5SDimitry Andric "Invalid attribute type to get the value as a string!"); 3950b57cec5SDimitry Andric return pImpl->getValueAsString(); 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric Type *Attribute::getValueAsType() const { 3990b57cec5SDimitry Andric if (!pImpl) return {}; 4000b57cec5SDimitry Andric assert(isTypeAttribute() && 4010b57cec5SDimitry Andric "Invalid attribute type to get the value as a type!"); 4020b57cec5SDimitry Andric return pImpl->getValueAsType(); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 405*0fca6ea1SDimitry Andric const ConstantRange &Attribute::getValueAsConstantRange() const { 406*0fca6ea1SDimitry Andric assert(isConstantRangeAttribute() && 407*0fca6ea1SDimitry Andric "Invalid attribute type to get the value as a ConstantRange!"); 408*0fca6ea1SDimitry Andric return pImpl->getValueAsConstantRange(); 409*0fca6ea1SDimitry Andric } 410*0fca6ea1SDimitry Andric 411*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const { 412*0fca6ea1SDimitry Andric assert(isConstantRangeListAttribute() && 413*0fca6ea1SDimitry Andric "Invalid attribute type to get the value as a ConstantRangeList!"); 414*0fca6ea1SDimitry Andric return pImpl->getValueAsConstantRangeList(); 415*0fca6ea1SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric bool Attribute::hasAttribute(AttrKind Kind) const { 4180b57cec5SDimitry Andric return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric bool Attribute::hasAttribute(StringRef Kind) const { 4220b57cec5SDimitry Andric if (!isStringAttribute()) return false; 4230b57cec5SDimitry Andric return pImpl && pImpl->hasAttribute(Kind); 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4268bcb0991SDimitry Andric MaybeAlign Attribute::getAlignment() const { 4270b57cec5SDimitry Andric assert(hasAttribute(Attribute::Alignment) && 4280b57cec5SDimitry Andric "Trying to get alignment from non-alignment attribute!"); 4298bcb0991SDimitry Andric return MaybeAlign(pImpl->getValueAsInt()); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4328bcb0991SDimitry Andric MaybeAlign Attribute::getStackAlignment() const { 4330b57cec5SDimitry Andric assert(hasAttribute(Attribute::StackAlignment) && 4340b57cec5SDimitry Andric "Trying to get alignment from non-alignment attribute!"); 4358bcb0991SDimitry Andric return MaybeAlign(pImpl->getValueAsInt()); 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric uint64_t Attribute::getDereferenceableBytes() const { 4390b57cec5SDimitry Andric assert(hasAttribute(Attribute::Dereferenceable) && 4400b57cec5SDimitry Andric "Trying to get dereferenceable bytes from " 4410b57cec5SDimitry Andric "non-dereferenceable attribute!"); 4420b57cec5SDimitry Andric return pImpl->getValueAsInt(); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric uint64_t Attribute::getDereferenceableOrNullBytes() const { 4460b57cec5SDimitry Andric assert(hasAttribute(Attribute::DereferenceableOrNull) && 4470b57cec5SDimitry Andric "Trying to get dereferenceable bytes from " 4480b57cec5SDimitry Andric "non-dereferenceable attribute!"); 4490b57cec5SDimitry Andric return pImpl->getValueAsInt(); 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric 452bdd1243dSDimitry Andric std::pair<unsigned, std::optional<unsigned>> 453bdd1243dSDimitry Andric Attribute::getAllocSizeArgs() const { 4540b57cec5SDimitry Andric assert(hasAttribute(Attribute::AllocSize) && 4550b57cec5SDimitry Andric "Trying to get allocsize args from non-allocsize attribute"); 4560b57cec5SDimitry Andric return unpackAllocSizeArgs(pImpl->getValueAsInt()); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590eae32dcSDimitry Andric unsigned Attribute::getVScaleRangeMin() const { 460fe6060f1SDimitry Andric assert(hasAttribute(Attribute::VScaleRange) && 461fe6060f1SDimitry Andric "Trying to get vscale args from non-vscale attribute"); 4620eae32dcSDimitry Andric return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first; 4630eae32dcSDimitry Andric } 4640eae32dcSDimitry Andric 465bdd1243dSDimitry Andric std::optional<unsigned> Attribute::getVScaleRangeMax() const { 4660eae32dcSDimitry Andric assert(hasAttribute(Attribute::VScaleRange) && 4670eae32dcSDimitry Andric "Trying to get vscale args from non-vscale attribute"); 4680eae32dcSDimitry Andric return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second; 469fe6060f1SDimitry Andric } 470fe6060f1SDimitry Andric 47181ad6265SDimitry Andric UWTableKind Attribute::getUWTableKind() const { 47281ad6265SDimitry Andric assert(hasAttribute(Attribute::UWTable) && 47381ad6265SDimitry Andric "Trying to get unwind table kind from non-uwtable attribute"); 47481ad6265SDimitry Andric return UWTableKind(pImpl->getValueAsInt()); 47581ad6265SDimitry Andric } 47681ad6265SDimitry Andric 47781ad6265SDimitry Andric AllocFnKind Attribute::getAllocKind() const { 47881ad6265SDimitry Andric assert(hasAttribute(Attribute::AllocKind) && 47981ad6265SDimitry Andric "Trying to get allockind value from non-allockind attribute"); 48081ad6265SDimitry Andric return AllocFnKind(pImpl->getValueAsInt()); 48181ad6265SDimitry Andric } 48281ad6265SDimitry Andric 483bdd1243dSDimitry Andric MemoryEffects Attribute::getMemoryEffects() const { 484bdd1243dSDimitry Andric assert(hasAttribute(Attribute::Memory) && 485bdd1243dSDimitry Andric "Can only call getMemoryEffects() on memory attribute"); 486bdd1243dSDimitry Andric return MemoryEffects::createFromIntValue(pImpl->getValueAsInt()); 487bdd1243dSDimitry Andric } 488bdd1243dSDimitry Andric 48906c3fb27SDimitry Andric FPClassTest Attribute::getNoFPClass() const { 49006c3fb27SDimitry Andric assert(hasAttribute(Attribute::NoFPClass) && 49106c3fb27SDimitry Andric "Can only call getNoFPClass() on nofpclass attribute"); 49206c3fb27SDimitry Andric return static_cast<FPClassTest>(pImpl->getValueAsInt()); 49306c3fb27SDimitry Andric } 49406c3fb27SDimitry Andric 495*0fca6ea1SDimitry Andric const ConstantRange &Attribute::getRange() const { 496*0fca6ea1SDimitry Andric assert(hasAttribute(Attribute::Range) && 497*0fca6ea1SDimitry Andric "Trying to get range args from non-range attribute"); 498*0fca6ea1SDimitry Andric return pImpl->getValueAsConstantRange(); 499*0fca6ea1SDimitry Andric } 500*0fca6ea1SDimitry Andric 501*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> Attribute::getInitializes() const { 502*0fca6ea1SDimitry Andric assert(hasAttribute(Attribute::Initializes) && 503*0fca6ea1SDimitry Andric "Trying to get initializes attr from non-ConstantRangeList attribute"); 504*0fca6ea1SDimitry Andric return pImpl->getValueAsConstantRangeList(); 505*0fca6ea1SDimitry Andric } 506*0fca6ea1SDimitry Andric 507bdd1243dSDimitry Andric static const char *getModRefStr(ModRefInfo MR) { 508bdd1243dSDimitry Andric switch (MR) { 509bdd1243dSDimitry Andric case ModRefInfo::NoModRef: 510bdd1243dSDimitry Andric return "none"; 511bdd1243dSDimitry Andric case ModRefInfo::Ref: 512bdd1243dSDimitry Andric return "read"; 513bdd1243dSDimitry Andric case ModRefInfo::Mod: 514bdd1243dSDimitry Andric return "write"; 515bdd1243dSDimitry Andric case ModRefInfo::ModRef: 516bdd1243dSDimitry Andric return "readwrite"; 517bdd1243dSDimitry Andric } 518bdd1243dSDimitry Andric llvm_unreachable("Invalid ModRefInfo"); 519bdd1243dSDimitry Andric } 520bdd1243dSDimitry Andric 5210b57cec5SDimitry Andric std::string Attribute::getAsString(bool InAttrGrp) const { 5220b57cec5SDimitry Andric if (!pImpl) return {}; 5230b57cec5SDimitry Andric 524fe6060f1SDimitry Andric if (isEnumAttribute()) 525fe6060f1SDimitry Andric return getNameFromAttrKind(getKindAsEnum()).str(); 5260b57cec5SDimitry Andric 527fe6060f1SDimitry Andric if (isTypeAttribute()) { 528fe6060f1SDimitry Andric std::string Result = getNameFromAttrKind(getKindAsEnum()).str(); 5290b57cec5SDimitry Andric Result += '('; 5305ffd83dbSDimitry Andric raw_string_ostream OS(Result); 5315ffd83dbSDimitry Andric getValueAsType()->print(OS, false, true); 5325ffd83dbSDimitry Andric OS.flush(); 5335ffd83dbSDimitry Andric Result += ')'; 5345ffd83dbSDimitry Andric return Result; 5355ffd83dbSDimitry Andric } 5365ffd83dbSDimitry Andric 5370b57cec5SDimitry Andric // FIXME: These should be output like this: 5380b57cec5SDimitry Andric // 5390b57cec5SDimitry Andric // align=4 5400b57cec5SDimitry Andric // alignstack=8 5410b57cec5SDimitry Andric // 5421fd87a68SDimitry Andric if (hasAttribute(Attribute::Alignment)) 5431fd87a68SDimitry Andric return (InAttrGrp ? "align=" + Twine(getValueAsInt()) 5441fd87a68SDimitry Andric : "align " + Twine(getValueAsInt())) 5451fd87a68SDimitry Andric .str(); 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric auto AttrWithBytesToString = [&](const char *Name) { 5481fd87a68SDimitry Andric return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt())) 5491fd87a68SDimitry Andric : Name + ("(" + Twine(getValueAsInt())) + ")") 5501fd87a68SDimitry Andric .str(); 5510b57cec5SDimitry Andric }; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric if (hasAttribute(Attribute::StackAlignment)) 5540b57cec5SDimitry Andric return AttrWithBytesToString("alignstack"); 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric if (hasAttribute(Attribute::Dereferenceable)) 5570b57cec5SDimitry Andric return AttrWithBytesToString("dereferenceable"); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric if (hasAttribute(Attribute::DereferenceableOrNull)) 5600b57cec5SDimitry Andric return AttrWithBytesToString("dereferenceable_or_null"); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (hasAttribute(Attribute::AllocSize)) { 5630b57cec5SDimitry Andric unsigned ElemSize; 564bdd1243dSDimitry Andric std::optional<unsigned> NumElems; 5650b57cec5SDimitry Andric std::tie(ElemSize, NumElems) = getAllocSizeArgs(); 5660b57cec5SDimitry Andric 5671fd87a68SDimitry Andric return (NumElems 5681fd87a68SDimitry Andric ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")" 5691fd87a68SDimitry Andric : "allocsize(" + Twine(ElemSize) + ")") 5701fd87a68SDimitry Andric .str(); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 573fe6060f1SDimitry Andric if (hasAttribute(Attribute::VScaleRange)) { 5740eae32dcSDimitry Andric unsigned MinValue = getVScaleRangeMin(); 575bdd1243dSDimitry Andric std::optional<unsigned> MaxValue = getVScaleRangeMax(); 5761fd87a68SDimitry Andric return ("vscale_range(" + Twine(MinValue) + "," + 57781ad6265SDimitry Andric Twine(MaxValue.value_or(0)) + ")") 57881ad6265SDimitry Andric .str(); 57981ad6265SDimitry Andric } 58081ad6265SDimitry Andric 58181ad6265SDimitry Andric if (hasAttribute(Attribute::UWTable)) { 58281ad6265SDimitry Andric UWTableKind Kind = getUWTableKind(); 583*0fca6ea1SDimitry Andric assert(Kind != UWTableKind::None && "uwtable attribute should not be none"); 584*0fca6ea1SDimitry Andric return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)"; 58581ad6265SDimitry Andric } 58681ad6265SDimitry Andric 58781ad6265SDimitry Andric if (hasAttribute(Attribute::AllocKind)) { 58881ad6265SDimitry Andric AllocFnKind Kind = getAllocKind(); 58981ad6265SDimitry Andric SmallVector<StringRef> parts; 59081ad6265SDimitry Andric if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown) 59181ad6265SDimitry Andric parts.push_back("alloc"); 59281ad6265SDimitry Andric if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown) 59381ad6265SDimitry Andric parts.push_back("realloc"); 59481ad6265SDimitry Andric if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown) 59581ad6265SDimitry Andric parts.push_back("free"); 59681ad6265SDimitry Andric if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown) 59781ad6265SDimitry Andric parts.push_back("uninitialized"); 59881ad6265SDimitry Andric if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown) 59981ad6265SDimitry Andric parts.push_back("zeroed"); 60081ad6265SDimitry Andric if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown) 60181ad6265SDimitry Andric parts.push_back("aligned"); 60281ad6265SDimitry Andric return ("allockind(\"" + 60381ad6265SDimitry Andric Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")") 6041fd87a68SDimitry Andric .str(); 605fe6060f1SDimitry Andric } 606fe6060f1SDimitry Andric 607bdd1243dSDimitry Andric if (hasAttribute(Attribute::Memory)) { 608bdd1243dSDimitry Andric std::string Result; 609bdd1243dSDimitry Andric raw_string_ostream OS(Result); 610bdd1243dSDimitry Andric bool First = true; 611bdd1243dSDimitry Andric OS << "memory("; 612bdd1243dSDimitry Andric 613bdd1243dSDimitry Andric MemoryEffects ME = getMemoryEffects(); 614bdd1243dSDimitry Andric 615bdd1243dSDimitry Andric // Print access kind for "other" as the default access kind. This way it 616bdd1243dSDimitry Andric // will apply to any new location kinds that get split out of "other". 61706c3fb27SDimitry Andric ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other); 618bdd1243dSDimitry Andric if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) { 619bdd1243dSDimitry Andric First = false; 620bdd1243dSDimitry Andric OS << getModRefStr(OtherMR); 621bdd1243dSDimitry Andric } 622bdd1243dSDimitry Andric 623bdd1243dSDimitry Andric for (auto Loc : MemoryEffects::locations()) { 624bdd1243dSDimitry Andric ModRefInfo MR = ME.getModRef(Loc); 625bdd1243dSDimitry Andric if (MR == OtherMR) 626bdd1243dSDimitry Andric continue; 627bdd1243dSDimitry Andric 628bdd1243dSDimitry Andric if (!First) 629bdd1243dSDimitry Andric OS << ", "; 630bdd1243dSDimitry Andric First = false; 631bdd1243dSDimitry Andric 632bdd1243dSDimitry Andric switch (Loc) { 63306c3fb27SDimitry Andric case IRMemLocation::ArgMem: 634bdd1243dSDimitry Andric OS << "argmem: "; 635bdd1243dSDimitry Andric break; 63606c3fb27SDimitry Andric case IRMemLocation::InaccessibleMem: 637bdd1243dSDimitry Andric OS << "inaccessiblemem: "; 638bdd1243dSDimitry Andric break; 63906c3fb27SDimitry Andric case IRMemLocation::Other: 640bdd1243dSDimitry Andric llvm_unreachable("This is represented as the default access kind"); 641bdd1243dSDimitry Andric } 642bdd1243dSDimitry Andric OS << getModRefStr(MR); 643bdd1243dSDimitry Andric } 644bdd1243dSDimitry Andric OS << ")"; 645bdd1243dSDimitry Andric OS.flush(); 646bdd1243dSDimitry Andric return Result; 647bdd1243dSDimitry Andric } 648bdd1243dSDimitry Andric 64906c3fb27SDimitry Andric if (hasAttribute(Attribute::NoFPClass)) { 65006c3fb27SDimitry Andric std::string Result = "nofpclass"; 65106c3fb27SDimitry Andric raw_string_ostream OS(Result); 65206c3fb27SDimitry Andric OS << getNoFPClass(); 65306c3fb27SDimitry Andric return Result; 65406c3fb27SDimitry Andric } 65506c3fb27SDimitry Andric 656*0fca6ea1SDimitry Andric if (hasAttribute(Attribute::Range)) { 657*0fca6ea1SDimitry Andric std::string Result; 658*0fca6ea1SDimitry Andric raw_string_ostream OS(Result); 659*0fca6ea1SDimitry Andric const ConstantRange &CR = getValueAsConstantRange(); 660*0fca6ea1SDimitry Andric OS << "range("; 661*0fca6ea1SDimitry Andric OS << "i" << CR.getBitWidth() << " "; 662*0fca6ea1SDimitry Andric OS << CR.getLower() << ", " << CR.getUpper(); 663*0fca6ea1SDimitry Andric OS << ")"; 664*0fca6ea1SDimitry Andric OS.flush(); 665*0fca6ea1SDimitry Andric return Result; 666*0fca6ea1SDimitry Andric } 667*0fca6ea1SDimitry Andric 668*0fca6ea1SDimitry Andric if (hasAttribute(Attribute::Initializes)) { 669*0fca6ea1SDimitry Andric std::string Result; 670*0fca6ea1SDimitry Andric raw_string_ostream OS(Result); 671*0fca6ea1SDimitry Andric ConstantRangeList CRL = getInitializes(); 672*0fca6ea1SDimitry Andric OS << "initializes("; 673*0fca6ea1SDimitry Andric CRL.print(OS); 674*0fca6ea1SDimitry Andric OS << ")"; 675*0fca6ea1SDimitry Andric OS.flush(); 676*0fca6ea1SDimitry Andric return Result; 677*0fca6ea1SDimitry Andric } 678*0fca6ea1SDimitry Andric 6790b57cec5SDimitry Andric // Convert target-dependent attributes to strings of the form: 6800b57cec5SDimitry Andric // 6810b57cec5SDimitry Andric // "kind" 6820b57cec5SDimitry Andric // "kind" = "value" 6830b57cec5SDimitry Andric // 6840b57cec5SDimitry Andric if (isStringAttribute()) { 6850b57cec5SDimitry Andric std::string Result; 6860b57cec5SDimitry Andric { 6870b57cec5SDimitry Andric raw_string_ostream OS(Result); 6885ffd83dbSDimitry Andric OS << '"' << getKindAsString() << '"'; 6895ffd83dbSDimitry Andric 6905ffd83dbSDimitry Andric // Since some attribute strings contain special characters that cannot be 6915ffd83dbSDimitry Andric // printable, those have to be escaped to make the attribute value 6925ffd83dbSDimitry Andric // printable as is. e.g. "\01__gnu_mcount_nc" 6935ffd83dbSDimitry Andric const auto &AttrVal = pImpl->getValueAsString(); 6945ffd83dbSDimitry Andric if (!AttrVal.empty()) { 6950b57cec5SDimitry Andric OS << "=\""; 6960b57cec5SDimitry Andric printEscapedString(AttrVal, OS); 6970b57cec5SDimitry Andric OS << "\""; 6980b57cec5SDimitry Andric } 6995ffd83dbSDimitry Andric } 7000b57cec5SDimitry Andric return Result; 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric llvm_unreachable("Unknown attribute"); 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric 706fe6060f1SDimitry Andric bool Attribute::hasParentContext(LLVMContext &C) const { 707fe6060f1SDimitry Andric assert(isValid() && "invalid Attribute doesn't refer to any context"); 708fe6060f1SDimitry Andric FoldingSetNodeID ID; 709fe6060f1SDimitry Andric pImpl->Profile(ID); 710fe6060f1SDimitry Andric void *Unused; 711fe6060f1SDimitry Andric return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl; 712fe6060f1SDimitry Andric } 713fe6060f1SDimitry Andric 7140b57cec5SDimitry Andric bool Attribute::operator<(Attribute A) const { 7150b57cec5SDimitry Andric if (!pImpl && !A.pImpl) return false; 7160b57cec5SDimitry Andric if (!pImpl) return true; 7170b57cec5SDimitry Andric if (!A.pImpl) return false; 7180b57cec5SDimitry Andric return *pImpl < *A.pImpl; 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7215ffd83dbSDimitry Andric void Attribute::Profile(FoldingSetNodeID &ID) const { 7225ffd83dbSDimitry Andric ID.AddPointer(pImpl); 7235ffd83dbSDimitry Andric } 7245ffd83dbSDimitry Andric 725fe6060f1SDimitry Andric enum AttributeProperty { 726fe6060f1SDimitry Andric FnAttr = (1 << 0), 727fe6060f1SDimitry Andric ParamAttr = (1 << 1), 728fe6060f1SDimitry Andric RetAttr = (1 << 2), 729fe6060f1SDimitry Andric }; 730fe6060f1SDimitry Andric 731fe6060f1SDimitry Andric #define GET_ATTR_PROP_TABLE 732fe6060f1SDimitry Andric #include "llvm/IR/Attributes.inc" 733fe6060f1SDimitry Andric 734fe6060f1SDimitry Andric static bool hasAttributeProperty(Attribute::AttrKind Kind, 735fe6060f1SDimitry Andric AttributeProperty Prop) { 736fe6060f1SDimitry Andric unsigned Index = Kind - 1; 737bdd1243dSDimitry Andric assert(Index < std::size(AttrPropTable) && "Invalid attribute kind"); 738fe6060f1SDimitry Andric return AttrPropTable[Index] & Prop; 739fe6060f1SDimitry Andric } 740fe6060f1SDimitry Andric 741fe6060f1SDimitry Andric bool Attribute::canUseAsFnAttr(AttrKind Kind) { 742fe6060f1SDimitry Andric return hasAttributeProperty(Kind, AttributeProperty::FnAttr); 743fe6060f1SDimitry Andric } 744fe6060f1SDimitry Andric 745fe6060f1SDimitry Andric bool Attribute::canUseAsParamAttr(AttrKind Kind) { 746fe6060f1SDimitry Andric return hasAttributeProperty(Kind, AttributeProperty::ParamAttr); 747fe6060f1SDimitry Andric } 748fe6060f1SDimitry Andric 749fe6060f1SDimitry Andric bool Attribute::canUseAsRetAttr(AttrKind Kind) { 750fe6060f1SDimitry Andric return hasAttributeProperty(Kind, AttributeProperty::RetAttr); 751fe6060f1SDimitry Andric } 752fe6060f1SDimitry Andric 7530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7540b57cec5SDimitry Andric // AttributeImpl Definition 7550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { 7580b57cec5SDimitry Andric if (isStringAttribute()) return false; 7590b57cec5SDimitry Andric return getKindAsEnum() == A; 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric bool AttributeImpl::hasAttribute(StringRef Kind) const { 7630b57cec5SDimitry Andric if (!isStringAttribute()) return false; 7640b57cec5SDimitry Andric return getKindAsString() == Kind; 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric Attribute::AttrKind AttributeImpl::getKindAsEnum() const { 768*0fca6ea1SDimitry Andric assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() || 769*0fca6ea1SDimitry Andric isConstantRangeAttribute() || isConstantRangeListAttribute()); 7700b57cec5SDimitry Andric return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric uint64_t AttributeImpl::getValueAsInt() const { 7740b57cec5SDimitry Andric assert(isIntAttribute()); 7750b57cec5SDimitry Andric return static_cast<const IntAttributeImpl *>(this)->getValue(); 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 778fe6060f1SDimitry Andric bool AttributeImpl::getValueAsBool() const { 779fe6060f1SDimitry Andric assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true"); 780fe6060f1SDimitry Andric return getValueAsString() == "true"; 781fe6060f1SDimitry Andric } 782fe6060f1SDimitry Andric 7830b57cec5SDimitry Andric StringRef AttributeImpl::getKindAsString() const { 7840b57cec5SDimitry Andric assert(isStringAttribute()); 7850b57cec5SDimitry Andric return static_cast<const StringAttributeImpl *>(this)->getStringKind(); 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric StringRef AttributeImpl::getValueAsString() const { 7890b57cec5SDimitry Andric assert(isStringAttribute()); 7900b57cec5SDimitry Andric return static_cast<const StringAttributeImpl *>(this)->getStringValue(); 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric Type *AttributeImpl::getValueAsType() const { 7940b57cec5SDimitry Andric assert(isTypeAttribute()); 7950b57cec5SDimitry Andric return static_cast<const TypeAttributeImpl *>(this)->getTypeValue(); 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 798*0fca6ea1SDimitry Andric const ConstantRange &AttributeImpl::getValueAsConstantRange() const { 799*0fca6ea1SDimitry Andric assert(isConstantRangeAttribute()); 800*0fca6ea1SDimitry Andric return static_cast<const ConstantRangeAttributeImpl *>(this) 801*0fca6ea1SDimitry Andric ->getConstantRangeValue(); 802*0fca6ea1SDimitry Andric } 803*0fca6ea1SDimitry Andric 804*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const { 805*0fca6ea1SDimitry Andric assert(isConstantRangeListAttribute()); 806*0fca6ea1SDimitry Andric return static_cast<const ConstantRangeListAttributeImpl *>(this) 807*0fca6ea1SDimitry Andric ->getConstantRangeListValue(); 808*0fca6ea1SDimitry Andric } 809*0fca6ea1SDimitry Andric 8100b57cec5SDimitry Andric bool AttributeImpl::operator<(const AttributeImpl &AI) const { 8115ffd83dbSDimitry Andric if (this == &AI) 8125ffd83dbSDimitry Andric return false; 813fe6060f1SDimitry Andric 8140b57cec5SDimitry Andric // This sorts the attributes with Attribute::AttrKinds coming first (sorted 8150b57cec5SDimitry Andric // relative to their enum value) and then strings. 816fe6060f1SDimitry Andric if (!isStringAttribute()) { 817fe6060f1SDimitry Andric if (AI.isStringAttribute()) 818fe6060f1SDimitry Andric return true; 819fe6060f1SDimitry Andric if (getKindAsEnum() != AI.getKindAsEnum()) 8200b57cec5SDimitry Andric return getKindAsEnum() < AI.getKindAsEnum(); 821fe6060f1SDimitry Andric assert(!AI.isEnumAttribute() && "Non-unique attribute"); 822fe6060f1SDimitry Andric assert(!AI.isTypeAttribute() && "Comparison of types would be unstable"); 823*0fca6ea1SDimitry Andric assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges"); 824*0fca6ea1SDimitry Andric assert(!AI.isConstantRangeListAttribute() && 825*0fca6ea1SDimitry Andric "Unclear how to compare range list"); 826fe6060f1SDimitry Andric // TODO: Is this actually needed? 827fe6060f1SDimitry Andric assert(AI.isIntAttribute() && "Only possibility left"); 8280b57cec5SDimitry Andric return getValueAsInt() < AI.getValueAsInt(); 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric 831fe6060f1SDimitry Andric if (!AI.isStringAttribute()) 832fe6060f1SDimitry Andric return false; 8330b57cec5SDimitry Andric if (getKindAsString() == AI.getKindAsString()) 8340b57cec5SDimitry Andric return getValueAsString() < AI.getValueAsString(); 8350b57cec5SDimitry Andric return getKindAsString() < AI.getKindAsString(); 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8390b57cec5SDimitry Andric // AttributeSet Definition 8400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) { 8430b57cec5SDimitry Andric return AttributeSet(AttributeSetNode::get(C, B)); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) { 8470b57cec5SDimitry Andric return AttributeSet(AttributeSetNode::get(C, Attrs)); 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric AttributeSet AttributeSet::addAttribute(LLVMContext &C, 8510b57cec5SDimitry Andric Attribute::AttrKind Kind) const { 8520b57cec5SDimitry Andric if (hasAttribute(Kind)) return *this; 85304eeddc0SDimitry Andric AttrBuilder B(C); 8540b57cec5SDimitry Andric B.addAttribute(Kind); 8550b57cec5SDimitry Andric return addAttributes(C, AttributeSet::get(C, B)); 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind, 8590b57cec5SDimitry Andric StringRef Value) const { 86004eeddc0SDimitry Andric AttrBuilder B(C); 8610b57cec5SDimitry Andric B.addAttribute(Kind, Value); 8620b57cec5SDimitry Andric return addAttributes(C, AttributeSet::get(C, B)); 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric AttributeSet AttributeSet::addAttributes(LLVMContext &C, 8660b57cec5SDimitry Andric const AttributeSet AS) const { 8670b57cec5SDimitry Andric if (!hasAttributes()) 8680b57cec5SDimitry Andric return AS; 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric if (!AS.hasAttributes()) 8710b57cec5SDimitry Andric return *this; 8720b57cec5SDimitry Andric 87304eeddc0SDimitry Andric AttrBuilder B(C, *this); 87404eeddc0SDimitry Andric B.merge(AttrBuilder(C, AS)); 8750b57cec5SDimitry Andric return get(C, B); 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric AttributeSet AttributeSet::removeAttribute(LLVMContext &C, 8790b57cec5SDimitry Andric Attribute::AttrKind Kind) const { 8800b57cec5SDimitry Andric if (!hasAttribute(Kind)) return *this; 88104eeddc0SDimitry Andric AttrBuilder B(C, *this); 8820b57cec5SDimitry Andric B.removeAttribute(Kind); 8830b57cec5SDimitry Andric return get(C, B); 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric AttributeSet AttributeSet::removeAttribute(LLVMContext &C, 8870b57cec5SDimitry Andric StringRef Kind) const { 8880b57cec5SDimitry Andric if (!hasAttribute(Kind)) return *this; 88904eeddc0SDimitry Andric AttrBuilder B(C, *this); 8900b57cec5SDimitry Andric B.removeAttribute(Kind); 8910b57cec5SDimitry Andric return get(C, B); 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric AttributeSet AttributeSet::removeAttributes(LLVMContext &C, 89504eeddc0SDimitry Andric const AttributeMask &Attrs) const { 89604eeddc0SDimitry Andric AttrBuilder B(C, *this); 897fe6060f1SDimitry Andric // If there is nothing to remove, directly return the original set. 898fe6060f1SDimitry Andric if (!B.overlaps(Attrs)) 899fe6060f1SDimitry Andric return *this; 900fe6060f1SDimitry Andric 9010b57cec5SDimitry Andric B.remove(Attrs); 9020b57cec5SDimitry Andric return get(C, B); 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric unsigned AttributeSet::getNumAttributes() const { 9060b57cec5SDimitry Andric return SetNode ? SetNode->getNumAttributes() : 0; 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const { 9100b57cec5SDimitry Andric return SetNode ? SetNode->hasAttribute(Kind) : false; 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric bool AttributeSet::hasAttribute(StringRef Kind) const { 9140b57cec5SDimitry Andric return SetNode ? SetNode->hasAttribute(Kind) : false; 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const { 9180b57cec5SDimitry Andric return SetNode ? SetNode->getAttribute(Kind) : Attribute(); 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric Attribute AttributeSet::getAttribute(StringRef Kind) const { 9220b57cec5SDimitry Andric return SetNode ? SetNode->getAttribute(Kind) : Attribute(); 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric 9258bcb0991SDimitry Andric MaybeAlign AttributeSet::getAlignment() const { 926bdd1243dSDimitry Andric return SetNode ? SetNode->getAlignment() : std::nullopt; 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9298bcb0991SDimitry Andric MaybeAlign AttributeSet::getStackAlignment() const { 930bdd1243dSDimitry Andric return SetNode ? SetNode->getStackAlignment() : std::nullopt; 9310b57cec5SDimitry Andric } 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric uint64_t AttributeSet::getDereferenceableBytes() const { 9340b57cec5SDimitry Andric return SetNode ? SetNode->getDereferenceableBytes() : 0; 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric uint64_t AttributeSet::getDereferenceableOrNullBytes() const { 9380b57cec5SDimitry Andric return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0; 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric 941e8d8bef9SDimitry Andric Type *AttributeSet::getByRefType() const { 942fe6060f1SDimitry Andric return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr; 943e8d8bef9SDimitry Andric } 944e8d8bef9SDimitry Andric 9450b57cec5SDimitry Andric Type *AttributeSet::getByValType() const { 946fe6060f1SDimitry Andric return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr; 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 949e8d8bef9SDimitry Andric Type *AttributeSet::getStructRetType() const { 950fe6060f1SDimitry Andric return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr; 951e8d8bef9SDimitry Andric } 952e8d8bef9SDimitry Andric 9535ffd83dbSDimitry Andric Type *AttributeSet::getPreallocatedType() const { 954fe6060f1SDimitry Andric return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr; 955fe6060f1SDimitry Andric } 956fe6060f1SDimitry Andric 957fe6060f1SDimitry Andric Type *AttributeSet::getInAllocaType() const { 958fe6060f1SDimitry Andric return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr; 959fe6060f1SDimitry Andric } 960fe6060f1SDimitry Andric 961fe6060f1SDimitry Andric Type *AttributeSet::getElementType() const { 962fe6060f1SDimitry Andric return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr; 9635ffd83dbSDimitry Andric } 9645ffd83dbSDimitry Andric 965bdd1243dSDimitry Andric std::optional<std::pair<unsigned, std::optional<unsigned>>> 966bdd1243dSDimitry Andric AttributeSet::getAllocSizeArgs() const { 967bdd1243dSDimitry Andric if (SetNode) 968bdd1243dSDimitry Andric return SetNode->getAllocSizeArgs(); 969bdd1243dSDimitry Andric return std::nullopt; 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720eae32dcSDimitry Andric unsigned AttributeSet::getVScaleRangeMin() const { 9730eae32dcSDimitry Andric return SetNode ? SetNode->getVScaleRangeMin() : 1; 9740eae32dcSDimitry Andric } 9750eae32dcSDimitry Andric 976bdd1243dSDimitry Andric std::optional<unsigned> AttributeSet::getVScaleRangeMax() const { 977bdd1243dSDimitry Andric return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt; 978fe6060f1SDimitry Andric } 979fe6060f1SDimitry Andric 98081ad6265SDimitry Andric UWTableKind AttributeSet::getUWTableKind() const { 98181ad6265SDimitry Andric return SetNode ? SetNode->getUWTableKind() : UWTableKind::None; 98281ad6265SDimitry Andric } 98381ad6265SDimitry Andric 98481ad6265SDimitry Andric AllocFnKind AttributeSet::getAllocKind() const { 98581ad6265SDimitry Andric return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown; 98681ad6265SDimitry Andric } 98781ad6265SDimitry Andric 988bdd1243dSDimitry Andric MemoryEffects AttributeSet::getMemoryEffects() const { 989bdd1243dSDimitry Andric return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown(); 990bdd1243dSDimitry Andric } 991bdd1243dSDimitry Andric 99206c3fb27SDimitry Andric FPClassTest AttributeSet::getNoFPClass() const { 99306c3fb27SDimitry Andric return SetNode ? SetNode->getNoFPClass() : fcNone; 99406c3fb27SDimitry Andric } 99506c3fb27SDimitry Andric 9960b57cec5SDimitry Andric std::string AttributeSet::getAsString(bool InAttrGrp) const { 9970b57cec5SDimitry Andric return SetNode ? SetNode->getAsString(InAttrGrp) : ""; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 1000fe6060f1SDimitry Andric bool AttributeSet::hasParentContext(LLVMContext &C) const { 1001fe6060f1SDimitry Andric assert(hasAttributes() && "empty AttributeSet doesn't refer to any context"); 1002fe6060f1SDimitry Andric FoldingSetNodeID ID; 1003fe6060f1SDimitry Andric SetNode->Profile(ID); 1004fe6060f1SDimitry Andric void *Unused; 1005fe6060f1SDimitry Andric return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode; 1006fe6060f1SDimitry Andric } 1007fe6060f1SDimitry Andric 10080b57cec5SDimitry Andric AttributeSet::iterator AttributeSet::begin() const { 10090b57cec5SDimitry Andric return SetNode ? SetNode->begin() : nullptr; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric AttributeSet::iterator AttributeSet::end() const { 10130b57cec5SDimitry Andric return SetNode ? SetNode->end() : nullptr; 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 10170b57cec5SDimitry Andric LLVM_DUMP_METHOD void AttributeSet::dump() const { 10180b57cec5SDimitry Andric dbgs() << "AS =\n"; 10190b57cec5SDimitry Andric dbgs() << " { "; 10200b57cec5SDimitry Andric dbgs() << getAsString(true) << " }\n"; 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric #endif 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10250b57cec5SDimitry Andric // AttributeSetNode Definition 10260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs) 10290b57cec5SDimitry Andric : NumAttrs(Attrs.size()) { 10300b57cec5SDimitry Andric // There's memory after the node where we can store the entries in. 10310b57cec5SDimitry Andric llvm::copy(Attrs, getTrailingObjects<Attribute>()); 10320b57cec5SDimitry Andric 1033480093f4SDimitry Andric for (const auto &I : *this) { 10345ffd83dbSDimitry Andric if (I.isStringAttribute()) 10355ffd83dbSDimitry Andric StringAttrs.insert({ I.getKindAsString(), I }); 10365ffd83dbSDimitry Andric else 10375ffd83dbSDimitry Andric AvailableAttrs.addAttribute(I.getKindAsEnum()); 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric AttributeSetNode *AttributeSetNode::get(LLVMContext &C, 10420b57cec5SDimitry Andric ArrayRef<Attribute> Attrs) { 10435ffd83dbSDimitry Andric SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end()); 10445ffd83dbSDimitry Andric llvm::sort(SortedAttrs); 10455ffd83dbSDimitry Andric return getSorted(C, SortedAttrs); 10465ffd83dbSDimitry Andric } 10475ffd83dbSDimitry Andric 10485ffd83dbSDimitry Andric AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C, 10495ffd83dbSDimitry Andric ArrayRef<Attribute> SortedAttrs) { 10505ffd83dbSDimitry Andric if (SortedAttrs.empty()) 10510b57cec5SDimitry Andric return nullptr; 10520b57cec5SDimitry Andric 10535ffd83dbSDimitry Andric // Build a key to look up the existing attributes. 10540b57cec5SDimitry Andric LLVMContextImpl *pImpl = C.pImpl; 10550b57cec5SDimitry Andric FoldingSetNodeID ID; 10560b57cec5SDimitry Andric 10575ffd83dbSDimitry Andric assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!"); 1058480093f4SDimitry Andric for (const auto &Attr : SortedAttrs) 10590b57cec5SDimitry Andric Attr.Profile(ID); 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric void *InsertPoint; 10620b57cec5SDimitry Andric AttributeSetNode *PA = 10630b57cec5SDimitry Andric pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint); 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric // If we didn't find any existing attributes of the same shape then create a 10660b57cec5SDimitry Andric // new one and insert it. 10670b57cec5SDimitry Andric if (!PA) { 10680b57cec5SDimitry Andric // Coallocate entries after the AttributeSetNode itself. 10690b57cec5SDimitry Andric void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size())); 10700b57cec5SDimitry Andric PA = new (Mem) AttributeSetNode(SortedAttrs); 10710b57cec5SDimitry Andric pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric // Return the AttributeSetNode that we found or created. 10750b57cec5SDimitry Andric return PA; 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { 107904eeddc0SDimitry Andric return getSorted(C, B.attrs()); 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric bool AttributeSetNode::hasAttribute(StringRef Kind) const { 10835ffd83dbSDimitry Andric return StringAttrs.count(Kind); 10845ffd83dbSDimitry Andric } 10855ffd83dbSDimitry Andric 1086bdd1243dSDimitry Andric std::optional<Attribute> 10875ffd83dbSDimitry Andric AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const { 10885ffd83dbSDimitry Andric // Do a quick presence check. 10895ffd83dbSDimitry Andric if (!hasAttribute(Kind)) 1090bdd1243dSDimitry Andric return std::nullopt; 10915ffd83dbSDimitry Andric 10925ffd83dbSDimitry Andric // Attributes in a set are sorted by enum value, followed by string 10935ffd83dbSDimitry Andric // attributes. Binary search the one we want. 10945ffd83dbSDimitry Andric const Attribute *I = 10955ffd83dbSDimitry Andric std::lower_bound(begin(), end() - StringAttrs.size(), Kind, 10965ffd83dbSDimitry Andric [](Attribute A, Attribute::AttrKind Kind) { 10975ffd83dbSDimitry Andric return A.getKindAsEnum() < Kind; 10985ffd83dbSDimitry Andric }); 10995ffd83dbSDimitry Andric assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?"); 11005ffd83dbSDimitry Andric return *I; 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { 11045ffd83dbSDimitry Andric if (auto A = findEnumAttribute(Kind)) 11055ffd83dbSDimitry Andric return *A; 11060b57cec5SDimitry Andric return {}; 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric Attribute AttributeSetNode::getAttribute(StringRef Kind) const { 11105ffd83dbSDimitry Andric return StringAttrs.lookup(Kind); 11110b57cec5SDimitry Andric } 11120b57cec5SDimitry Andric 11138bcb0991SDimitry Andric MaybeAlign AttributeSetNode::getAlignment() const { 11145ffd83dbSDimitry Andric if (auto A = findEnumAttribute(Attribute::Alignment)) 11155ffd83dbSDimitry Andric return A->getAlignment(); 1116bdd1243dSDimitry Andric return std::nullopt; 11170b57cec5SDimitry Andric } 11180b57cec5SDimitry Andric 11198bcb0991SDimitry Andric MaybeAlign AttributeSetNode::getStackAlignment() const { 11205ffd83dbSDimitry Andric if (auto A = findEnumAttribute(Attribute::StackAlignment)) 11215ffd83dbSDimitry Andric return A->getStackAlignment(); 1122bdd1243dSDimitry Andric return std::nullopt; 11230b57cec5SDimitry Andric } 11240b57cec5SDimitry Andric 1125fe6060f1SDimitry Andric Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const { 1126fe6060f1SDimitry Andric if (auto A = findEnumAttribute(Kind)) 1127e8d8bef9SDimitry Andric return A->getValueAsType(); 1128e8d8bef9SDimitry Andric return nullptr; 11290b57cec5SDimitry Andric } 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric uint64_t AttributeSetNode::getDereferenceableBytes() const { 11325ffd83dbSDimitry Andric if (auto A = findEnumAttribute(Attribute::Dereferenceable)) 11335ffd83dbSDimitry Andric return A->getDereferenceableBytes(); 11340b57cec5SDimitry Andric return 0; 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric 11370b57cec5SDimitry Andric uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { 11385ffd83dbSDimitry Andric if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull)) 11395ffd83dbSDimitry Andric return A->getDereferenceableOrNullBytes(); 11400b57cec5SDimitry Andric return 0; 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 1143bdd1243dSDimitry Andric std::optional<std::pair<unsigned, std::optional<unsigned>>> 11440b57cec5SDimitry Andric AttributeSetNode::getAllocSizeArgs() const { 11455ffd83dbSDimitry Andric if (auto A = findEnumAttribute(Attribute::AllocSize)) 11465ffd83dbSDimitry Andric return A->getAllocSizeArgs(); 1147bdd1243dSDimitry Andric return std::nullopt; 11480b57cec5SDimitry Andric } 11490b57cec5SDimitry Andric 11500eae32dcSDimitry Andric unsigned AttributeSetNode::getVScaleRangeMin() const { 1151fe6060f1SDimitry Andric if (auto A = findEnumAttribute(Attribute::VScaleRange)) 11520eae32dcSDimitry Andric return A->getVScaleRangeMin(); 11530eae32dcSDimitry Andric return 1; 11540eae32dcSDimitry Andric } 11550eae32dcSDimitry Andric 1156bdd1243dSDimitry Andric std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const { 11570eae32dcSDimitry Andric if (auto A = findEnumAttribute(Attribute::VScaleRange)) 11580eae32dcSDimitry Andric return A->getVScaleRangeMax(); 1159bdd1243dSDimitry Andric return std::nullopt; 1160fe6060f1SDimitry Andric } 1161fe6060f1SDimitry Andric 116281ad6265SDimitry Andric UWTableKind AttributeSetNode::getUWTableKind() const { 116381ad6265SDimitry Andric if (auto A = findEnumAttribute(Attribute::UWTable)) 116481ad6265SDimitry Andric return A->getUWTableKind(); 116581ad6265SDimitry Andric return UWTableKind::None; 116681ad6265SDimitry Andric } 116781ad6265SDimitry Andric 116881ad6265SDimitry Andric AllocFnKind AttributeSetNode::getAllocKind() const { 116981ad6265SDimitry Andric if (auto A = findEnumAttribute(Attribute::AllocKind)) 117081ad6265SDimitry Andric return A->getAllocKind(); 117181ad6265SDimitry Andric return AllocFnKind::Unknown; 117281ad6265SDimitry Andric } 117381ad6265SDimitry Andric 1174bdd1243dSDimitry Andric MemoryEffects AttributeSetNode::getMemoryEffects() const { 1175bdd1243dSDimitry Andric if (auto A = findEnumAttribute(Attribute::Memory)) 1176bdd1243dSDimitry Andric return A->getMemoryEffects(); 1177bdd1243dSDimitry Andric return MemoryEffects::unknown(); 1178bdd1243dSDimitry Andric } 1179bdd1243dSDimitry Andric 118006c3fb27SDimitry Andric FPClassTest AttributeSetNode::getNoFPClass() const { 118106c3fb27SDimitry Andric if (auto A = findEnumAttribute(Attribute::NoFPClass)) 118206c3fb27SDimitry Andric return A->getNoFPClass(); 118306c3fb27SDimitry Andric return fcNone; 118406c3fb27SDimitry Andric } 118506c3fb27SDimitry Andric 11860b57cec5SDimitry Andric std::string AttributeSetNode::getAsString(bool InAttrGrp) const { 11870b57cec5SDimitry Andric std::string Str; 11880b57cec5SDimitry Andric for (iterator I = begin(), E = end(); I != E; ++I) { 11890b57cec5SDimitry Andric if (I != begin()) 11900b57cec5SDimitry Andric Str += ' '; 11910b57cec5SDimitry Andric Str += I->getAsString(InAttrGrp); 11920b57cec5SDimitry Andric } 11930b57cec5SDimitry Andric return Str; 11940b57cec5SDimitry Andric } 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11970b57cec5SDimitry Andric // AttributeListImpl Definition 11980b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric /// Map from AttributeList index to the internal array index. Adding one happens 12015ffd83dbSDimitry Andric /// to work, because -1 wraps around to 0. 1202e8d8bef9SDimitry Andric static unsigned attrIdxToArrayIdx(unsigned Index) { 12035ffd83dbSDimitry Andric return Index + 1; 12040b57cec5SDimitry Andric } 12050b57cec5SDimitry Andric 12065ffd83dbSDimitry Andric AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets) 12075ffd83dbSDimitry Andric : NumAttrSets(Sets.size()) { 12080b57cec5SDimitry Andric assert(!Sets.empty() && "pointless AttributeListImpl"); 12090b57cec5SDimitry Andric 12100b57cec5SDimitry Andric // There's memory after the node where we can store the entries in. 12110b57cec5SDimitry Andric llvm::copy(Sets, getTrailingObjects<AttributeSet>()); 12120b57cec5SDimitry Andric 12135ffd83dbSDimitry Andric // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs 12145ffd83dbSDimitry Andric // summary bitsets. 1215e8d8bef9SDimitry Andric for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)]) 12165ffd83dbSDimitry Andric if (!I.isStringAttribute()) 12175ffd83dbSDimitry Andric AvailableFunctionAttrs.addAttribute(I.getKindAsEnum()); 12185ffd83dbSDimitry Andric 12195ffd83dbSDimitry Andric for (const auto &Set : Sets) 12205ffd83dbSDimitry Andric for (const auto &I : Set) 12215ffd83dbSDimitry Andric if (!I.isStringAttribute()) 12225ffd83dbSDimitry Andric AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum()); 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric 12250b57cec5SDimitry Andric void AttributeListImpl::Profile(FoldingSetNodeID &ID) const { 1226bdd1243dSDimitry Andric Profile(ID, ArrayRef(begin(), end())); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric void AttributeListImpl::Profile(FoldingSetNodeID &ID, 12300b57cec5SDimitry Andric ArrayRef<AttributeSet> Sets) { 12310b57cec5SDimitry Andric for (const auto &Set : Sets) 12320b57cec5SDimitry Andric ID.AddPointer(Set.SetNode); 12330b57cec5SDimitry Andric } 12340b57cec5SDimitry Andric 12355ffd83dbSDimitry Andric bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind, 12365ffd83dbSDimitry Andric unsigned *Index) const { 12375ffd83dbSDimitry Andric if (!AvailableSomewhereAttrs.hasAttribute(Kind)) 12385ffd83dbSDimitry Andric return false; 12395ffd83dbSDimitry Andric 12405ffd83dbSDimitry Andric if (Index) { 12415ffd83dbSDimitry Andric for (unsigned I = 0, E = NumAttrSets; I != E; ++I) { 12425ffd83dbSDimitry Andric if (begin()[I].hasAttribute(Kind)) { 12435ffd83dbSDimitry Andric *Index = I - 1; 12445ffd83dbSDimitry Andric break; 12455ffd83dbSDimitry Andric } 12465ffd83dbSDimitry Andric } 12475ffd83dbSDimitry Andric } 12485ffd83dbSDimitry Andric 12495ffd83dbSDimitry Andric return true; 12505ffd83dbSDimitry Andric } 12515ffd83dbSDimitry Andric 12525ffd83dbSDimitry Andric 12530b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 12540b57cec5SDimitry Andric LLVM_DUMP_METHOD void AttributeListImpl::dump() const { 12550b57cec5SDimitry Andric AttributeList(const_cast<AttributeListImpl *>(this)).dump(); 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric #endif 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12600b57cec5SDimitry Andric // AttributeList Construction and Mutation Methods 12610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12620b57cec5SDimitry Andric 12630b57cec5SDimitry Andric AttributeList AttributeList::getImpl(LLVMContext &C, 12640b57cec5SDimitry Andric ArrayRef<AttributeSet> AttrSets) { 12650b57cec5SDimitry Andric assert(!AttrSets.empty() && "pointless AttributeListImpl"); 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric LLVMContextImpl *pImpl = C.pImpl; 12680b57cec5SDimitry Andric FoldingSetNodeID ID; 12690b57cec5SDimitry Andric AttributeListImpl::Profile(ID, AttrSets); 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric void *InsertPoint; 12720b57cec5SDimitry Andric AttributeListImpl *PA = 12730b57cec5SDimitry Andric pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint); 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric // If we didn't find any existing attributes of the same shape then 12760b57cec5SDimitry Andric // create a new one and insert it. 12770b57cec5SDimitry Andric if (!PA) { 12780b57cec5SDimitry Andric // Coallocate entries after the AttributeListImpl itself. 12795ffd83dbSDimitry Andric void *Mem = pImpl->Alloc.Allocate( 12805ffd83dbSDimitry Andric AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()), 12815ffd83dbSDimitry Andric alignof(AttributeListImpl)); 12825ffd83dbSDimitry Andric PA = new (Mem) AttributeListImpl(AttrSets); 12830b57cec5SDimitry Andric pImpl->AttrsLists.InsertNode(PA, InsertPoint); 12840b57cec5SDimitry Andric } 12850b57cec5SDimitry Andric 12860b57cec5SDimitry Andric // Return the AttributesList that we found or created. 12870b57cec5SDimitry Andric return AttributeList(PA); 12880b57cec5SDimitry Andric } 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric AttributeList 12910b57cec5SDimitry Andric AttributeList::get(LLVMContext &C, 12920b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, Attribute>> Attrs) { 12930b57cec5SDimitry Andric // If there are no attributes then return a null AttributesList pointer. 12940b57cec5SDimitry Andric if (Attrs.empty()) 12950b57cec5SDimitry Andric return {}; 12960b57cec5SDimitry Andric 129781ad6265SDimitry Andric assert(llvm::is_sorted(Attrs, llvm::less_first()) && 12985ffd83dbSDimitry Andric "Misordered Attributes list!"); 1299e8d8bef9SDimitry Andric assert(llvm::all_of(Attrs, 13000b57cec5SDimitry Andric [](const std::pair<unsigned, Attribute> &Pair) { 1301e8d8bef9SDimitry Andric return Pair.second.isValid(); 13020b57cec5SDimitry Andric }) && 13030b57cec5SDimitry Andric "Pointless attribute!"); 13040b57cec5SDimitry Andric 13050b57cec5SDimitry Andric // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes 13060b57cec5SDimitry Andric // list. 13070b57cec5SDimitry Andric SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec; 13080b57cec5SDimitry Andric for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(), 13090b57cec5SDimitry Andric E = Attrs.end(); I != E; ) { 13100b57cec5SDimitry Andric unsigned Index = I->first; 13110b57cec5SDimitry Andric SmallVector<Attribute, 4> AttrVec; 13120b57cec5SDimitry Andric while (I != E && I->first == Index) { 13130b57cec5SDimitry Andric AttrVec.push_back(I->second); 13140b57cec5SDimitry Andric ++I; 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec)); 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric return get(C, AttrPairVec); 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric AttributeList 13240b57cec5SDimitry Andric AttributeList::get(LLVMContext &C, 13250b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) { 13260b57cec5SDimitry Andric // If there are no attributes then return a null AttributesList pointer. 13270b57cec5SDimitry Andric if (Attrs.empty()) 13280b57cec5SDimitry Andric return {}; 13290b57cec5SDimitry Andric 133081ad6265SDimitry Andric assert(llvm::is_sorted(Attrs, llvm::less_first()) && 13310b57cec5SDimitry Andric "Misordered Attributes list!"); 13320b57cec5SDimitry Andric assert(llvm::none_of(Attrs, 13330b57cec5SDimitry Andric [](const std::pair<unsigned, AttributeSet> &Pair) { 13340b57cec5SDimitry Andric return !Pair.second.hasAttributes(); 13350b57cec5SDimitry Andric }) && 13360b57cec5SDimitry Andric "Pointless attribute!"); 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andric unsigned MaxIndex = Attrs.back().first; 13390b57cec5SDimitry Andric // If the MaxIndex is FunctionIndex and there are other indices in front 13400b57cec5SDimitry Andric // of it, we need to use the largest of those to get the right size. 13410b57cec5SDimitry Andric if (MaxIndex == FunctionIndex && Attrs.size() > 1) 13420b57cec5SDimitry Andric MaxIndex = Attrs[Attrs.size() - 2].first; 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1); 1345480093f4SDimitry Andric for (const auto &Pair : Attrs) 13460b57cec5SDimitry Andric AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second; 13470b57cec5SDimitry Andric 13480b57cec5SDimitry Andric return getImpl(C, AttrVec); 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs, 13520b57cec5SDimitry Andric AttributeSet RetAttrs, 13530b57cec5SDimitry Andric ArrayRef<AttributeSet> ArgAttrs) { 13540b57cec5SDimitry Andric // Scan from the end to find the last argument with attributes. Most 13550b57cec5SDimitry Andric // arguments don't have attributes, so it's nice if we can have fewer unique 13560b57cec5SDimitry Andric // AttributeListImpls by dropping empty attribute sets at the end of the list. 13570b57cec5SDimitry Andric unsigned NumSets = 0; 13580b57cec5SDimitry Andric for (size_t I = ArgAttrs.size(); I != 0; --I) { 13590b57cec5SDimitry Andric if (ArgAttrs[I - 1].hasAttributes()) { 13600b57cec5SDimitry Andric NumSets = I + 2; 13610b57cec5SDimitry Andric break; 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric } 13640b57cec5SDimitry Andric if (NumSets == 0) { 13650b57cec5SDimitry Andric // Check function and return attributes if we didn't have argument 13660b57cec5SDimitry Andric // attributes. 13670b57cec5SDimitry Andric if (RetAttrs.hasAttributes()) 13680b57cec5SDimitry Andric NumSets = 2; 13690b57cec5SDimitry Andric else if (FnAttrs.hasAttributes()) 13700b57cec5SDimitry Andric NumSets = 1; 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric // If all attribute sets were empty, we can use the empty attribute list. 13740b57cec5SDimitry Andric if (NumSets == 0) 13750b57cec5SDimitry Andric return {}; 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric SmallVector<AttributeSet, 8> AttrSets; 13780b57cec5SDimitry Andric AttrSets.reserve(NumSets); 13790b57cec5SDimitry Andric // If we have any attributes, we always have function attributes. 13800b57cec5SDimitry Andric AttrSets.push_back(FnAttrs); 13810b57cec5SDimitry Andric if (NumSets > 1) 13820b57cec5SDimitry Andric AttrSets.push_back(RetAttrs); 13830b57cec5SDimitry Andric if (NumSets > 2) { 13840b57cec5SDimitry Andric // Drop the empty argument attribute sets at the end. 13850b57cec5SDimitry Andric ArgAttrs = ArgAttrs.take_front(NumSets - 2); 1386e8d8bef9SDimitry Andric llvm::append_range(AttrSets, ArgAttrs); 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric return getImpl(C, AttrSets); 13900b57cec5SDimitry Andric } 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andric AttributeList AttributeList::get(LLVMContext &C, unsigned Index, 13930eae32dcSDimitry Andric AttributeSet Attrs) { 13940eae32dcSDimitry Andric if (!Attrs.hasAttributes()) 13950b57cec5SDimitry Andric return {}; 13960b57cec5SDimitry Andric Index = attrIdxToArrayIdx(Index); 13970b57cec5SDimitry Andric SmallVector<AttributeSet, 8> AttrSets(Index + 1); 13980eae32dcSDimitry Andric AttrSets[Index] = Attrs; 13990b57cec5SDimitry Andric return getImpl(C, AttrSets); 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric AttributeList AttributeList::get(LLVMContext &C, unsigned Index, 14030eae32dcSDimitry Andric const AttrBuilder &B) { 14040eae32dcSDimitry Andric return get(C, Index, AttributeSet::get(C, B)); 14050eae32dcSDimitry Andric } 14060eae32dcSDimitry Andric 14070eae32dcSDimitry Andric AttributeList AttributeList::get(LLVMContext &C, unsigned Index, 14080b57cec5SDimitry Andric ArrayRef<Attribute::AttrKind> Kinds) { 14090b57cec5SDimitry Andric SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; 14100b57cec5SDimitry Andric for (const auto K : Kinds) 14110b57cec5SDimitry Andric Attrs.emplace_back(Index, Attribute::get(C, K)); 14120b57cec5SDimitry Andric return get(C, Attrs); 14130b57cec5SDimitry Andric } 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric AttributeList AttributeList::get(LLVMContext &C, unsigned Index, 14165ffd83dbSDimitry Andric ArrayRef<Attribute::AttrKind> Kinds, 14175ffd83dbSDimitry Andric ArrayRef<uint64_t> Values) { 14185ffd83dbSDimitry Andric assert(Kinds.size() == Values.size() && "Mismatched attribute values."); 14195ffd83dbSDimitry Andric SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; 14205ffd83dbSDimitry Andric auto VI = Values.begin(); 14215ffd83dbSDimitry Andric for (const auto K : Kinds) 14225ffd83dbSDimitry Andric Attrs.emplace_back(Index, Attribute::get(C, K, *VI++)); 14235ffd83dbSDimitry Andric return get(C, Attrs); 14245ffd83dbSDimitry Andric } 14255ffd83dbSDimitry Andric 14265ffd83dbSDimitry Andric AttributeList AttributeList::get(LLVMContext &C, unsigned Index, 14270b57cec5SDimitry Andric ArrayRef<StringRef> Kinds) { 14280b57cec5SDimitry Andric SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; 1429480093f4SDimitry Andric for (const auto &K : Kinds) 14300b57cec5SDimitry Andric Attrs.emplace_back(Index, Attribute::get(C, K)); 14310b57cec5SDimitry Andric return get(C, Attrs); 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric 14340b57cec5SDimitry Andric AttributeList AttributeList::get(LLVMContext &C, 14350b57cec5SDimitry Andric ArrayRef<AttributeList> Attrs) { 14360b57cec5SDimitry Andric if (Attrs.empty()) 14370b57cec5SDimitry Andric return {}; 14380b57cec5SDimitry Andric if (Attrs.size() == 1) 14390b57cec5SDimitry Andric return Attrs[0]; 14400b57cec5SDimitry Andric 14410b57cec5SDimitry Andric unsigned MaxSize = 0; 1442480093f4SDimitry Andric for (const auto &List : Attrs) 14430b57cec5SDimitry Andric MaxSize = std::max(MaxSize, List.getNumAttrSets()); 14440b57cec5SDimitry Andric 14450b57cec5SDimitry Andric // If every list was empty, there is no point in merging the lists. 14460b57cec5SDimitry Andric if (MaxSize == 0) 14470b57cec5SDimitry Andric return {}; 14480b57cec5SDimitry Andric 14490b57cec5SDimitry Andric SmallVector<AttributeSet, 8> NewAttrSets(MaxSize); 14500b57cec5SDimitry Andric for (unsigned I = 0; I < MaxSize; ++I) { 145104eeddc0SDimitry Andric AttrBuilder CurBuilder(C); 1452480093f4SDimitry Andric for (const auto &List : Attrs) 145304eeddc0SDimitry Andric CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1))); 14540b57cec5SDimitry Andric NewAttrSets[I] = AttributeSet::get(C, CurBuilder); 14550b57cec5SDimitry Andric } 14560b57cec5SDimitry Andric 14570b57cec5SDimitry Andric return getImpl(C, NewAttrSets); 14580b57cec5SDimitry Andric } 14590b57cec5SDimitry Andric 1460349cc55cSDimitry Andric AttributeList 1461349cc55cSDimitry Andric AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, 14620b57cec5SDimitry Andric Attribute::AttrKind Kind) const { 1463e8d8bef9SDimitry Andric AttributeSet Attrs = getAttributes(Index); 1464bdd1243dSDimitry Andric if (Attrs.hasAttribute(Kind)) 1465bdd1243dSDimitry Andric return *this; 1466e8d8bef9SDimitry Andric // TODO: Insert at correct position and avoid sort. 1467e8d8bef9SDimitry Andric SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end()); 1468e8d8bef9SDimitry Andric NewAttrs.push_back(Attribute::get(C, Kind)); 1469349cc55cSDimitry Andric return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs)); 14700b57cec5SDimitry Andric } 14710b57cec5SDimitry Andric 1472349cc55cSDimitry Andric AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, 14730b57cec5SDimitry Andric StringRef Kind, 14740b57cec5SDimitry Andric StringRef Value) const { 147504eeddc0SDimitry Andric AttrBuilder B(C); 14760b57cec5SDimitry Andric B.addAttribute(Kind, Value); 1477349cc55cSDimitry Andric return addAttributesAtIndex(C, Index, B); 14780b57cec5SDimitry Andric } 14790b57cec5SDimitry Andric 1480349cc55cSDimitry Andric AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, 14810b57cec5SDimitry Andric Attribute A) const { 148204eeddc0SDimitry Andric AttrBuilder B(C); 14830b57cec5SDimitry Andric B.addAttribute(A); 1484349cc55cSDimitry Andric return addAttributesAtIndex(C, Index, B); 14850b57cec5SDimitry Andric } 14860b57cec5SDimitry Andric 1487349cc55cSDimitry Andric AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C, 1488349cc55cSDimitry Andric unsigned Index, 1489e8d8bef9SDimitry Andric AttributeSet Attrs) const { 1490e8d8bef9SDimitry Andric Index = attrIdxToArrayIdx(Index); 1491e8d8bef9SDimitry Andric SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); 1492e8d8bef9SDimitry Andric if (Index >= AttrSets.size()) 1493e8d8bef9SDimitry Andric AttrSets.resize(Index + 1); 1494e8d8bef9SDimitry Andric AttrSets[Index] = Attrs; 1495bdd1243dSDimitry Andric 1496bdd1243dSDimitry Andric // Remove trailing empty attribute sets. 1497bdd1243dSDimitry Andric while (!AttrSets.empty() && !AttrSets.back().hasAttributes()) 1498bdd1243dSDimitry Andric AttrSets.pop_back(); 1499bdd1243dSDimitry Andric if (AttrSets.empty()) 1500bdd1243dSDimitry Andric return {}; 1501e8d8bef9SDimitry Andric return AttributeList::getImpl(C, AttrSets); 1502e8d8bef9SDimitry Andric } 1503e8d8bef9SDimitry Andric 1504349cc55cSDimitry Andric AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C, 1505349cc55cSDimitry Andric unsigned Index, 15060b57cec5SDimitry Andric const AttrBuilder &B) const { 15070b57cec5SDimitry Andric if (!B.hasAttributes()) 15080b57cec5SDimitry Andric return *this; 15090b57cec5SDimitry Andric 15100b57cec5SDimitry Andric if (!pImpl) 15110b57cec5SDimitry Andric return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}}); 15120b57cec5SDimitry Andric 151304eeddc0SDimitry Andric AttrBuilder Merged(C, getAttributes(Index)); 15140b57cec5SDimitry Andric Merged.merge(B); 1515349cc55cSDimitry Andric return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged)); 15160b57cec5SDimitry Andric } 15170b57cec5SDimitry Andric 15180b57cec5SDimitry Andric AttributeList AttributeList::addParamAttribute(LLVMContext &C, 15190b57cec5SDimitry Andric ArrayRef<unsigned> ArgNos, 15200b57cec5SDimitry Andric Attribute A) const { 15215ffd83dbSDimitry Andric assert(llvm::is_sorted(ArgNos)); 15220b57cec5SDimitry Andric 15230b57cec5SDimitry Andric SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); 15240b57cec5SDimitry Andric unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex); 15250b57cec5SDimitry Andric if (MaxIndex >= AttrSets.size()) 15260b57cec5SDimitry Andric AttrSets.resize(MaxIndex + 1); 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric for (unsigned ArgNo : ArgNos) { 15290b57cec5SDimitry Andric unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex); 153004eeddc0SDimitry Andric AttrBuilder B(C, AttrSets[Index]); 15310b57cec5SDimitry Andric B.addAttribute(A); 15320b57cec5SDimitry Andric AttrSets[Index] = AttributeSet::get(C, B); 15330b57cec5SDimitry Andric } 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric return getImpl(C, AttrSets); 15360b57cec5SDimitry Andric } 15370b57cec5SDimitry Andric 1538349cc55cSDimitry Andric AttributeList 1539349cc55cSDimitry Andric AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index, 15400b57cec5SDimitry Andric Attribute::AttrKind Kind) const { 1541bdd1243dSDimitry Andric AttributeSet Attrs = getAttributes(Index); 1542bdd1243dSDimitry Andric AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind); 1543bdd1243dSDimitry Andric if (Attrs == NewAttrs) 1544349cc55cSDimitry Andric return *this; 1545bdd1243dSDimitry Andric return setAttributesAtIndex(C, Index, NewAttrs); 15460b57cec5SDimitry Andric } 15470b57cec5SDimitry Andric 1548349cc55cSDimitry Andric AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C, 1549349cc55cSDimitry Andric unsigned Index, 15500b57cec5SDimitry Andric StringRef Kind) const { 1551bdd1243dSDimitry Andric AttributeSet Attrs = getAttributes(Index); 1552bdd1243dSDimitry Andric AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind); 1553bdd1243dSDimitry Andric if (Attrs == NewAttrs) 1554349cc55cSDimitry Andric return *this; 1555bdd1243dSDimitry Andric return setAttributesAtIndex(C, Index, NewAttrs); 15560b57cec5SDimitry Andric } 15570b57cec5SDimitry Andric 155804eeddc0SDimitry Andric AttributeList AttributeList::removeAttributesAtIndex( 155904eeddc0SDimitry Andric LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const { 1560fe6060f1SDimitry Andric AttributeSet Attrs = getAttributes(Index); 1561fe6060f1SDimitry Andric AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove); 1562fe6060f1SDimitry Andric // If nothing was removed, return the original list. 1563fe6060f1SDimitry Andric if (Attrs == NewAttrs) 1564fe6060f1SDimitry Andric return *this; 1565349cc55cSDimitry Andric return setAttributesAtIndex(C, Index, NewAttrs); 15660b57cec5SDimitry Andric } 15670b57cec5SDimitry Andric 1568349cc55cSDimitry Andric AttributeList 1569349cc55cSDimitry Andric AttributeList::removeAttributesAtIndex(LLVMContext &C, 15700b57cec5SDimitry Andric unsigned WithoutIndex) const { 15710b57cec5SDimitry Andric if (!pImpl) 15720b57cec5SDimitry Andric return {}; 1573bdd1243dSDimitry Andric if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets()) 15740b57cec5SDimitry Andric return *this; 1575bdd1243dSDimitry Andric return setAttributesAtIndex(C, WithoutIndex, AttributeSet()); 15760b57cec5SDimitry Andric } 15770b57cec5SDimitry Andric 1578349cc55cSDimitry Andric AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C, 1579349cc55cSDimitry Andric uint64_t Bytes) const { 158004eeddc0SDimitry Andric AttrBuilder B(C); 1581349cc55cSDimitry Andric B.addDereferenceableAttr(Bytes); 1582349cc55cSDimitry Andric return addRetAttributes(C, B); 1583349cc55cSDimitry Andric } 1584349cc55cSDimitry Andric 1585349cc55cSDimitry Andric AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C, 15860b57cec5SDimitry Andric unsigned Index, 15870b57cec5SDimitry Andric uint64_t Bytes) const { 158804eeddc0SDimitry Andric AttrBuilder B(C); 15890b57cec5SDimitry Andric B.addDereferenceableAttr(Bytes); 1590349cc55cSDimitry Andric return addParamAttributes(C, Index, B); 15910b57cec5SDimitry Andric } 15920b57cec5SDimitry Andric 15930b57cec5SDimitry Andric AttributeList 1594349cc55cSDimitry Andric AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index, 15950b57cec5SDimitry Andric uint64_t Bytes) const { 159604eeddc0SDimitry Andric AttrBuilder B(C); 15970b57cec5SDimitry Andric B.addDereferenceableOrNullAttr(Bytes); 1598349cc55cSDimitry Andric return addParamAttributes(C, Index, B); 15990b57cec5SDimitry Andric } 16000b57cec5SDimitry Andric 1601*0fca6ea1SDimitry Andric AttributeList AttributeList::addRangeRetAttr(LLVMContext &C, 1602*0fca6ea1SDimitry Andric const ConstantRange &CR) const { 1603*0fca6ea1SDimitry Andric AttrBuilder B(C); 1604*0fca6ea1SDimitry Andric B.addRangeAttr(CR); 1605*0fca6ea1SDimitry Andric return addRetAttributes(C, B); 1606*0fca6ea1SDimitry Andric } 1607*0fca6ea1SDimitry Andric 1608bdd1243dSDimitry Andric AttributeList AttributeList::addAllocSizeParamAttr( 1609bdd1243dSDimitry Andric LLVMContext &C, unsigned Index, unsigned ElemSizeArg, 1610bdd1243dSDimitry Andric const std::optional<unsigned> &NumElemsArg) { 161104eeddc0SDimitry Andric AttrBuilder B(C); 16120b57cec5SDimitry Andric B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); 1613349cc55cSDimitry Andric return addParamAttributes(C, Index, B); 1614fe6060f1SDimitry Andric } 1615fe6060f1SDimitry Andric 16160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16170b57cec5SDimitry Andric // AttributeList Accessor Methods 16180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16190b57cec5SDimitry Andric 1620349cc55cSDimitry Andric AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const { 16210b57cec5SDimitry Andric return getAttributes(ArgNo + FirstArgIndex); 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric 1624349cc55cSDimitry Andric AttributeSet AttributeList::getRetAttrs() const { 16250b57cec5SDimitry Andric return getAttributes(ReturnIndex); 16260b57cec5SDimitry Andric } 16270b57cec5SDimitry Andric 1628349cc55cSDimitry Andric AttributeSet AttributeList::getFnAttrs() const { 16290b57cec5SDimitry Andric return getAttributes(FunctionIndex); 16300b57cec5SDimitry Andric } 16310b57cec5SDimitry Andric 1632349cc55cSDimitry Andric bool AttributeList::hasAttributeAtIndex(unsigned Index, 16330b57cec5SDimitry Andric Attribute::AttrKind Kind) const { 16340b57cec5SDimitry Andric return getAttributes(Index).hasAttribute(Kind); 16350b57cec5SDimitry Andric } 16360b57cec5SDimitry Andric 1637349cc55cSDimitry Andric bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const { 16380b57cec5SDimitry Andric return getAttributes(Index).hasAttribute(Kind); 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 1641349cc55cSDimitry Andric bool AttributeList::hasAttributesAtIndex(unsigned Index) const { 16420b57cec5SDimitry Andric return getAttributes(Index).hasAttributes(); 16430b57cec5SDimitry Andric } 16440b57cec5SDimitry Andric 1645349cc55cSDimitry Andric bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const { 16460b57cec5SDimitry Andric return pImpl && pImpl->hasFnAttribute(Kind); 16470b57cec5SDimitry Andric } 16480b57cec5SDimitry Andric 1649349cc55cSDimitry Andric bool AttributeList::hasFnAttr(StringRef Kind) const { 1650349cc55cSDimitry Andric return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind); 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr, 16540b57cec5SDimitry Andric unsigned *Index) const { 16555ffd83dbSDimitry Andric return pImpl && pImpl->hasAttrSomewhere(Attr, Index); 16560b57cec5SDimitry Andric } 16570b57cec5SDimitry Andric 1658349cc55cSDimitry Andric Attribute AttributeList::getAttributeAtIndex(unsigned Index, 16590b57cec5SDimitry Andric Attribute::AttrKind Kind) const { 16600b57cec5SDimitry Andric return getAttributes(Index).getAttribute(Kind); 16610b57cec5SDimitry Andric } 16620b57cec5SDimitry Andric 1663349cc55cSDimitry Andric Attribute AttributeList::getAttributeAtIndex(unsigned Index, 1664349cc55cSDimitry Andric StringRef Kind) const { 16650b57cec5SDimitry Andric return getAttributes(Index).getAttribute(Kind); 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric 16688bcb0991SDimitry Andric MaybeAlign AttributeList::getRetAlignment() const { 16690b57cec5SDimitry Andric return getAttributes(ReturnIndex).getAlignment(); 16700b57cec5SDimitry Andric } 16710b57cec5SDimitry Andric 16728bcb0991SDimitry Andric MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const { 16730b57cec5SDimitry Andric return getAttributes(ArgNo + FirstArgIndex).getAlignment(); 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric 1676fe6060f1SDimitry Andric MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const { 1677fe6060f1SDimitry Andric return getAttributes(ArgNo + FirstArgIndex).getStackAlignment(); 1678fe6060f1SDimitry Andric } 1679fe6060f1SDimitry Andric 16800b57cec5SDimitry Andric Type *AttributeList::getParamByValType(unsigned Index) const { 16810b57cec5SDimitry Andric return getAttributes(Index+FirstArgIndex).getByValType(); 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric 1684e8d8bef9SDimitry Andric Type *AttributeList::getParamStructRetType(unsigned Index) const { 1685e8d8bef9SDimitry Andric return getAttributes(Index + FirstArgIndex).getStructRetType(); 1686e8d8bef9SDimitry Andric } 1687e8d8bef9SDimitry Andric 1688e8d8bef9SDimitry Andric Type *AttributeList::getParamByRefType(unsigned Index) const { 1689e8d8bef9SDimitry Andric return getAttributes(Index + FirstArgIndex).getByRefType(); 1690e8d8bef9SDimitry Andric } 1691e8d8bef9SDimitry Andric 16925ffd83dbSDimitry Andric Type *AttributeList::getParamPreallocatedType(unsigned Index) const { 16935ffd83dbSDimitry Andric return getAttributes(Index + FirstArgIndex).getPreallocatedType(); 16945ffd83dbSDimitry Andric } 16955ffd83dbSDimitry Andric 1696fe6060f1SDimitry Andric Type *AttributeList::getParamInAllocaType(unsigned Index) const { 1697fe6060f1SDimitry Andric return getAttributes(Index + FirstArgIndex).getInAllocaType(); 1698fe6060f1SDimitry Andric } 1699fe6060f1SDimitry Andric 1700fe6060f1SDimitry Andric Type *AttributeList::getParamElementType(unsigned Index) const { 1701fe6060f1SDimitry Andric return getAttributes(Index + FirstArgIndex).getElementType(); 1702fe6060f1SDimitry Andric } 1703fe6060f1SDimitry Andric 1704349cc55cSDimitry Andric MaybeAlign AttributeList::getFnStackAlignment() const { 1705349cc55cSDimitry Andric return getFnAttrs().getStackAlignment(); 17060b57cec5SDimitry Andric } 17070b57cec5SDimitry Andric 1708349cc55cSDimitry Andric MaybeAlign AttributeList::getRetStackAlignment() const { 1709349cc55cSDimitry Andric return getRetAttrs().getStackAlignment(); 17100b57cec5SDimitry Andric } 17110b57cec5SDimitry Andric 1712349cc55cSDimitry Andric uint64_t AttributeList::getRetDereferenceableBytes() const { 1713349cc55cSDimitry Andric return getRetAttrs().getDereferenceableBytes(); 17140b57cec5SDimitry Andric } 17150b57cec5SDimitry Andric 1716349cc55cSDimitry Andric uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const { 1717349cc55cSDimitry Andric return getParamAttrs(Index).getDereferenceableBytes(); 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric 1720349cc55cSDimitry Andric uint64_t AttributeList::getRetDereferenceableOrNullBytes() const { 1721349cc55cSDimitry Andric return getRetAttrs().getDereferenceableOrNullBytes(); 1722349cc55cSDimitry Andric } 1723349cc55cSDimitry Andric 1724349cc55cSDimitry Andric uint64_t 1725349cc55cSDimitry Andric AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const { 1726349cc55cSDimitry Andric return getParamAttrs(Index).getDereferenceableOrNullBytes(); 1727fe6060f1SDimitry Andric } 1728fe6060f1SDimitry Andric 172906c3fb27SDimitry Andric FPClassTest AttributeList::getRetNoFPClass() const { 173006c3fb27SDimitry Andric return getRetAttrs().getNoFPClass(); 173106c3fb27SDimitry Andric } 173206c3fb27SDimitry Andric 173306c3fb27SDimitry Andric FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const { 173406c3fb27SDimitry Andric return getParamAttrs(Index).getNoFPClass(); 173506c3fb27SDimitry Andric } 173606c3fb27SDimitry Andric 173781ad6265SDimitry Andric UWTableKind AttributeList::getUWTableKind() const { 173881ad6265SDimitry Andric return getFnAttrs().getUWTableKind(); 173981ad6265SDimitry Andric } 174081ad6265SDimitry Andric 174181ad6265SDimitry Andric AllocFnKind AttributeList::getAllocKind() const { 174281ad6265SDimitry Andric return getFnAttrs().getAllocKind(); 174381ad6265SDimitry Andric } 174481ad6265SDimitry Andric 1745bdd1243dSDimitry Andric MemoryEffects AttributeList::getMemoryEffects() const { 1746bdd1243dSDimitry Andric return getFnAttrs().getMemoryEffects(); 1747bdd1243dSDimitry Andric } 1748bdd1243dSDimitry Andric 17490b57cec5SDimitry Andric std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const { 17500b57cec5SDimitry Andric return getAttributes(Index).getAsString(InAttrGrp); 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric AttributeSet AttributeList::getAttributes(unsigned Index) const { 17540b57cec5SDimitry Andric Index = attrIdxToArrayIdx(Index); 17550b57cec5SDimitry Andric if (!pImpl || Index >= getNumAttrSets()) 17560b57cec5SDimitry Andric return {}; 17570b57cec5SDimitry Andric return pImpl->begin()[Index]; 17580b57cec5SDimitry Andric } 17590b57cec5SDimitry Andric 1760fe6060f1SDimitry Andric bool AttributeList::hasParentContext(LLVMContext &C) const { 1761fe6060f1SDimitry Andric assert(!isEmpty() && "an empty attribute list has no parent context"); 1762fe6060f1SDimitry Andric FoldingSetNodeID ID; 1763fe6060f1SDimitry Andric pImpl->Profile(ID); 1764fe6060f1SDimitry Andric void *Unused; 1765fe6060f1SDimitry Andric return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl; 1766fe6060f1SDimitry Andric } 1767fe6060f1SDimitry Andric 17680b57cec5SDimitry Andric AttributeList::iterator AttributeList::begin() const { 17690b57cec5SDimitry Andric return pImpl ? pImpl->begin() : nullptr; 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric AttributeList::iterator AttributeList::end() const { 17730b57cec5SDimitry Andric return pImpl ? pImpl->end() : nullptr; 17740b57cec5SDimitry Andric } 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17770b57cec5SDimitry Andric // AttributeList Introspection Methods 17780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17790b57cec5SDimitry Andric 17800b57cec5SDimitry Andric unsigned AttributeList::getNumAttrSets() const { 17810b57cec5SDimitry Andric return pImpl ? pImpl->NumAttrSets : 0; 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric 1784fe6060f1SDimitry Andric void AttributeList::print(raw_ostream &O) const { 1785fe6060f1SDimitry Andric O << "AttributeList[\n"; 17860b57cec5SDimitry Andric 1787349cc55cSDimitry Andric for (unsigned i : indexes()) { 1788fe6060f1SDimitry Andric if (!getAttributes(i).hasAttributes()) 1789fe6060f1SDimitry Andric continue; 1790fe6060f1SDimitry Andric O << " { "; 1791fe6060f1SDimitry Andric switch (i) { 1792fe6060f1SDimitry Andric case AttrIndex::ReturnIndex: 1793fe6060f1SDimitry Andric O << "return"; 1794fe6060f1SDimitry Andric break; 1795fe6060f1SDimitry Andric case AttrIndex::FunctionIndex: 1796fe6060f1SDimitry Andric O << "function"; 1797fe6060f1SDimitry Andric break; 1798fe6060f1SDimitry Andric default: 1799fe6060f1SDimitry Andric O << "arg(" << i - AttrIndex::FirstArgIndex << ")"; 1800fe6060f1SDimitry Andric } 1801fe6060f1SDimitry Andric O << " => " << getAsString(i) << " }\n"; 18020b57cec5SDimitry Andric } 18030b57cec5SDimitry Andric 1804fe6060f1SDimitry Andric O << "]\n"; 18050b57cec5SDimitry Andric } 1806fe6060f1SDimitry Andric 1807fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1808fe6060f1SDimitry Andric LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); } 18090b57cec5SDimitry Andric #endif 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18120b57cec5SDimitry Andric // AttrBuilder Method Implementations 18130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18140b57cec5SDimitry Andric 181504eeddc0SDimitry Andric AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) { 181604eeddc0SDimitry Andric append_range(Attrs, AS); 181704eeddc0SDimitry Andric assert(is_sorted(Attrs) && "AttributeSet should be sorted"); 18180b57cec5SDimitry Andric } 18190b57cec5SDimitry Andric 182004eeddc0SDimitry Andric void AttrBuilder::clear() { Attrs.clear(); } 18210b57cec5SDimitry Andric 182204eeddc0SDimitry Andric /// Attribute comparator that only compares attribute keys. Enum attributes are 182304eeddc0SDimitry Andric /// sorted before string attributes. 182404eeddc0SDimitry Andric struct AttributeComparator { 182504eeddc0SDimitry Andric bool operator()(Attribute A0, Attribute A1) const { 182604eeddc0SDimitry Andric bool A0IsString = A0.isStringAttribute(); 182704eeddc0SDimitry Andric bool A1IsString = A1.isStringAttribute(); 182804eeddc0SDimitry Andric if (A0IsString) { 182904eeddc0SDimitry Andric if (A1IsString) 183004eeddc0SDimitry Andric return A0.getKindAsString() < A1.getKindAsString(); 183104eeddc0SDimitry Andric else 183204eeddc0SDimitry Andric return false; 1833fe6060f1SDimitry Andric } 183404eeddc0SDimitry Andric if (A1IsString) 183504eeddc0SDimitry Andric return true; 183604eeddc0SDimitry Andric return A0.getKindAsEnum() < A1.getKindAsEnum(); 1837349cc55cSDimitry Andric } 183804eeddc0SDimitry Andric bool operator()(Attribute A0, Attribute::AttrKind Kind) const { 183904eeddc0SDimitry Andric if (A0.isStringAttribute()) 184004eeddc0SDimitry Andric return false; 184104eeddc0SDimitry Andric return A0.getKindAsEnum() < Kind; 184204eeddc0SDimitry Andric } 184304eeddc0SDimitry Andric bool operator()(Attribute A0, StringRef Kind) const { 184404eeddc0SDimitry Andric if (A0.isStringAttribute()) 184504eeddc0SDimitry Andric return A0.getKindAsString() < Kind; 184604eeddc0SDimitry Andric return true; 184704eeddc0SDimitry Andric } 184804eeddc0SDimitry Andric }; 1849349cc55cSDimitry Andric 185004eeddc0SDimitry Andric template <typename K> 185104eeddc0SDimitry Andric static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind, 185204eeddc0SDimitry Andric Attribute Attr) { 185304eeddc0SDimitry Andric auto It = lower_bound(Attrs, Kind, AttributeComparator()); 185404eeddc0SDimitry Andric if (It != Attrs.end() && It->hasAttribute(Kind)) 185504eeddc0SDimitry Andric std::swap(*It, Attr); 185604eeddc0SDimitry Andric else 185704eeddc0SDimitry Andric Attrs.insert(It, Attr); 18580b57cec5SDimitry Andric } 18590b57cec5SDimitry Andric 18600b57cec5SDimitry Andric AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { 186104eeddc0SDimitry Andric if (Attr.isStringAttribute()) 186204eeddc0SDimitry Andric addAttributeImpl(Attrs, Attr.getKindAsString(), Attr); 186304eeddc0SDimitry Andric else 186404eeddc0SDimitry Andric addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr); 18650b57cec5SDimitry Andric return *this; 18660b57cec5SDimitry Andric } 18670b57cec5SDimitry Andric 186804eeddc0SDimitry Andric AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) { 186904eeddc0SDimitry Andric addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind)); 18700b57cec5SDimitry Andric return *this; 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric 18730b57cec5SDimitry Andric AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) { 187404eeddc0SDimitry Andric addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V)); 18750b57cec5SDimitry Andric return *this; 18760b57cec5SDimitry Andric } 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { 18790b57cec5SDimitry Andric assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); 188004eeddc0SDimitry Andric auto It = lower_bound(Attrs, Val, AttributeComparator()); 188104eeddc0SDimitry Andric if (It != Attrs.end() && It->hasAttribute(Val)) 188204eeddc0SDimitry Andric Attrs.erase(It); 18830b57cec5SDimitry Andric return *this; 18840b57cec5SDimitry Andric } 18850b57cec5SDimitry Andric 18860b57cec5SDimitry Andric AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { 188704eeddc0SDimitry Andric auto It = lower_bound(Attrs, A, AttributeComparator()); 188804eeddc0SDimitry Andric if (It != Attrs.end() && It->hasAttribute(A)) 188904eeddc0SDimitry Andric Attrs.erase(It); 1890349cc55cSDimitry Andric return *this; 1891349cc55cSDimitry Andric } 1892349cc55cSDimitry Andric 1893bdd1243dSDimitry Andric std::optional<uint64_t> 1894bdd1243dSDimitry Andric AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const { 189504eeddc0SDimitry Andric assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute"); 189604eeddc0SDimitry Andric Attribute A = getAttribute(Kind); 1897bdd1243dSDimitry Andric if (A.isValid()) 1898bdd1243dSDimitry Andric return A.getValueAsInt(); 1899bdd1243dSDimitry Andric return std::nullopt; 1900349cc55cSDimitry Andric } 1901349cc55cSDimitry Andric 1902349cc55cSDimitry Andric AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind, 1903349cc55cSDimitry Andric uint64_t Value) { 190404eeddc0SDimitry Andric return addAttribute(Attribute::get(Ctx, Kind, Value)); 19050b57cec5SDimitry Andric } 19060b57cec5SDimitry Andric 1907bdd1243dSDimitry Andric std::optional<std::pair<unsigned, std::optional<unsigned>>> 1908bdd1243dSDimitry Andric AttrBuilder::getAllocSizeArgs() const { 1909bdd1243dSDimitry Andric Attribute A = getAttribute(Attribute::AllocSize); 1910bdd1243dSDimitry Andric if (A.isValid()) 1911bdd1243dSDimitry Andric return A.getAllocSizeArgs(); 1912bdd1243dSDimitry Andric return std::nullopt; 1913fe6060f1SDimitry Andric } 1914fe6060f1SDimitry Andric 19158bcb0991SDimitry Andric AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) { 19168bcb0991SDimitry Andric if (!Align) 19178bcb0991SDimitry Andric return *this; 19180b57cec5SDimitry Andric 19195ffd83dbSDimitry Andric assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large."); 1920349cc55cSDimitry Andric return addRawIntAttr(Attribute::Alignment, Align->value()); 19210b57cec5SDimitry Andric } 19220b57cec5SDimitry Andric 19238bcb0991SDimitry Andric AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) { 19240b57cec5SDimitry Andric // Default alignment, allow the target to define how to align it. 19258bcb0991SDimitry Andric if (!Align) 19268bcb0991SDimitry Andric return *this; 19270b57cec5SDimitry Andric 19288bcb0991SDimitry Andric assert(*Align <= 0x100 && "Alignment too large."); 1929349cc55cSDimitry Andric return addRawIntAttr(Attribute::StackAlignment, Align->value()); 19300b57cec5SDimitry Andric } 19310b57cec5SDimitry Andric 19320b57cec5SDimitry Andric AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) { 19330b57cec5SDimitry Andric if (Bytes == 0) return *this; 19340b57cec5SDimitry Andric 1935349cc55cSDimitry Andric return addRawIntAttr(Attribute::Dereferenceable, Bytes); 19360b57cec5SDimitry Andric } 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) { 19390b57cec5SDimitry Andric if (Bytes == 0) 19400b57cec5SDimitry Andric return *this; 19410b57cec5SDimitry Andric 1942349cc55cSDimitry Andric return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes); 19430b57cec5SDimitry Andric } 19440b57cec5SDimitry Andric 1945bdd1243dSDimitry Andric AttrBuilder & 1946bdd1243dSDimitry Andric AttrBuilder::addAllocSizeAttr(unsigned ElemSize, 1947bdd1243dSDimitry Andric const std::optional<unsigned> &NumElems) { 19480b57cec5SDimitry Andric return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems)); 19490b57cec5SDimitry Andric } 19500b57cec5SDimitry Andric 19510b57cec5SDimitry Andric AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) { 19520b57cec5SDimitry Andric // (0, 0) is our "not present" value, so we need to check for it here. 19530b57cec5SDimitry Andric assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)"); 1954349cc55cSDimitry Andric return addRawIntAttr(Attribute::AllocSize, RawArgs); 19550b57cec5SDimitry Andric } 19560b57cec5SDimitry Andric 1957fe6060f1SDimitry Andric AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue, 1958bdd1243dSDimitry Andric std::optional<unsigned> MaxValue) { 1959fe6060f1SDimitry Andric return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue)); 1960fe6060f1SDimitry Andric } 1961fe6060f1SDimitry Andric 1962fe6060f1SDimitry Andric AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) { 1963fe6060f1SDimitry Andric // (0, 0) is not present hence ignore this case 1964fe6060f1SDimitry Andric if (RawArgs == 0) 19650b57cec5SDimitry Andric return *this; 1966fe6060f1SDimitry Andric 1967349cc55cSDimitry Andric return addRawIntAttr(Attribute::VScaleRange, RawArgs); 1968fe6060f1SDimitry Andric } 1969fe6060f1SDimitry Andric 197081ad6265SDimitry Andric AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) { 197181ad6265SDimitry Andric if (Kind == UWTableKind::None) 197281ad6265SDimitry Andric return *this; 197381ad6265SDimitry Andric return addRawIntAttr(Attribute::UWTable, uint64_t(Kind)); 197481ad6265SDimitry Andric } 197581ad6265SDimitry Andric 1976bdd1243dSDimitry Andric AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) { 1977bdd1243dSDimitry Andric return addRawIntAttr(Attribute::Memory, ME.toIntValue()); 1978bdd1243dSDimitry Andric } 1979bdd1243dSDimitry Andric 198006c3fb27SDimitry Andric AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) { 198106c3fb27SDimitry Andric if (Mask == fcNone) 198206c3fb27SDimitry Andric return *this; 198306c3fb27SDimitry Andric 198406c3fb27SDimitry Andric return addRawIntAttr(Attribute::NoFPClass, Mask); 198506c3fb27SDimitry Andric } 198606c3fb27SDimitry Andric 198781ad6265SDimitry Andric AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) { 198881ad6265SDimitry Andric return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind)); 198981ad6265SDimitry Andric } 199081ad6265SDimitry Andric 1991fe6060f1SDimitry Andric Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const { 199204eeddc0SDimitry Andric assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute"); 199304eeddc0SDimitry Andric Attribute A = getAttribute(Kind); 199404eeddc0SDimitry Andric return A.isValid() ? A.getValueAsType() : nullptr; 1995fe6060f1SDimitry Andric } 1996fe6060f1SDimitry Andric 1997fe6060f1SDimitry Andric AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) { 199804eeddc0SDimitry Andric return addAttribute(Attribute::get(Ctx, Kind, Ty)); 1999fe6060f1SDimitry Andric } 2000fe6060f1SDimitry Andric 2001fe6060f1SDimitry Andric AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) { 2002fe6060f1SDimitry Andric return addTypeAttr(Attribute::ByVal, Ty); 20030b57cec5SDimitry Andric } 20040b57cec5SDimitry Andric 2005e8d8bef9SDimitry Andric AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) { 2006fe6060f1SDimitry Andric return addTypeAttr(Attribute::StructRet, Ty); 2007e8d8bef9SDimitry Andric } 2008e8d8bef9SDimitry Andric 2009e8d8bef9SDimitry Andric AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) { 2010fe6060f1SDimitry Andric return addTypeAttr(Attribute::ByRef, Ty); 2011e8d8bef9SDimitry Andric } 2012e8d8bef9SDimitry Andric 20135ffd83dbSDimitry Andric AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) { 2014fe6060f1SDimitry Andric return addTypeAttr(Attribute::Preallocated, Ty); 2015fe6060f1SDimitry Andric } 2016fe6060f1SDimitry Andric 2017fe6060f1SDimitry Andric AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) { 2018fe6060f1SDimitry Andric return addTypeAttr(Attribute::InAlloca, Ty); 20195ffd83dbSDimitry Andric } 20205ffd83dbSDimitry Andric 2021*0fca6ea1SDimitry Andric AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind, 2022*0fca6ea1SDimitry Andric const ConstantRange &CR) { 2023*0fca6ea1SDimitry Andric return addAttribute(Attribute::get(Ctx, Kind, CR)); 2024*0fca6ea1SDimitry Andric } 2025*0fca6ea1SDimitry Andric 2026*0fca6ea1SDimitry Andric AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) { 2027*0fca6ea1SDimitry Andric return addConstantRangeAttr(Attribute::Range, CR); 2028*0fca6ea1SDimitry Andric } 2029*0fca6ea1SDimitry Andric 2030*0fca6ea1SDimitry Andric AttrBuilder & 2031*0fca6ea1SDimitry Andric AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind, 2032*0fca6ea1SDimitry Andric ArrayRef<ConstantRange> Val) { 2033*0fca6ea1SDimitry Andric return addAttribute(Attribute::get(Ctx, Kind, Val)); 2034*0fca6ea1SDimitry Andric } 2035*0fca6ea1SDimitry Andric 2036*0fca6ea1SDimitry Andric AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) { 2037*0fca6ea1SDimitry Andric return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef()); 2038*0fca6ea1SDimitry Andric } 2039*0fca6ea1SDimitry Andric 20400b57cec5SDimitry Andric AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { 204104eeddc0SDimitry Andric // TODO: Could make this O(n) as we're merging two sorted lists. 204204eeddc0SDimitry Andric for (const auto &I : B.attrs()) 204304eeddc0SDimitry Andric addAttribute(I); 20440b57cec5SDimitry Andric 20450b57cec5SDimitry Andric return *this; 20460b57cec5SDimitry Andric } 20470b57cec5SDimitry Andric 204804eeddc0SDimitry Andric AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) { 204904eeddc0SDimitry Andric erase_if(Attrs, [&](Attribute A) { return AM.contains(A); }); 20500b57cec5SDimitry Andric return *this; 20510b57cec5SDimitry Andric } 20520b57cec5SDimitry Andric 205304eeddc0SDimitry Andric bool AttrBuilder::overlaps(const AttributeMask &AM) const { 205404eeddc0SDimitry Andric return any_of(Attrs, [&](Attribute A) { return AM.contains(A); }); 205504eeddc0SDimitry Andric } 20560b57cec5SDimitry Andric 205704eeddc0SDimitry Andric Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const { 205804eeddc0SDimitry Andric assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); 205904eeddc0SDimitry Andric auto It = lower_bound(Attrs, A, AttributeComparator()); 206004eeddc0SDimitry Andric if (It != Attrs.end() && It->hasAttribute(A)) 206104eeddc0SDimitry Andric return *It; 206204eeddc0SDimitry Andric return {}; 206304eeddc0SDimitry Andric } 20640b57cec5SDimitry Andric 206504eeddc0SDimitry Andric Attribute AttrBuilder::getAttribute(StringRef A) const { 206604eeddc0SDimitry Andric auto It = lower_bound(Attrs, A, AttributeComparator()); 206704eeddc0SDimitry Andric if (It != Attrs.end() && It->hasAttribute(A)) 206804eeddc0SDimitry Andric return *It; 206904eeddc0SDimitry Andric return {}; 207004eeddc0SDimitry Andric } 207104eeddc0SDimitry Andric 207204eeddc0SDimitry Andric bool AttrBuilder::contains(Attribute::AttrKind A) const { 207304eeddc0SDimitry Andric return getAttribute(A).isValid(); 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric bool AttrBuilder::contains(StringRef A) const { 207704eeddc0SDimitry Andric return getAttribute(A).isValid(); 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric 2080e8d8bef9SDimitry Andric bool AttrBuilder::operator==(const AttrBuilder &B) const { 208104eeddc0SDimitry Andric return Attrs == B.Attrs; 20820b57cec5SDimitry Andric } 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20850b57cec5SDimitry Andric // AttributeFuncs Function Defintions 20860b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20870b57cec5SDimitry Andric 208806c3fb27SDimitry Andric /// Returns true if this is a type legal for the 'nofpclass' attribute. This 208906c3fb27SDimitry Andric /// follows the same type rules as FPMathOperator. 209006c3fb27SDimitry Andric /// 209106c3fb27SDimitry Andric /// TODO: Consider relaxing to any FP type struct fields. 209206c3fb27SDimitry Andric bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) { 209306c3fb27SDimitry Andric while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) 209406c3fb27SDimitry Andric Ty = ArrTy->getElementType(); 209506c3fb27SDimitry Andric return Ty->isFPOrFPVectorTy(); 209606c3fb27SDimitry Andric } 209706c3fb27SDimitry Andric 20980b57cec5SDimitry Andric /// Which attributes cannot be applied to a type. 209981ad6265SDimitry Andric AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, 210081ad6265SDimitry Andric AttributeSafetyKind ASK) { 210104eeddc0SDimitry Andric AttributeMask Incompatible; 21020b57cec5SDimitry Andric 210381ad6265SDimitry Andric if (!Ty->isIntegerTy()) { 210404eeddc0SDimitry Andric // Attributes that only apply to integers. 210581ad6265SDimitry Andric if (ASK & ASK_SAFE_TO_DROP) 210681ad6265SDimitry Andric Incompatible.addAttribute(Attribute::AllocAlign); 210781ad6265SDimitry Andric if (ASK & ASK_UNSAFE_TO_DROP) 210881ad6265SDimitry Andric Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt); 210981ad6265SDimitry Andric } 21100b57cec5SDimitry Andric 2111*0fca6ea1SDimitry Andric if (!Ty->isIntOrIntVectorTy()) { 2112*0fca6ea1SDimitry Andric // Attributes that only apply to integers or vector of integers. 2113*0fca6ea1SDimitry Andric if (ASK & ASK_SAFE_TO_DROP) 2114*0fca6ea1SDimitry Andric Incompatible.addAttribute(Attribute::Range); 2115*0fca6ea1SDimitry Andric } 2116*0fca6ea1SDimitry Andric 211781ad6265SDimitry Andric if (!Ty->isPointerTy()) { 211804eeddc0SDimitry Andric // Attributes that only apply to pointers. 211981ad6265SDimitry Andric if (ASK & ASK_SAFE_TO_DROP) 212081ad6265SDimitry Andric Incompatible.addAttribute(Attribute::NoAlias) 21210b57cec5SDimitry Andric .addAttribute(Attribute::NoCapture) 21220b57cec5SDimitry Andric .addAttribute(Attribute::NonNull) 2123fe6060f1SDimitry Andric .addAttribute(Attribute::ReadNone) 2124fe6060f1SDimitry Andric .addAttribute(Attribute::ReadOnly) 212504eeddc0SDimitry Andric .addAttribute(Attribute::Dereferenceable) 21265f757f3fSDimitry Andric .addAttribute(Attribute::DereferenceableOrNull) 21275f757f3fSDimitry Andric .addAttribute(Attribute::Writable) 2128*0fca6ea1SDimitry Andric .addAttribute(Attribute::DeadOnUnwind) 2129*0fca6ea1SDimitry Andric .addAttribute(Attribute::Initializes); 213081ad6265SDimitry Andric if (ASK & ASK_UNSAFE_TO_DROP) 213181ad6265SDimitry Andric Incompatible.addAttribute(Attribute::Nest) 213281ad6265SDimitry Andric .addAttribute(Attribute::SwiftError) 213304eeddc0SDimitry Andric .addAttribute(Attribute::Preallocated) 213404eeddc0SDimitry Andric .addAttribute(Attribute::InAlloca) 213504eeddc0SDimitry Andric .addAttribute(Attribute::ByVal) 213604eeddc0SDimitry Andric .addAttribute(Attribute::StructRet) 213704eeddc0SDimitry Andric .addAttribute(Attribute::ByRef) 213881ad6265SDimitry Andric .addAttribute(Attribute::ElementType) 213981ad6265SDimitry Andric .addAttribute(Attribute::AllocatedPointer); 214081ad6265SDimitry Andric } 214104eeddc0SDimitry Andric 214204eeddc0SDimitry Andric // Attributes that only apply to pointers or vectors of pointers. 214381ad6265SDimitry Andric if (!Ty->isPtrOrPtrVectorTy()) { 214481ad6265SDimitry Andric if (ASK & ASK_SAFE_TO_DROP) 214504eeddc0SDimitry Andric Incompatible.addAttribute(Attribute::Alignment); 214681ad6265SDimitry Andric } 2147e8d8bef9SDimitry Andric 214806c3fb27SDimitry Andric if (ASK & ASK_SAFE_TO_DROP) { 214906c3fb27SDimitry Andric if (!isNoFPClassCompatibleType(Ty)) 215006c3fb27SDimitry Andric Incompatible.addAttribute(Attribute::NoFPClass); 215106c3fb27SDimitry Andric } 215206c3fb27SDimitry Andric 2153e8d8bef9SDimitry Andric // Some attributes can apply to all "values" but there are no `void` values. 215481ad6265SDimitry Andric if (Ty->isVoidTy()) { 215581ad6265SDimitry Andric if (ASK & ASK_SAFE_TO_DROP) 2156e8d8bef9SDimitry Andric Incompatible.addAttribute(Attribute::NoUndef); 215781ad6265SDimitry Andric } 21580b57cec5SDimitry Andric 21590b57cec5SDimitry Andric return Incompatible; 21600b57cec5SDimitry Andric } 21610b57cec5SDimitry Andric 216204eeddc0SDimitry Andric AttributeMask AttributeFuncs::getUBImplyingAttributes() { 216304eeddc0SDimitry Andric AttributeMask AM; 216404eeddc0SDimitry Andric AM.addAttribute(Attribute::NoUndef); 216504eeddc0SDimitry Andric AM.addAttribute(Attribute::Dereferenceable); 216604eeddc0SDimitry Andric AM.addAttribute(Attribute::DereferenceableOrNull); 216704eeddc0SDimitry Andric return AM; 2168fe6060f1SDimitry Andric } 2169fe6060f1SDimitry Andric 217006c3fb27SDimitry Andric /// Callees with dynamic denormal modes are compatible with any caller mode. 217106c3fb27SDimitry Andric static bool denormModeCompatible(DenormalMode CallerMode, 217206c3fb27SDimitry Andric DenormalMode CalleeMode) { 217306c3fb27SDimitry Andric if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic()) 217406c3fb27SDimitry Andric return true; 217506c3fb27SDimitry Andric 217606c3fb27SDimitry Andric // If they don't exactly match, it's OK if the mismatched component is 217706c3fb27SDimitry Andric // dynamic. 217806c3fb27SDimitry Andric if (CalleeMode.Input == CallerMode.Input && 217906c3fb27SDimitry Andric CalleeMode.Output == DenormalMode::Dynamic) 218006c3fb27SDimitry Andric return true; 218106c3fb27SDimitry Andric 218206c3fb27SDimitry Andric if (CalleeMode.Output == CallerMode.Output && 218306c3fb27SDimitry Andric CalleeMode.Input == DenormalMode::Dynamic) 218406c3fb27SDimitry Andric return true; 218506c3fb27SDimitry Andric return false; 218606c3fb27SDimitry Andric } 218706c3fb27SDimitry Andric 218806c3fb27SDimitry Andric static bool checkDenormMode(const Function &Caller, const Function &Callee) { 218906c3fb27SDimitry Andric DenormalMode CallerMode = Caller.getDenormalModeRaw(); 219006c3fb27SDimitry Andric DenormalMode CalleeMode = Callee.getDenormalModeRaw(); 219106c3fb27SDimitry Andric 219206c3fb27SDimitry Andric if (denormModeCompatible(CallerMode, CalleeMode)) { 219306c3fb27SDimitry Andric DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw(); 219406c3fb27SDimitry Andric DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw(); 219506c3fb27SDimitry Andric if (CallerModeF32 == DenormalMode::getInvalid()) 219606c3fb27SDimitry Andric CallerModeF32 = CallerMode; 219706c3fb27SDimitry Andric if (CalleeModeF32 == DenormalMode::getInvalid()) 219806c3fb27SDimitry Andric CalleeModeF32 = CalleeMode; 219906c3fb27SDimitry Andric return denormModeCompatible(CallerModeF32, CalleeModeF32); 220006c3fb27SDimitry Andric } 220106c3fb27SDimitry Andric 220206c3fb27SDimitry Andric return false; 220306c3fb27SDimitry Andric } 220406c3fb27SDimitry Andric 2205*0fca6ea1SDimitry Andric static bool checkStrictFP(const Function &Caller, const Function &Callee) { 2206*0fca6ea1SDimitry Andric // Do not inline strictfp function into non-strictfp one. It would require 2207*0fca6ea1SDimitry Andric // conversion of all FP operations in host function to constrained intrinsics. 2208*0fca6ea1SDimitry Andric return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) || 2209*0fca6ea1SDimitry Andric Caller.getAttributes().hasFnAttr(Attribute::StrictFP); 2210*0fca6ea1SDimitry Andric } 2211*0fca6ea1SDimitry Andric 22120b57cec5SDimitry Andric template<typename AttrClass> 22130b57cec5SDimitry Andric static bool isEqual(const Function &Caller, const Function &Callee) { 22140b57cec5SDimitry Andric return Caller.getFnAttribute(AttrClass::getKind()) == 22150b57cec5SDimitry Andric Callee.getFnAttribute(AttrClass::getKind()); 22160b57cec5SDimitry Andric } 22170b57cec5SDimitry Andric 22184c2d3b02SDimitry Andric static bool isEqual(const Function &Caller, const Function &Callee, 22194c2d3b02SDimitry Andric const StringRef &AttrName) { 22204c2d3b02SDimitry Andric return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName); 22214c2d3b02SDimitry Andric } 22224c2d3b02SDimitry Andric 22230b57cec5SDimitry Andric /// Compute the logical AND of the attributes of the caller and the 22240b57cec5SDimitry Andric /// callee. 22250b57cec5SDimitry Andric /// 22260b57cec5SDimitry Andric /// This function sets the caller's attribute to false if the callee's attribute 22270b57cec5SDimitry Andric /// is false. 22280b57cec5SDimitry Andric template<typename AttrClass> 22290b57cec5SDimitry Andric static void setAND(Function &Caller, const Function &Callee) { 22300b57cec5SDimitry Andric if (AttrClass::isSet(Caller, AttrClass::getKind()) && 22310b57cec5SDimitry Andric !AttrClass::isSet(Callee, AttrClass::getKind())) 22320b57cec5SDimitry Andric AttrClass::set(Caller, AttrClass::getKind(), false); 22330b57cec5SDimitry Andric } 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric /// Compute the logical OR of the attributes of the caller and the 22360b57cec5SDimitry Andric /// callee. 22370b57cec5SDimitry Andric /// 22380b57cec5SDimitry Andric /// This function sets the caller's attribute to true if the callee's attribute 22390b57cec5SDimitry Andric /// is true. 22400b57cec5SDimitry Andric template<typename AttrClass> 22410b57cec5SDimitry Andric static void setOR(Function &Caller, const Function &Callee) { 22420b57cec5SDimitry Andric if (!AttrClass::isSet(Caller, AttrClass::getKind()) && 22430b57cec5SDimitry Andric AttrClass::isSet(Callee, AttrClass::getKind())) 22440b57cec5SDimitry Andric AttrClass::set(Caller, AttrClass::getKind(), true); 22450b57cec5SDimitry Andric } 22460b57cec5SDimitry Andric 22470b57cec5SDimitry Andric /// If the inlined function had a higher stack protection level than the 22480b57cec5SDimitry Andric /// calling function, then bump up the caller's stack protection level. 22490b57cec5SDimitry Andric static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { 225004eeddc0SDimitry Andric // If the calling function has *no* stack protection level (e.g. it was built 225104eeddc0SDimitry Andric // with Clang's -fno-stack-protector or no_stack_protector attribute), don't 225204eeddc0SDimitry Andric // change it as that could change the program's semantics. 225304eeddc0SDimitry Andric if (!Caller.hasStackProtectorFnAttr()) 225404eeddc0SDimitry Andric return; 225504eeddc0SDimitry Andric 22560b57cec5SDimitry Andric // If upgrading the SSP attribute, clear out the old SSP Attributes first. 22570b57cec5SDimitry Andric // Having multiple SSP attributes doesn't actually hurt, but it adds useless 22580b57cec5SDimitry Andric // clutter to the IR. 225904eeddc0SDimitry Andric AttributeMask OldSSPAttr; 22600b57cec5SDimitry Andric OldSSPAttr.addAttribute(Attribute::StackProtect) 22610b57cec5SDimitry Andric .addAttribute(Attribute::StackProtectStrong) 22620b57cec5SDimitry Andric .addAttribute(Attribute::StackProtectReq); 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric if (Callee.hasFnAttribute(Attribute::StackProtectReq)) { 2265349cc55cSDimitry Andric Caller.removeFnAttrs(OldSSPAttr); 22660b57cec5SDimitry Andric Caller.addFnAttr(Attribute::StackProtectReq); 22670b57cec5SDimitry Andric } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) && 22680b57cec5SDimitry Andric !Caller.hasFnAttribute(Attribute::StackProtectReq)) { 2269349cc55cSDimitry Andric Caller.removeFnAttrs(OldSSPAttr); 22700b57cec5SDimitry Andric Caller.addFnAttr(Attribute::StackProtectStrong); 22710b57cec5SDimitry Andric } else if (Callee.hasFnAttribute(Attribute::StackProtect) && 22720b57cec5SDimitry Andric !Caller.hasFnAttribute(Attribute::StackProtectReq) && 22730b57cec5SDimitry Andric !Caller.hasFnAttribute(Attribute::StackProtectStrong)) 22740b57cec5SDimitry Andric Caller.addFnAttr(Attribute::StackProtect); 22750b57cec5SDimitry Andric } 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric /// If the inlined function required stack probes, then ensure that 22780b57cec5SDimitry Andric /// the calling function has those too. 22790b57cec5SDimitry Andric static void adjustCallerStackProbes(Function &Caller, const Function &Callee) { 22800b57cec5SDimitry Andric if (!Caller.hasFnAttribute("probe-stack") && 22810b57cec5SDimitry Andric Callee.hasFnAttribute("probe-stack")) { 22820b57cec5SDimitry Andric Caller.addFnAttr(Callee.getFnAttribute("probe-stack")); 22830b57cec5SDimitry Andric } 22840b57cec5SDimitry Andric } 22850b57cec5SDimitry Andric 22860b57cec5SDimitry Andric /// If the inlined function defines the size of guard region 22870b57cec5SDimitry Andric /// on the stack, then ensure that the calling function defines a guard region 22880b57cec5SDimitry Andric /// that is no larger. 22890b57cec5SDimitry Andric static void 22900b57cec5SDimitry Andric adjustCallerStackProbeSize(Function &Caller, const Function &Callee) { 2291e8d8bef9SDimitry Andric Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size"); 2292e8d8bef9SDimitry Andric if (CalleeAttr.isValid()) { 2293e8d8bef9SDimitry Andric Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size"); 2294e8d8bef9SDimitry Andric if (CallerAttr.isValid()) { 2295e8d8bef9SDimitry Andric uint64_t CallerStackProbeSize, CalleeStackProbeSize; 2296e8d8bef9SDimitry Andric CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize); 2297e8d8bef9SDimitry Andric CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize); 2298e8d8bef9SDimitry Andric 22990b57cec5SDimitry Andric if (CallerStackProbeSize > CalleeStackProbeSize) { 2300e8d8bef9SDimitry Andric Caller.addFnAttr(CalleeAttr); 23010b57cec5SDimitry Andric } 23020b57cec5SDimitry Andric } else { 2303e8d8bef9SDimitry Andric Caller.addFnAttr(CalleeAttr); 23040b57cec5SDimitry Andric } 23050b57cec5SDimitry Andric } 23060b57cec5SDimitry Andric } 23070b57cec5SDimitry Andric 23080b57cec5SDimitry Andric /// If the inlined function defines a min legal vector width, then ensure 23090b57cec5SDimitry Andric /// the calling function has the same or larger min legal vector width. If the 23100b57cec5SDimitry Andric /// caller has the attribute, but the callee doesn't, we need to remove the 23110b57cec5SDimitry Andric /// attribute from the caller since we can't make any guarantees about the 23120b57cec5SDimitry Andric /// caller's requirements. 23130b57cec5SDimitry Andric /// This function is called after the inlining decision has been made so we have 23140b57cec5SDimitry Andric /// to merge the attribute this way. Heuristics that would use 23150b57cec5SDimitry Andric /// min-legal-vector-width to determine inline compatibility would need to be 23160b57cec5SDimitry Andric /// handled as part of inline cost analysis. 23170b57cec5SDimitry Andric static void 23180b57cec5SDimitry Andric adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) { 2319e8d8bef9SDimitry Andric Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width"); 2320e8d8bef9SDimitry Andric if (CallerAttr.isValid()) { 2321e8d8bef9SDimitry Andric Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width"); 2322e8d8bef9SDimitry Andric if (CalleeAttr.isValid()) { 2323e8d8bef9SDimitry Andric uint64_t CallerVectorWidth, CalleeVectorWidth; 2324e8d8bef9SDimitry Andric CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth); 2325e8d8bef9SDimitry Andric CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth); 23260b57cec5SDimitry Andric if (CallerVectorWidth < CalleeVectorWidth) 2327e8d8bef9SDimitry Andric Caller.addFnAttr(CalleeAttr); 23280b57cec5SDimitry Andric } else { 23290b57cec5SDimitry Andric // If the callee doesn't have the attribute then we don't know anything 23300b57cec5SDimitry Andric // and must drop the attribute from the caller. 23310b57cec5SDimitry Andric Caller.removeFnAttr("min-legal-vector-width"); 23320b57cec5SDimitry Andric } 23330b57cec5SDimitry Andric } 23340b57cec5SDimitry Andric } 23350b57cec5SDimitry Andric 23365ffd83dbSDimitry Andric /// If the inlined function has null_pointer_is_valid attribute, 23370b57cec5SDimitry Andric /// set this attribute in the caller post inlining. 23380b57cec5SDimitry Andric static void 23390b57cec5SDimitry Andric adjustNullPointerValidAttr(Function &Caller, const Function &Callee) { 23400b57cec5SDimitry Andric if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) { 23415ffd83dbSDimitry Andric Caller.addFnAttr(Attribute::NullPointerIsValid); 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric } 23440b57cec5SDimitry Andric 23455ffd83dbSDimitry Andric struct EnumAttr { 23465ffd83dbSDimitry Andric static bool isSet(const Function &Fn, 23475ffd83dbSDimitry Andric Attribute::AttrKind Kind) { 23485ffd83dbSDimitry Andric return Fn.hasFnAttribute(Kind); 23495ffd83dbSDimitry Andric } 23505ffd83dbSDimitry Andric 23515ffd83dbSDimitry Andric static void set(Function &Fn, 23525ffd83dbSDimitry Andric Attribute::AttrKind Kind, bool Val) { 23535ffd83dbSDimitry Andric if (Val) 23545ffd83dbSDimitry Andric Fn.addFnAttr(Kind); 23555ffd83dbSDimitry Andric else 23565ffd83dbSDimitry Andric Fn.removeFnAttr(Kind); 23575ffd83dbSDimitry Andric } 23585ffd83dbSDimitry Andric }; 23595ffd83dbSDimitry Andric 23605ffd83dbSDimitry Andric struct StrBoolAttr { 23615ffd83dbSDimitry Andric static bool isSet(const Function &Fn, 23625ffd83dbSDimitry Andric StringRef Kind) { 23635ffd83dbSDimitry Andric auto A = Fn.getFnAttribute(Kind); 2364*0fca6ea1SDimitry Andric return A.getValueAsString() == "true"; 23655ffd83dbSDimitry Andric } 23665ffd83dbSDimitry Andric 23675ffd83dbSDimitry Andric static void set(Function &Fn, 23685ffd83dbSDimitry Andric StringRef Kind, bool Val) { 23695ffd83dbSDimitry Andric Fn.addFnAttr(Kind, Val ? "true" : "false"); 23705ffd83dbSDimitry Andric } 23715ffd83dbSDimitry Andric }; 23725ffd83dbSDimitry Andric 23735ffd83dbSDimitry Andric #define GET_ATTR_NAMES 23745ffd83dbSDimitry Andric #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \ 23755ffd83dbSDimitry Andric struct ENUM_NAME##Attr : EnumAttr { \ 23765ffd83dbSDimitry Andric static enum Attribute::AttrKind getKind() { \ 23775ffd83dbSDimitry Andric return llvm::Attribute::ENUM_NAME; \ 23785ffd83dbSDimitry Andric } \ 23795ffd83dbSDimitry Andric }; 23805ffd83dbSDimitry Andric #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ 23815ffd83dbSDimitry Andric struct ENUM_NAME##Attr : StrBoolAttr { \ 23825ffd83dbSDimitry Andric static StringRef getKind() { return #DISPLAY_NAME; } \ 23835ffd83dbSDimitry Andric }; 23845ffd83dbSDimitry Andric #include "llvm/IR/Attributes.inc" 23855ffd83dbSDimitry Andric 23860b57cec5SDimitry Andric #define GET_ATTR_COMPAT_FUNC 23875ffd83dbSDimitry Andric #include "llvm/IR/Attributes.inc" 23880b57cec5SDimitry Andric 23890b57cec5SDimitry Andric bool AttributeFuncs::areInlineCompatible(const Function &Caller, 23900b57cec5SDimitry Andric const Function &Callee) { 23910b57cec5SDimitry Andric return hasCompatibleFnAttrs(Caller, Callee); 23920b57cec5SDimitry Andric } 23930b57cec5SDimitry Andric 2394e8d8bef9SDimitry Andric bool AttributeFuncs::areOutlineCompatible(const Function &A, 2395e8d8bef9SDimitry Andric const Function &B) { 2396e8d8bef9SDimitry Andric return hasCompatibleFnAttrs(A, B); 2397e8d8bef9SDimitry Andric } 2398e8d8bef9SDimitry Andric 23990b57cec5SDimitry Andric void AttributeFuncs::mergeAttributesForInlining(Function &Caller, 24000b57cec5SDimitry Andric const Function &Callee) { 24010b57cec5SDimitry Andric mergeFnAttrs(Caller, Callee); 24020b57cec5SDimitry Andric } 2403e8d8bef9SDimitry Andric 2404e8d8bef9SDimitry Andric void AttributeFuncs::mergeAttributesForOutlining(Function &Base, 2405e8d8bef9SDimitry Andric const Function &ToMerge) { 2406e8d8bef9SDimitry Andric 2407e8d8bef9SDimitry Andric // We merge functions so that they meet the most general case. 2408e8d8bef9SDimitry Andric // For example, if the NoNansFPMathAttr is set in one function, but not in 2409e8d8bef9SDimitry Andric // the other, in the merged function we can say that the NoNansFPMathAttr 2410e8d8bef9SDimitry Andric // is not set. 2411e8d8bef9SDimitry Andric // However if we have the SpeculativeLoadHardeningAttr set true in one 2412e8d8bef9SDimitry Andric // function, but not the other, we make sure that the function retains 2413e8d8bef9SDimitry Andric // that aspect in the merged function. 2414e8d8bef9SDimitry Andric mergeFnAttrs(Base, ToMerge); 2415e8d8bef9SDimitry Andric } 241681ad6265SDimitry Andric 241781ad6265SDimitry Andric void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn, 241881ad6265SDimitry Andric uint64_t Width) { 241981ad6265SDimitry Andric Attribute Attr = Fn.getFnAttribute("min-legal-vector-width"); 242081ad6265SDimitry Andric if (Attr.isValid()) { 242181ad6265SDimitry Andric uint64_t OldWidth; 242281ad6265SDimitry Andric Attr.getValueAsString().getAsInteger(0, OldWidth); 242381ad6265SDimitry Andric if (Width > OldWidth) 242481ad6265SDimitry Andric Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width)); 242581ad6265SDimitry Andric } 242681ad6265SDimitry Andric } 2427