brintos

brintos / llvm-project-archived public Read only

0
0
Text · 88.8 KiB · fe6d3e5 Raw
2745 lines · cpp
1//===- Attributes.cpp - Implement AttributesList --------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// \file10// This file implements the Attribute, AttributeImpl, AttrBuilder,11// AttributeListImpl, and AttributeList classes.12//13//===----------------------------------------------------------------------===//14 15#include "llvm/IR/Attributes.h"16#include "AttributeImpl.h"17#include "LLVMContextImpl.h"18#include "llvm/ADT/ArrayRef.h"19#include "llvm/ADT/FoldingSet.h"20#include "llvm/ADT/STLExtras.h"21#include "llvm/ADT/SmallVector.h"22#include "llvm/ADT/StringExtras.h"23#include "llvm/ADT/StringRef.h"24#include "llvm/ADT/StringSwitch.h"25#include "llvm/Config/llvm-config.h"26#include "llvm/IR/AttributeMask.h"27#include "llvm/IR/ConstantRange.h"28#include "llvm/IR/ConstantRangeList.h"29#include "llvm/IR/Function.h"30#include "llvm/IR/LLVMContext.h"31#include "llvm/IR/Operator.h"32#include "llvm/IR/Type.h"33#include "llvm/Support/Compiler.h"34#include "llvm/Support/ErrorHandling.h"35#include "llvm/Support/ModRef.h"36#include "llvm/Support/raw_ostream.h"37#include <algorithm>38#include <cassert>39#include <cstddef>40#include <cstdint>41#include <limits>42#include <optional>43#include <string>44#include <tuple>45#include <utility>46 47using namespace llvm;48 49//===----------------------------------------------------------------------===//50// Attribute Construction Methods51//===----------------------------------------------------------------------===//52 53// allocsize has two integer arguments, but because they're both 32 bits, we can54// pack them into one 64-bit value, at the cost of making said value55// nonsensical.56//57// In order to do this, we need to reserve one value of the second (optional)58// allocsize argument to signify "not present."59static const unsigned AllocSizeNumElemsNotPresent = -1;60 61static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,62                                  const std::optional<unsigned> &NumElemsArg) {63  assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&64         "Attempting to pack a reserved value");65 66  return uint64_t(ElemSizeArg) << 32 |67         NumElemsArg.value_or(AllocSizeNumElemsNotPresent);68}69 70static std::pair<unsigned, std::optional<unsigned>>71unpackAllocSizeArgs(uint64_t Num) {72  unsigned NumElems = Num & std::numeric_limits<unsigned>::max();73  unsigned ElemSizeArg = Num >> 32;74 75  std::optional<unsigned> NumElemsArg;76  if (NumElems != AllocSizeNumElemsNotPresent)77    NumElemsArg = NumElems;78  return std::make_pair(ElemSizeArg, NumElemsArg);79}80 81static uint64_t packVScaleRangeArgs(unsigned MinValue,82                                    std::optional<unsigned> MaxValue) {83  return uint64_t(MinValue) << 32 | MaxValue.value_or(0);84}85 86static std::pair<unsigned, std::optional<unsigned>>87unpackVScaleRangeArgs(uint64_t Value) {88  unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();89  unsigned MinValue = Value >> 32;90 91  return std::make_pair(MinValue,92                        MaxValue > 0 ? MaxValue : std::optional<unsigned>());93}94 95Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,96                         uint64_t Val) {97  bool IsIntAttr = Attribute::isIntAttrKind(Kind);98  assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&99         "Not an enum or int attribute");100 101  LLVMContextImpl *pImpl = Context.pImpl;102  FoldingSetNodeID ID;103  ID.AddInteger(Kind);104  if (IsIntAttr)105    ID.AddInteger(Val);106  else107    assert(Val == 0 && "Value must be zero for enum attributes");108 109  void *InsertPoint;110  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);111 112  if (!PA) {113    // If we didn't find any existing attributes of the same shape then create a114    // new one and insert it.115    if (!IsIntAttr)116      PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);117    else118      PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);119    pImpl->AttrsSet.InsertNode(PA, InsertPoint);120  }121 122  // Return the Attribute that we found or created.123  return Attribute(PA);124}125 126Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {127  LLVMContextImpl *pImpl = Context.pImpl;128  FoldingSetNodeID ID;129  ID.AddString(Kind);130  if (!Val.empty()) ID.AddString(Val);131 132  void *InsertPoint;133  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);134 135  if (!PA) {136    // If we didn't find any existing attributes of the same shape then create a137    // new one and insert it.138    void *Mem =139        pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),140                              alignof(StringAttributeImpl));141    PA = new (Mem) StringAttributeImpl(Kind, Val);142    pImpl->AttrsSet.InsertNode(PA, InsertPoint);143  }144 145  // Return the Attribute that we found or created.146  return Attribute(PA);147}148 149Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,150                         Type *Ty) {151  assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");152  LLVMContextImpl *pImpl = Context.pImpl;153  FoldingSetNodeID ID;154  ID.AddInteger(Kind);155  ID.AddPointer(Ty);156 157  void *InsertPoint;158  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);159 160  if (!PA) {161    // If we didn't find any existing attributes of the same shape then create a162    // new one and insert it.163    PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);164    pImpl->AttrsSet.InsertNode(PA, InsertPoint);165  }166 167  // Return the Attribute that we found or created.168  return Attribute(PA);169}170 171Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,172                         const ConstantRange &CR) {173  assert(Attribute::isConstantRangeAttrKind(Kind) &&174         "Not a ConstantRange attribute");175  assert(!CR.isFullSet() && "ConstantRange attribute must not be full");176  LLVMContextImpl *pImpl = Context.pImpl;177  FoldingSetNodeID ID;178  ID.AddInteger(Kind);179  CR.getLower().Profile(ID);180  CR.getUpper().Profile(ID);181 182  void *InsertPoint;183  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);184 185  if (!PA) {186    // If we didn't find any existing attributes of the same shape then create a187    // new one and insert it.188    PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())189        ConstantRangeAttributeImpl(Kind, CR);190    pImpl->AttrsSet.InsertNode(PA, InsertPoint);191  }192 193  // Return the Attribute that we found or created.194  return Attribute(PA);195}196 197Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,198                         ArrayRef<ConstantRange> Val) {199  assert(Attribute::isConstantRangeListAttrKind(Kind) &&200         "Not a ConstantRangeList attribute");201  LLVMContextImpl *pImpl = Context.pImpl;202  FoldingSetNodeID ID;203  ID.AddInteger(Kind);204  ID.AddInteger(Val.size());205  for (auto &CR : Val) {206    CR.getLower().Profile(ID);207    CR.getUpper().Profile(ID);208  }209 210  void *InsertPoint;211  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);212 213  if (!PA) {214    // If we didn't find any existing attributes of the same shape then create a215    // new one and insert it.216    // ConstantRangeListAttributeImpl is a dynamically sized class and cannot217    // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for218    // allocation and record the allocated pointer in219    // `ConstantRangeListAttributes`. LLVMContext destructor will call the220    // destructor of the allocated pointer explicitly.221    void *Mem = pImpl->Alloc.Allocate(222        ConstantRangeListAttributeImpl::totalSizeToAlloc(Val),223        alignof(ConstantRangeListAttributeImpl));224    PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);225    pImpl->AttrsSet.InsertNode(PA, InsertPoint);226    pImpl->ConstantRangeListAttributes.push_back(227        reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));228  }229 230  // Return the Attribute that we found or created.231  return Attribute(PA);232}233 234Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {235  assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");236  return get(Context, Alignment, A.value());237}238 239Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {240  assert(A <= 0x100 && "Alignment too large.");241  return get(Context, StackAlignment, A.value());242}243 244Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,245                                                uint64_t Bytes) {246  assert(Bytes && "Bytes must be non-zero.");247  return get(Context, Dereferenceable, Bytes);248}249 250Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,251                                                       uint64_t Bytes) {252  assert(Bytes && "Bytes must be non-zero.");253  return get(Context, DereferenceableOrNull, Bytes);254}255 256Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {257  return get(Context, ByVal, Ty);258}259 260Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {261  return get(Context, StructRet, Ty);262}263 264Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {265  return get(Context, ByRef, Ty);266}267 268Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {269  return get(Context, Preallocated, Ty);270}271 272Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {273  return get(Context, InAlloca, Ty);274}275 276Attribute Attribute::getWithUWTableKind(LLVMContext &Context,277                                        UWTableKind Kind) {278  return get(Context, UWTable, uint64_t(Kind));279}280 281Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,282                                          MemoryEffects ME) {283  return get(Context, Memory, ME.toIntValue());284}285 286Attribute Attribute::getWithNoFPClass(LLVMContext &Context,287                                      FPClassTest ClassMask) {288  return get(Context, NoFPClass, ClassMask);289}290 291Attribute Attribute::getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI) {292  return get(Context, Captures, CI.toIntValue());293}294 295Attribute296Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,297                                const std::optional<unsigned> &NumElemsArg) {298  assert(!(ElemSizeArg == 0 && NumElemsArg == 0) &&299         "Invalid allocsize arguments -- given allocsize(0, 0)");300  return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));301}302 303Attribute Attribute::getWithAllocKind(LLVMContext &Context, AllocFnKind Kind) {304  return get(Context, AllocKind, static_cast<uint64_t>(Kind));305}306 307Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,308                                            unsigned MinValue,309                                            unsigned MaxValue) {310  return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));311}312 313Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {314  return StringSwitch<Attribute::AttrKind>(AttrName)315#define GET_ATTR_NAMES316#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \317  .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)318#include "llvm/IR/Attributes.inc"319      .Default(Attribute::None);320}321 322StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {323  switch (AttrKind) {324#define GET_ATTR_NAMES325#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \326  case Attribute::ENUM_NAME:                                                   \327    return #DISPLAY_NAME;328#include "llvm/IR/Attributes.inc"329  case Attribute::None:330    return "none";331  default:332    llvm_unreachable("invalid Kind");333  }334}335 336bool Attribute::isExistingAttribute(StringRef Name) {337  return StringSwitch<bool>(Name)338#define GET_ATTR_NAMES339#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)340#include "llvm/IR/Attributes.inc"341      .Default(false);342}343 344//===----------------------------------------------------------------------===//345// Attribute Accessor Methods346//===----------------------------------------------------------------------===//347 348bool Attribute::isEnumAttribute() const {349  return pImpl && pImpl->isEnumAttribute();350}351 352bool Attribute::isIntAttribute() const {353  return pImpl && pImpl->isIntAttribute();354}355 356bool Attribute::isStringAttribute() const {357  return pImpl && pImpl->isStringAttribute();358}359 360bool Attribute::isTypeAttribute() const {361  return pImpl && pImpl->isTypeAttribute();362}363 364bool Attribute::isConstantRangeAttribute() const {365  return pImpl && pImpl->isConstantRangeAttribute();366}367 368bool Attribute::isConstantRangeListAttribute() const {369  return pImpl && pImpl->isConstantRangeListAttribute();370}371 372Attribute::AttrKind Attribute::getKindAsEnum() const {373  if (!pImpl) return None;374  assert(hasKindAsEnum() &&375         "Invalid attribute type to get the kind as an enum!");376  return pImpl->getKindAsEnum();377}378 379uint64_t Attribute::getValueAsInt() const {380  if (!pImpl) return 0;381  assert(isIntAttribute() &&382         "Expected the attribute to be an integer attribute!");383  return pImpl->getValueAsInt();384}385 386bool Attribute::getValueAsBool() const {387  if (!pImpl) return false;388  assert(isStringAttribute() &&389         "Expected the attribute to be a string attribute!");390  return pImpl->getValueAsBool();391}392 393StringRef Attribute::getKindAsString() const {394  if (!pImpl) return {};395  assert(isStringAttribute() &&396         "Invalid attribute type to get the kind as a string!");397  return pImpl->getKindAsString();398}399 400StringRef Attribute::getValueAsString() const {401  if (!pImpl) return {};402  assert(isStringAttribute() &&403         "Invalid attribute type to get the value as a string!");404  return pImpl->getValueAsString();405}406 407Type *Attribute::getValueAsType() const {408  if (!pImpl) return {};409  assert(isTypeAttribute() &&410         "Invalid attribute type to get the value as a type!");411  return pImpl->getValueAsType();412}413 414const ConstantRange &Attribute::getValueAsConstantRange() const {415  assert(isConstantRangeAttribute() &&416         "Invalid attribute type to get the value as a ConstantRange!");417  return pImpl->getValueAsConstantRange();418}419 420ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const {421  assert(isConstantRangeListAttribute() &&422         "Invalid attribute type to get the value as a ConstantRangeList!");423  return pImpl->getValueAsConstantRangeList();424}425 426bool Attribute::hasAttribute(AttrKind Kind) const {427  return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);428}429 430bool Attribute::hasAttribute(StringRef Kind) const {431  if (!isStringAttribute()) return false;432  return pImpl && pImpl->hasAttribute(Kind);433}434 435MaybeAlign Attribute::getAlignment() const {436  assert(hasAttribute(Attribute::Alignment) &&437         "Trying to get alignment from non-alignment attribute!");438  return MaybeAlign(pImpl->getValueAsInt());439}440 441MaybeAlign Attribute::getStackAlignment() const {442  assert(hasAttribute(Attribute::StackAlignment) &&443         "Trying to get alignment from non-alignment attribute!");444  return MaybeAlign(pImpl->getValueAsInt());445}446 447uint64_t Attribute::getDereferenceableBytes() const {448  assert(hasAttribute(Attribute::Dereferenceable) &&449         "Trying to get dereferenceable bytes from "450         "non-dereferenceable attribute!");451  return pImpl->getValueAsInt();452}453 454uint64_t Attribute::getDereferenceableOrNullBytes() const {455  assert(hasAttribute(Attribute::DereferenceableOrNull) &&456         "Trying to get dereferenceable bytes from "457         "non-dereferenceable attribute!");458  return pImpl->getValueAsInt();459}460 461std::pair<unsigned, std::optional<unsigned>>462Attribute::getAllocSizeArgs() const {463  assert(hasAttribute(Attribute::AllocSize) &&464         "Trying to get allocsize args from non-allocsize attribute");465  return unpackAllocSizeArgs(pImpl->getValueAsInt());466}467 468unsigned Attribute::getVScaleRangeMin() const {469  assert(hasAttribute(Attribute::VScaleRange) &&470         "Trying to get vscale args from non-vscale attribute");471  return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;472}473 474std::optional<unsigned> Attribute::getVScaleRangeMax() const {475  assert(hasAttribute(Attribute::VScaleRange) &&476         "Trying to get vscale args from non-vscale attribute");477  return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;478}479 480UWTableKind Attribute::getUWTableKind() const {481  assert(hasAttribute(Attribute::UWTable) &&482         "Trying to get unwind table kind from non-uwtable attribute");483  return UWTableKind(pImpl->getValueAsInt());484}485 486AllocFnKind Attribute::getAllocKind() const {487  assert(hasAttribute(Attribute::AllocKind) &&488         "Trying to get allockind value from non-allockind attribute");489  return AllocFnKind(pImpl->getValueAsInt());490}491 492MemoryEffects Attribute::getMemoryEffects() const {493  assert(hasAttribute(Attribute::Memory) &&494         "Can only call getMemoryEffects() on memory attribute");495  return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());496}497 498CaptureInfo Attribute::getCaptureInfo() const {499  assert(hasAttribute(Attribute::Captures) &&500         "Can only call getCaptureInfo() on captures attribute");501  return CaptureInfo::createFromIntValue(pImpl->getValueAsInt());502}503 504FPClassTest Attribute::getNoFPClass() const {505  assert(hasAttribute(Attribute::NoFPClass) &&506         "Can only call getNoFPClass() on nofpclass attribute");507  return static_cast<FPClassTest>(pImpl->getValueAsInt());508}509 510const ConstantRange &Attribute::getRange() const {511  assert(hasAttribute(Attribute::Range) &&512         "Trying to get range args from non-range attribute");513  return pImpl->getValueAsConstantRange();514}515 516ArrayRef<ConstantRange> Attribute::getInitializes() const {517  assert(hasAttribute(Attribute::Initializes) &&518         "Trying to get initializes attr from non-ConstantRangeList attribute");519  return pImpl->getValueAsConstantRangeList();520}521 522static const char *getModRefStr(ModRefInfo MR) {523  switch (MR) {524  case ModRefInfo::NoModRef:525    return "none";526  case ModRefInfo::Ref:527    return "read";528  case ModRefInfo::Mod:529    return "write";530  case ModRefInfo::ModRef:531    return "readwrite";532  }533  llvm_unreachable("Invalid ModRefInfo");534}535 536std::string Attribute::getAsString(bool InAttrGrp) const {537  if (!pImpl) return {};538 539  if (isEnumAttribute())540    return getNameFromAttrKind(getKindAsEnum()).str();541 542  if (isTypeAttribute()) {543    std::string Result = getNameFromAttrKind(getKindAsEnum()).str();544    Result += '(';545    raw_string_ostream OS(Result);546    getValueAsType()->print(OS, false, true);547    OS.flush();548    Result += ')';549    return Result;550  }551 552  // FIXME: These should be output like this:553  //554  //   align=4555  //   alignstack=8556  //557  if (hasAttribute(Attribute::Alignment))558    return (InAttrGrp ? "align=" + Twine(getValueAsInt())559                      : "align " + Twine(getValueAsInt()))560        .str();561 562  auto AttrWithBytesToString = [&](const char *Name) {563    return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))564                      : Name + ("(" + Twine(getValueAsInt())) + ")")565        .str();566  };567 568  if (hasAttribute(Attribute::StackAlignment))569    return AttrWithBytesToString("alignstack");570 571  if (hasAttribute(Attribute::Dereferenceable))572    return AttrWithBytesToString("dereferenceable");573 574  if (hasAttribute(Attribute::DereferenceableOrNull))575    return AttrWithBytesToString("dereferenceable_or_null");576 577  if (hasAttribute(Attribute::AllocSize)) {578    unsigned ElemSize;579    std::optional<unsigned> NumElems;580    std::tie(ElemSize, NumElems) = getAllocSizeArgs();581 582    return (NumElems583                ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"584                : "allocsize(" + Twine(ElemSize) + ")")585        .str();586  }587 588  if (hasAttribute(Attribute::VScaleRange)) {589    unsigned MinValue = getVScaleRangeMin();590    std::optional<unsigned> MaxValue = getVScaleRangeMax();591    return ("vscale_range(" + Twine(MinValue) + "," +592            Twine(MaxValue.value_or(0)) + ")")593        .str();594  }595 596  if (hasAttribute(Attribute::UWTable)) {597    UWTableKind Kind = getUWTableKind();598    assert(Kind != UWTableKind::None && "uwtable attribute should not be none");599    return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";600  }601 602  if (hasAttribute(Attribute::AllocKind)) {603    AllocFnKind Kind = getAllocKind();604    SmallVector<StringRef> parts;605    if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)606      parts.push_back("alloc");607    if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)608      parts.push_back("realloc");609    if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)610      parts.push_back("free");611    if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)612      parts.push_back("uninitialized");613    if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)614      parts.push_back("zeroed");615    if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)616      parts.push_back("aligned");617    return ("allockind(\"" +618            Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")619        .str();620  }621 622  if (hasAttribute(Attribute::Memory)) {623    std::string Result;624    raw_string_ostream OS(Result);625    bool First = true;626    OS << "memory(";627 628    MemoryEffects ME = getMemoryEffects();629 630    // Print access kind for "other" as the default access kind. This way it631    // will apply to any new location kinds that get split out of "other".632    ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);633    if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {634      First = false;635      OS << getModRefStr(OtherMR);636    }637 638    for (auto Loc : MemoryEffects::locations()) {639      ModRefInfo MR = ME.getModRef(Loc);640      if (MR == OtherMR)641        continue;642 643      if (!First)644        OS << ", ";645      First = false;646 647      switch (Loc) {648      case IRMemLocation::ArgMem:649        OS << "argmem: ";650        break;651      case IRMemLocation::InaccessibleMem:652        OS << "inaccessiblemem: ";653        break;654      case IRMemLocation::ErrnoMem:655        OS << "errnomem: ";656        break;657      case IRMemLocation::Other:658        llvm_unreachable("This is represented as the default access kind");659      case IRMemLocation::TargetMem0:660        OS << "target_mem0: ";661        break;662      case IRMemLocation::TargetMem1:663        OS << "target_mem1: ";664        break;665      }666      OS << getModRefStr(MR);667    }668    OS << ")";669    OS.flush();670    return Result;671  }672 673  if (hasAttribute(Attribute::Captures)) {674    std::string Result;675    raw_string_ostream OS(Result);676    OS << getCaptureInfo();677    return Result;678  }679 680  if (hasAttribute(Attribute::NoFPClass)) {681    std::string Result = "nofpclass";682    raw_string_ostream OS(Result);683    OS << getNoFPClass();684    return Result;685  }686 687  if (hasAttribute(Attribute::Range)) {688    std::string Result;689    raw_string_ostream OS(Result);690    const ConstantRange &CR = getValueAsConstantRange();691    OS << "range(";692    OS << "i" << CR.getBitWidth() << " ";693    OS << CR.getLower() << ", " << CR.getUpper();694    OS << ")";695    OS.flush();696    return Result;697  }698 699  if (hasAttribute(Attribute::Initializes)) {700    std::string Result;701    raw_string_ostream OS(Result);702    ConstantRangeList CRL = getInitializes();703    OS << "initializes(";704    CRL.print(OS);705    OS << ")";706    OS.flush();707    return Result;708  }709 710  // Convert target-dependent attributes to strings of the form:711  //712  //   "kind"713  //   "kind" = "value"714  //715  if (isStringAttribute()) {716    std::string Result;717    {718      raw_string_ostream OS(Result);719      OS << '"' << getKindAsString() << '"';720 721      // Since some attribute strings contain special characters that cannot be722      // printable, those have to be escaped to make the attribute value723      // printable as is.  e.g. "\01__gnu_mcount_nc"724      const auto &AttrVal = pImpl->getValueAsString();725      if (!AttrVal.empty()) {726        OS << "=\"";727        printEscapedString(AttrVal, OS);728        OS << "\"";729      }730    }731    return Result;732  }733 734  llvm_unreachable("Unknown attribute");735}736 737bool Attribute::hasParentContext(LLVMContext &C) const {738  assert(isValid() && "invalid Attribute doesn't refer to any context");739  FoldingSetNodeID ID;740  pImpl->Profile(ID);741  void *Unused;742  return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;743}744 745int Attribute::cmpKind(Attribute A) const {746  if (!pImpl && !A.pImpl)747    return 0;748  if (!pImpl)749    return 1;750  if (!A.pImpl)751    return -1;752  return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);753}754 755bool Attribute::operator<(Attribute A) const {756  if (!pImpl && !A.pImpl) return false;757  if (!pImpl) return true;758  if (!A.pImpl) return false;759  return *pImpl < *A.pImpl;760}761 762void Attribute::Profile(FoldingSetNodeID &ID) const {763  ID.AddPointer(pImpl);764}765 766enum AttributeProperty {767  FnAttr = (1 << 0),768  ParamAttr = (1 << 1),769  RetAttr = (1 << 2),770  IntersectPreserve = (0 << 3),771  IntersectAnd = (1 << 3),772  IntersectMin = (2 << 3),773  IntersectCustom = (3 << 3),774  IntersectPropertyMask = (3 << 3),775};776 777#define GET_ATTR_PROP_TABLE778#include "llvm/IR/Attributes.inc"779 780static unsigned getAttributeProperties(Attribute::AttrKind Kind) {781  unsigned Index = Kind - 1;782  assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");783  return AttrPropTable[Index];784}785 786static bool hasAttributeProperty(Attribute::AttrKind Kind,787                                 AttributeProperty Prop) {788  return getAttributeProperties(Kind) & Prop;789}790 791bool Attribute::canUseAsFnAttr(AttrKind Kind) {792  return hasAttributeProperty(Kind, AttributeProperty::FnAttr);793}794 795bool Attribute::canUseAsParamAttr(AttrKind Kind) {796  return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);797}798 799bool Attribute::canUseAsRetAttr(AttrKind Kind) {800  return hasAttributeProperty(Kind, AttributeProperty::RetAttr);801}802 803static bool hasIntersectProperty(Attribute::AttrKind Kind,804                                 AttributeProperty Prop) {805  assert((Prop == AttributeProperty::IntersectPreserve ||806          Prop == AttributeProperty::IntersectAnd ||807          Prop == AttributeProperty::IntersectMin ||808          Prop == AttributeProperty::IntersectCustom) &&809         "Unknown intersect property");810  return (getAttributeProperties(Kind) &811          AttributeProperty::IntersectPropertyMask) == Prop;812}813 814bool Attribute::intersectMustPreserve(AttrKind Kind) {815  return hasIntersectProperty(Kind, AttributeProperty::IntersectPreserve);816}817bool Attribute::intersectWithAnd(AttrKind Kind) {818  return hasIntersectProperty(Kind, AttributeProperty::IntersectAnd);819}820bool Attribute::intersectWithMin(AttrKind Kind) {821  return hasIntersectProperty(Kind, AttributeProperty::IntersectMin);822}823bool Attribute::intersectWithCustom(AttrKind Kind) {824  return hasIntersectProperty(Kind, AttributeProperty::IntersectCustom);825}826 827//===----------------------------------------------------------------------===//828// AttributeImpl Definition829//===----------------------------------------------------------------------===//830 831bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {832  if (isStringAttribute()) return false;833  return getKindAsEnum() == A;834}835 836bool AttributeImpl::hasAttribute(StringRef Kind) const {837  if (!isStringAttribute()) return false;838  return getKindAsString() == Kind;839}840 841Attribute::AttrKind AttributeImpl::getKindAsEnum() const {842  assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||843         isConstantRangeAttribute() || isConstantRangeListAttribute());844  return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();845}846 847uint64_t AttributeImpl::getValueAsInt() const {848  assert(isIntAttribute());849  return static_cast<const IntAttributeImpl *>(this)->getValue();850}851 852bool AttributeImpl::getValueAsBool() const {853  assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");854  return getValueAsString() == "true";855}856 857StringRef AttributeImpl::getKindAsString() const {858  assert(isStringAttribute());859  return static_cast<const StringAttributeImpl *>(this)->getStringKind();860}861 862StringRef AttributeImpl::getValueAsString() const {863  assert(isStringAttribute());864  return static_cast<const StringAttributeImpl *>(this)->getStringValue();865}866 867Type *AttributeImpl::getValueAsType() const {868  assert(isTypeAttribute());869  return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();870}871 872const ConstantRange &AttributeImpl::getValueAsConstantRange() const {873  assert(isConstantRangeAttribute());874  return static_cast<const ConstantRangeAttributeImpl *>(this)875      ->getConstantRangeValue();876}877 878ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const {879  assert(isConstantRangeListAttribute());880  return static_cast<const ConstantRangeListAttributeImpl *>(this)881      ->getConstantRangeListValue();882}883 884int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {885  if (this == &AI)886    return 0;887 888  // This sorts the attributes with Attribute::AttrKinds coming first (sorted889  // relative to their enum value) and then strings.890  if (!isStringAttribute()) {891    if (AI.isStringAttribute())892      return -1;893 894    if (getKindAsEnum() != AI.getKindAsEnum())895      return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;896    else if (KindOnly)897      return 0;898 899    assert(!AI.isEnumAttribute() && "Non-unique attribute");900    assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");901    assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");902    assert(!AI.isConstantRangeListAttribute() &&903           "Unclear how to compare range list");904    // TODO: Is this actually needed?905    assert(AI.isIntAttribute() && "Only possibility left");906    if (getValueAsInt() < AI.getValueAsInt())907      return -1;908    return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;909  }910  if (!AI.isStringAttribute())911    return 1;912  if (KindOnly)913    return getKindAsString().compare(AI.getKindAsString());914  if (getKindAsString() == AI.getKindAsString())915    return getValueAsString().compare(AI.getValueAsString());916  return getKindAsString().compare(AI.getKindAsString());917}918 919bool AttributeImpl::operator<(const AttributeImpl &AI) const {920  return cmp(AI, /*KindOnly=*/false) < 0;921}922 923//===----------------------------------------------------------------------===//924// AttributeSet Definition925//===----------------------------------------------------------------------===//926 927AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {928  return AttributeSet(AttributeSetNode::get(C, B));929}930 931AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {932  return AttributeSet(AttributeSetNode::get(C, Attrs));933}934 935AttributeSet AttributeSet::addAttribute(LLVMContext &C,936                                        Attribute::AttrKind Kind) const {937  if (hasAttribute(Kind)) return *this;938  AttrBuilder B(C);939  B.addAttribute(Kind);940  return addAttributes(C, AttributeSet::get(C, B));941}942 943AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,944                                        StringRef Value) const {945  AttrBuilder B(C);946  B.addAttribute(Kind, Value);947  return addAttributes(C, AttributeSet::get(C, B));948}949 950AttributeSet AttributeSet::addAttributes(LLVMContext &C,951                                         const AttributeSet AS) const {952  if (!hasAttributes())953    return AS;954 955  if (!AS.hasAttributes())956    return *this;957 958  AttrBuilder B(C, *this);959  B.merge(AttrBuilder(C, AS));960  return get(C, B);961}962 963AttributeSet AttributeSet::addAttributes(LLVMContext &C,964                                         const AttrBuilder &B) const {965  if (!hasAttributes())966    return get(C, B);967 968  if (!B.hasAttributes())969    return *this;970 971  AttrBuilder Merged(C, *this);972  Merged.merge(B);973  return get(C, Merged);974}975 976AttributeSet AttributeSet::removeAttribute(LLVMContext &C,977                                             Attribute::AttrKind Kind) const {978  if (!hasAttribute(Kind)) return *this;979  AttrBuilder B(C, *this);980  B.removeAttribute(Kind);981  return get(C, B);982}983 984AttributeSet AttributeSet::removeAttribute(LLVMContext &C,985                                             StringRef Kind) const {986  if (!hasAttribute(Kind)) return *this;987  AttrBuilder B(C, *this);988  B.removeAttribute(Kind);989  return get(C, B);990}991 992AttributeSet AttributeSet::removeAttributes(LLVMContext &C,993                                            const AttributeMask &Attrs) const {994  AttrBuilder B(C, *this);995  // If there is nothing to remove, directly return the original set.996  if (!B.overlaps(Attrs))997    return *this;998 999  B.remove(Attrs);1000  return get(C, B);1001}1002 1003std::optional<AttributeSet>1004AttributeSet::intersectWith(LLVMContext &C, AttributeSet Other) const {1005  if (*this == Other)1006    return *this;1007 1008  AttrBuilder Intersected(C);1009  // Iterate over both attr sets at once.1010  auto ItBegin0 = begin();1011  auto ItEnd0 = end();1012  auto ItBegin1 = Other.begin();1013  auto ItEnd1 = Other.end();1014 1015  while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {1016    // Loop through all attributes in both this and Other in sorted order. If1017    // the attribute is only present in one of the sets, it will be set in1018    // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.1019    Attribute Attr0, Attr1;1020    if (ItBegin1 == ItEnd1)1021      Attr0 = *ItBegin0++;1022    else if (ItBegin0 == ItEnd0)1023      Attr0 = *ItBegin1++;1024    else {1025      int Cmp = ItBegin0->cmpKind(*ItBegin1);1026      if (Cmp == 0) {1027        Attr0 = *ItBegin0++;1028        Attr1 = *ItBegin1++;1029      } else if (Cmp < 0)1030        Attr0 = *ItBegin0++;1031      else1032        Attr0 = *ItBegin1++;1033    }1034    assert(Attr0.isValid() && "Iteration should always yield a valid attr");1035 1036    auto IntersectEq = [&]() {1037      if (!Attr1.isValid())1038        return false;1039      if (Attr0 != Attr1)1040        return false;1041      Intersected.addAttribute(Attr0);1042      return true;1043    };1044 1045    // Non-enum assume we must preserve. Handle early so we can unconditionally1046    // use Kind below.1047    if (!Attr0.hasKindAsEnum()) {1048      if (!IntersectEq())1049        return std::nullopt;1050      continue;1051    }1052 1053    Attribute::AttrKind Kind = Attr0.getKindAsEnum();1054    // If we don't have both attributes, then fail if the attribute is1055    // must-preserve or drop it otherwise.1056    if (!Attr1.isValid()) {1057      if (Attribute::intersectMustPreserve(Kind))1058        return std::nullopt;1059      continue;1060    }1061 1062    // We have both attributes so apply the intersection rule.1063    assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&1064           "Iterator picked up two different attributes in the same iteration");1065 1066    // Attribute we can intersect with "and"1067    if (Attribute::intersectWithAnd(Kind)) {1068      assert(Attribute::isEnumAttrKind(Kind) &&1069             "Invalid attr type of intersectAnd");1070      Intersected.addAttribute(Kind);1071      continue;1072    }1073 1074    // Attribute we can intersect with "min"1075    if (Attribute::intersectWithMin(Kind)) {1076      assert(Attribute::isIntAttrKind(Kind) &&1077             "Invalid attr type of intersectMin");1078      uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());1079      Intersected.addRawIntAttr(Kind, NewVal);1080      continue;1081    }1082    // Attribute we can intersect but need a custom rule for.1083    if (Attribute::intersectWithCustom(Kind)) {1084      switch (Kind) {1085      case Attribute::Alignment:1086        // If `byval` is present, alignment become must-preserve. This is1087        // handled below if we have `byval`.1088        Intersected.addAlignmentAttr(1089            std::min(Attr0.getAlignment().valueOrOne(),1090                     Attr1.getAlignment().valueOrOne()));1091        break;1092      case Attribute::Memory:1093        Intersected.addMemoryAttr(Attr0.getMemoryEffects() |1094                                  Attr1.getMemoryEffects());1095        break;1096      case Attribute::Captures:1097        Intersected.addCapturesAttr(Attr0.getCaptureInfo() |1098                                    Attr1.getCaptureInfo());1099        break;1100      case Attribute::NoFPClass:1101        Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &1102                                     Attr1.getNoFPClass());1103        break;1104      case Attribute::Range: {1105        ConstantRange Range0 = Attr0.getRange();1106        ConstantRange Range1 = Attr1.getRange();1107        ConstantRange NewRange = Range0.unionWith(Range1);1108        if (!NewRange.isFullSet())1109          Intersected.addRangeAttr(NewRange);1110      } break;1111      default:1112        llvm_unreachable("Unknown attribute with custom intersection rule");1113      }1114      continue;1115    }1116 1117    // Attributes with no intersection rule. Only intersect if they are equal.1118    // Otherwise fail.1119    if (!IntersectEq())1120      return std::nullopt;1121 1122    // Special handling of `byval`. `byval` essentially turns align attr into1123    // must-preserve1124    if (Kind == Attribute::ByVal &&1125        getAttribute(Attribute::Alignment) !=1126            Other.getAttribute(Attribute::Alignment))1127      return std::nullopt;1128  }1129 1130  return get(C, Intersected);1131}1132 1133unsigned AttributeSet::getNumAttributes() const {1134  return SetNode ? SetNode->getNumAttributes() : 0;1135}1136 1137bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {1138  return SetNode ? SetNode->hasAttribute(Kind) : false;1139}1140 1141bool AttributeSet::hasAttribute(StringRef Kind) const {1142  return SetNode ? SetNode->hasAttribute(Kind) : false;1143}1144 1145Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {1146  return SetNode ? SetNode->getAttribute(Kind) : Attribute();1147}1148 1149Attribute AttributeSet::getAttribute(StringRef Kind) const {1150  return SetNode ? SetNode->getAttribute(Kind) : Attribute();1151}1152 1153MaybeAlign AttributeSet::getAlignment() const {1154  return SetNode ? SetNode->getAlignment() : std::nullopt;1155}1156 1157MaybeAlign AttributeSet::getStackAlignment() const {1158  return SetNode ? SetNode->getStackAlignment() : std::nullopt;1159}1160 1161uint64_t AttributeSet::getDereferenceableBytes() const {1162  return SetNode ? SetNode->getDereferenceableBytes() : 0;1163}1164 1165uint64_t AttributeSet::getDereferenceableOrNullBytes() const {1166  return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;1167}1168 1169Type *AttributeSet::getByRefType() const {1170  return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;1171}1172 1173Type *AttributeSet::getByValType() const {1174  return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;1175}1176 1177Type *AttributeSet::getStructRetType() const {1178  return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;1179}1180 1181Type *AttributeSet::getPreallocatedType() const {1182  return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;1183}1184 1185Type *AttributeSet::getInAllocaType() const {1186  return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;1187}1188 1189Type *AttributeSet::getElementType() const {1190  return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;1191}1192 1193std::optional<std::pair<unsigned, std::optional<unsigned>>>1194AttributeSet::getAllocSizeArgs() const {1195  if (SetNode)1196    return SetNode->getAllocSizeArgs();1197  return std::nullopt;1198}1199 1200unsigned AttributeSet::getVScaleRangeMin() const {1201  return SetNode ? SetNode->getVScaleRangeMin() : 1;1202}1203 1204std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {1205  return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;1206}1207 1208UWTableKind AttributeSet::getUWTableKind() const {1209  return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;1210}1211 1212AllocFnKind AttributeSet::getAllocKind() const {1213  return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;1214}1215 1216MemoryEffects AttributeSet::getMemoryEffects() const {1217  return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();1218}1219 1220CaptureInfo AttributeSet::getCaptureInfo() const {1221  return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();1222}1223 1224FPClassTest AttributeSet::getNoFPClass() const {1225  return SetNode ? SetNode->getNoFPClass() : fcNone;1226}1227 1228std::string AttributeSet::getAsString(bool InAttrGrp) const {1229  return SetNode ? SetNode->getAsString(InAttrGrp) : "";1230}1231 1232bool AttributeSet::hasParentContext(LLVMContext &C) const {1233  assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");1234  FoldingSetNodeID ID;1235  SetNode->Profile(ID);1236  void *Unused;1237  return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;1238}1239 1240AttributeSet::iterator AttributeSet::begin() const {1241  return SetNode ? SetNode->begin() : nullptr;1242}1243 1244AttributeSet::iterator AttributeSet::end() const {1245  return SetNode ? SetNode->end() : nullptr;1246}1247 1248#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)1249LLVM_DUMP_METHOD void AttributeSet::dump() const {1250  dbgs() << "AS =\n";1251    dbgs() << "  { ";1252    dbgs() << getAsString(true) << " }\n";1253}1254#endif1255 1256//===----------------------------------------------------------------------===//1257// AttributeSetNode Definition1258//===----------------------------------------------------------------------===//1259 1260AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)1261    : NumAttrs(Attrs.size()) {1262  // There's memory after the node where we can store the entries in.1263  llvm::copy(Attrs, getTrailingObjects());1264 1265  for (const auto &I : *this) {1266    if (I.isStringAttribute())1267      StringAttrs.insert({ I.getKindAsString(), I });1268    else1269      AvailableAttrs.addAttribute(I.getKindAsEnum());1270  }1271}1272 1273AttributeSetNode *AttributeSetNode::get(LLVMContext &C,1274                                        ArrayRef<Attribute> Attrs) {1275  SmallVector<Attribute, 8> SortedAttrs(Attrs);1276  llvm::sort(SortedAttrs);1277  return getSorted(C, SortedAttrs);1278}1279 1280AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,1281                                              ArrayRef<Attribute> SortedAttrs) {1282  if (SortedAttrs.empty())1283    return nullptr;1284 1285  // Build a key to look up the existing attributes.1286  LLVMContextImpl *pImpl = C.pImpl;1287  FoldingSetNodeID ID;1288 1289  assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");1290  for (const auto &Attr : SortedAttrs)1291    Attr.Profile(ID);1292 1293  void *InsertPoint;1294  AttributeSetNode *PA =1295    pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);1296 1297  // If we didn't find any existing attributes of the same shape then create a1298  // new one and insert it.1299  if (!PA) {1300    // Coallocate entries after the AttributeSetNode itself.1301    void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));1302    PA = new (Mem) AttributeSetNode(SortedAttrs);1303    pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);1304  }1305 1306  // Return the AttributeSetNode that we found or created.1307  return PA;1308}1309 1310AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {1311  return getSorted(C, B.attrs());1312}1313 1314bool AttributeSetNode::hasAttribute(StringRef Kind) const {1315  return StringAttrs.count(Kind);1316}1317 1318std::optional<Attribute>1319AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {1320  // Do a quick presence check.1321  if (!hasAttribute(Kind))1322    return std::nullopt;1323 1324  // Attributes in a set are sorted by enum value, followed by string1325  // attributes. Binary search the one we want.1326  const Attribute *I =1327      std::lower_bound(begin(), end() - StringAttrs.size(), Kind,1328                       [](Attribute A, Attribute::AttrKind Kind) {1329                         return A.getKindAsEnum() < Kind;1330                       });1331  assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");1332  return *I;1333}1334 1335Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {1336  if (auto A = findEnumAttribute(Kind))1337    return *A;1338  return {};1339}1340 1341Attribute AttributeSetNode::getAttribute(StringRef Kind) const {1342  return StringAttrs.lookup(Kind);1343}1344 1345MaybeAlign AttributeSetNode::getAlignment() const {1346  if (auto A = findEnumAttribute(Attribute::Alignment))1347    return A->getAlignment();1348  return std::nullopt;1349}1350 1351MaybeAlign AttributeSetNode::getStackAlignment() const {1352  if (auto A = findEnumAttribute(Attribute::StackAlignment))1353    return A->getStackAlignment();1354  return std::nullopt;1355}1356 1357Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {1358  if (auto A = findEnumAttribute(Kind))1359    return A->getValueAsType();1360  return nullptr;1361}1362 1363uint64_t AttributeSetNode::getDereferenceableBytes() const {1364  if (auto A = findEnumAttribute(Attribute::Dereferenceable))1365    return A->getDereferenceableBytes();1366  return 0;1367}1368 1369uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {1370  if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))1371    return A->getDereferenceableOrNullBytes();1372  return 0;1373}1374 1375std::optional<std::pair<unsigned, std::optional<unsigned>>>1376AttributeSetNode::getAllocSizeArgs() const {1377  if (auto A = findEnumAttribute(Attribute::AllocSize))1378    return A->getAllocSizeArgs();1379  return std::nullopt;1380}1381 1382unsigned AttributeSetNode::getVScaleRangeMin() const {1383  if (auto A = findEnumAttribute(Attribute::VScaleRange))1384    return A->getVScaleRangeMin();1385  return 1;1386}1387 1388std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {1389  if (auto A = findEnumAttribute(Attribute::VScaleRange))1390    return A->getVScaleRangeMax();1391  return std::nullopt;1392}1393 1394UWTableKind AttributeSetNode::getUWTableKind() const {1395  if (auto A = findEnumAttribute(Attribute::UWTable))1396    return A->getUWTableKind();1397  return UWTableKind::None;1398}1399 1400AllocFnKind AttributeSetNode::getAllocKind() const {1401  if (auto A = findEnumAttribute(Attribute::AllocKind))1402    return A->getAllocKind();1403  return AllocFnKind::Unknown;1404}1405 1406MemoryEffects AttributeSetNode::getMemoryEffects() const {1407  if (auto A = findEnumAttribute(Attribute::Memory))1408    return A->getMemoryEffects();1409  return MemoryEffects::unknown();1410}1411 1412CaptureInfo AttributeSetNode::getCaptureInfo() const {1413  if (auto A = findEnumAttribute(Attribute::Captures))1414    return A->getCaptureInfo();1415  return CaptureInfo::all();1416}1417 1418FPClassTest AttributeSetNode::getNoFPClass() const {1419  if (auto A = findEnumAttribute(Attribute::NoFPClass))1420    return A->getNoFPClass();1421  return fcNone;1422}1423 1424std::string AttributeSetNode::getAsString(bool InAttrGrp) const {1425  std::string Str;1426  for (iterator I = begin(), E = end(); I != E; ++I) {1427    if (I != begin())1428      Str += ' ';1429    Str += I->getAsString(InAttrGrp);1430  }1431  return Str;1432}1433 1434//===----------------------------------------------------------------------===//1435// AttributeListImpl Definition1436//===----------------------------------------------------------------------===//1437 1438/// Map from AttributeList index to the internal array index. Adding one happens1439/// to work, because -1 wraps around to 0.1440static unsigned attrIdxToArrayIdx(unsigned Index) {1441  return Index + 1;1442}1443 1444AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)1445    : NumAttrSets(Sets.size()) {1446  assert(!Sets.empty() && "pointless AttributeListImpl");1447 1448  // There's memory after the node where we can store the entries in.1449  llvm::copy(Sets, getTrailingObjects());1450 1451  // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs1452  // summary bitsets.1453  for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])1454    if (!I.isStringAttribute())1455      AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());1456 1457  for (const auto &Set : Sets)1458    for (const auto &I : Set)1459      if (!I.isStringAttribute())1460        AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());1461}1462 1463void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {1464  Profile(ID, ArrayRef(begin(), end()));1465}1466 1467void AttributeListImpl::Profile(FoldingSetNodeID &ID,1468                                ArrayRef<AttributeSet> Sets) {1469  for (const auto &Set : Sets)1470    ID.AddPointer(Set.SetNode);1471}1472 1473bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,1474                                        unsigned *Index) const {1475  if (!AvailableSomewhereAttrs.hasAttribute(Kind))1476    return false;1477 1478  if (Index) {1479    for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {1480      if (begin()[I].hasAttribute(Kind)) {1481        *Index = I - 1;1482        break;1483      }1484    }1485  }1486 1487  return true;1488}1489 1490 1491#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)1492LLVM_DUMP_METHOD void AttributeListImpl::dump() const {1493  AttributeList(const_cast<AttributeListImpl *>(this)).dump();1494}1495#endif1496 1497//===----------------------------------------------------------------------===//1498// AttributeList Construction and Mutation Methods1499//===----------------------------------------------------------------------===//1500 1501AttributeList AttributeList::getImpl(LLVMContext &C,1502                                     ArrayRef<AttributeSet> AttrSets) {1503  assert(!AttrSets.empty() && "pointless AttributeListImpl");1504 1505  LLVMContextImpl *pImpl = C.pImpl;1506  FoldingSetNodeID ID;1507  AttributeListImpl::Profile(ID, AttrSets);1508 1509  void *InsertPoint;1510  AttributeListImpl *PA =1511      pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);1512 1513  // If we didn't find any existing attributes of the same shape then1514  // create a new one and insert it.1515  if (!PA) {1516    // Coallocate entries after the AttributeListImpl itself.1517    void *Mem = pImpl->Alloc.Allocate(1518        AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),1519        alignof(AttributeListImpl));1520    PA = new (Mem) AttributeListImpl(AttrSets);1521    pImpl->AttrsLists.InsertNode(PA, InsertPoint);1522  }1523 1524  // Return the AttributesList that we found or created.1525  return AttributeList(PA);1526}1527 1528AttributeList1529AttributeList::get(LLVMContext &C,1530                   ArrayRef<std::pair<unsigned, Attribute>> Attrs) {1531  // If there are no attributes then return a null AttributesList pointer.1532  if (Attrs.empty())1533    return {};1534 1535  assert(llvm::is_sorted(Attrs, llvm::less_first()) &&1536         "Misordered Attributes list!");1537  assert(llvm::all_of(Attrs,1538                      [](const std::pair<unsigned, Attribute> &Pair) {1539                        return Pair.second.isValid();1540                      }) &&1541         "Pointless attribute!");1542 1543  // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes1544  // list.1545  SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;1546  for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),1547         E = Attrs.end(); I != E; ) {1548    unsigned Index = I->first;1549    SmallVector<Attribute, 4> AttrVec;1550    while (I != E && I->first == Index) {1551      AttrVec.push_back(I->second);1552      ++I;1553    }1554 1555    AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));1556  }1557 1558  return get(C, AttrPairVec);1559}1560 1561AttributeList1562AttributeList::get(LLVMContext &C,1563                   ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {1564  // If there are no attributes then return a null AttributesList pointer.1565  if (Attrs.empty())1566    return {};1567 1568  assert(llvm::is_sorted(Attrs, llvm::less_first()) &&1569         "Misordered Attributes list!");1570  assert(llvm::none_of(Attrs,1571                       [](const std::pair<unsigned, AttributeSet> &Pair) {1572                         return !Pair.second.hasAttributes();1573                       }) &&1574         "Pointless attribute!");1575 1576  unsigned MaxIndex = Attrs.back().first;1577  // If the MaxIndex is FunctionIndex and there are other indices in front1578  // of it, we need to use the largest of those to get the right size.1579  if (MaxIndex == FunctionIndex && Attrs.size() > 1)1580    MaxIndex = Attrs[Attrs.size() - 2].first;1581 1582  SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);1583  for (const auto &Pair : Attrs)1584    AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;1585 1586  return getImpl(C, AttrVec);1587}1588 1589AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,1590                                 AttributeSet RetAttrs,1591                                 ArrayRef<AttributeSet> ArgAttrs) {1592  // Scan from the end to find the last argument with attributes.  Most1593  // arguments don't have attributes, so it's nice if we can have fewer unique1594  // AttributeListImpls by dropping empty attribute sets at the end of the list.1595  unsigned NumSets = 0;1596  for (size_t I = ArgAttrs.size(); I != 0; --I) {1597    if (ArgAttrs[I - 1].hasAttributes()) {1598      NumSets = I + 2;1599      break;1600    }1601  }1602  if (NumSets == 0) {1603    // Check function and return attributes if we didn't have argument1604    // attributes.1605    if (RetAttrs.hasAttributes())1606      NumSets = 2;1607    else if (FnAttrs.hasAttributes())1608      NumSets = 1;1609  }1610 1611  // If all attribute sets were empty, we can use the empty attribute list.1612  if (NumSets == 0)1613    return {};1614 1615  SmallVector<AttributeSet, 8> AttrSets;1616  AttrSets.reserve(NumSets);1617  // If we have any attributes, we always have function attributes.1618  AttrSets.push_back(FnAttrs);1619  if (NumSets > 1)1620    AttrSets.push_back(RetAttrs);1621  if (NumSets > 2) {1622    // Drop the empty argument attribute sets at the end.1623    ArgAttrs = ArgAttrs.take_front(NumSets - 2);1624    llvm::append_range(AttrSets, ArgAttrs);1625  }1626 1627  return getImpl(C, AttrSets);1628}1629 1630AttributeList AttributeList::get(LLVMContext &C, unsigned Index,1631                                 AttributeSet Attrs) {1632  if (!Attrs.hasAttributes())1633    return {};1634  Index = attrIdxToArrayIdx(Index);1635  SmallVector<AttributeSet, 8> AttrSets(Index + 1);1636  AttrSets[Index] = Attrs;1637  return getImpl(C, AttrSets);1638}1639 1640AttributeList AttributeList::get(LLVMContext &C, unsigned Index,1641                                 const AttrBuilder &B) {1642  return get(C, Index, AttributeSet::get(C, B));1643}1644 1645AttributeList AttributeList::get(LLVMContext &C, unsigned Index,1646                                 ArrayRef<Attribute::AttrKind> Kinds) {1647  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;1648  for (const auto K : Kinds)1649    Attrs.emplace_back(Index, Attribute::get(C, K));1650  return get(C, Attrs);1651}1652 1653AttributeList AttributeList::get(LLVMContext &C, unsigned Index,1654                                 ArrayRef<Attribute::AttrKind> Kinds,1655                                 ArrayRef<uint64_t> Values) {1656  assert(Kinds.size() == Values.size() && "Mismatched attribute values.");1657  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;1658  auto VI = Values.begin();1659  for (const auto K : Kinds)1660    Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));1661  return get(C, Attrs);1662}1663 1664AttributeList AttributeList::get(LLVMContext &C, unsigned Index,1665                                 ArrayRef<StringRef> Kinds) {1666  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;1667  for (const auto &K : Kinds)1668    Attrs.emplace_back(Index, Attribute::get(C, K));1669  return get(C, Attrs);1670}1671 1672AttributeList AttributeList::get(LLVMContext &C,1673                                 ArrayRef<AttributeList> Attrs) {1674  if (Attrs.empty())1675    return {};1676  if (Attrs.size() == 1)1677    return Attrs[0];1678 1679  unsigned MaxSize = 0;1680  for (const auto &List : Attrs)1681    MaxSize = std::max(MaxSize, List.getNumAttrSets());1682 1683  // If every list was empty, there is no point in merging the lists.1684  if (MaxSize == 0)1685    return {};1686 1687  SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);1688  for (unsigned I = 0; I < MaxSize; ++I) {1689    AttrBuilder CurBuilder(C);1690    for (const auto &List : Attrs)1691      CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));1692    NewAttrSets[I] = AttributeSet::get(C, CurBuilder);1693  }1694 1695  return getImpl(C, NewAttrSets);1696}1697 1698AttributeList1699AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,1700                                   Attribute::AttrKind Kind) const {1701  AttributeSet Attrs = getAttributes(Index);1702  if (Attrs.hasAttribute(Kind))1703    return *this;1704  // TODO: Insert at correct position and avoid sort.1705  SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());1706  NewAttrs.push_back(Attribute::get(C, Kind));1707  return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));1708}1709 1710AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,1711                                                 StringRef Kind,1712                                                 StringRef Value) const {1713  AttrBuilder B(C);1714  B.addAttribute(Kind, Value);1715  return addAttributesAtIndex(C, Index, B);1716}1717 1718AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,1719                                                 Attribute A) const {1720  AttrBuilder B(C);1721  B.addAttribute(A);1722  return addAttributesAtIndex(C, Index, B);1723}1724 1725AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,1726                                                  unsigned Index,1727                                                  AttributeSet Attrs) const {1728  Index = attrIdxToArrayIdx(Index);1729  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());1730  if (Index >= AttrSets.size())1731    AttrSets.resize(Index + 1);1732  AttrSets[Index] = Attrs;1733 1734  // Remove trailing empty attribute sets.1735  while (!AttrSets.empty() && !AttrSets.back().hasAttributes())1736    AttrSets.pop_back();1737  if (AttrSets.empty())1738    return {};1739  return AttributeList::getImpl(C, AttrSets);1740}1741 1742AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,1743                                                  unsigned Index,1744                                                  const AttrBuilder &B) const {1745  if (!B.hasAttributes())1746    return *this;1747 1748  if (!pImpl)1749    return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});1750 1751  AttrBuilder Merged(C, getAttributes(Index));1752  Merged.merge(B);1753  return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));1754}1755 1756AttributeList AttributeList::addParamAttribute(LLVMContext &C,1757                                               ArrayRef<unsigned> ArgNos,1758                                               Attribute A) const {1759  assert(llvm::is_sorted(ArgNos));1760 1761  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());1762  unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);1763  if (MaxIndex >= AttrSets.size())1764    AttrSets.resize(MaxIndex + 1);1765 1766  for (unsigned ArgNo : ArgNos) {1767    unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);1768    AttrBuilder B(C, AttrSets[Index]);1769    B.addAttribute(A);1770    AttrSets[Index] = AttributeSet::get(C, B);1771  }1772 1773  return getImpl(C, AttrSets);1774}1775 1776AttributeList1777AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,1778                                      Attribute::AttrKind Kind) const {1779  AttributeSet Attrs = getAttributes(Index);1780  AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);1781  if (Attrs == NewAttrs)1782    return *this;1783  return setAttributesAtIndex(C, Index, NewAttrs);1784}1785 1786AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,1787                                                    unsigned Index,1788                                                    StringRef Kind) const {1789  AttributeSet Attrs = getAttributes(Index);1790  AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);1791  if (Attrs == NewAttrs)1792    return *this;1793  return setAttributesAtIndex(C, Index, NewAttrs);1794}1795 1796AttributeList AttributeList::removeAttributesAtIndex(1797    LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {1798  AttributeSet Attrs = getAttributes(Index);1799  AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);1800  // If nothing was removed, return the original list.1801  if (Attrs == NewAttrs)1802    return *this;1803  return setAttributesAtIndex(C, Index, NewAttrs);1804}1805 1806AttributeList1807AttributeList::removeAttributesAtIndex(LLVMContext &C,1808                                       unsigned WithoutIndex) const {1809  if (!pImpl)1810    return {};1811  if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())1812    return *this;1813  return setAttributesAtIndex(C, WithoutIndex, AttributeSet());1814}1815 1816AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,1817                                                       uint64_t Bytes) const {1818  AttrBuilder B(C);1819  B.addDereferenceableAttr(Bytes);1820  return addRetAttributes(C, B);1821}1822 1823AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,1824                                                         unsigned Index,1825                                                         uint64_t Bytes) const {1826  AttrBuilder B(C);1827  B.addDereferenceableAttr(Bytes);1828  return addParamAttributes(C, Index, B);1829}1830 1831AttributeList1832AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,1833                                                 uint64_t Bytes) const {1834  AttrBuilder B(C);1835  B.addDereferenceableOrNullAttr(Bytes);1836  return addParamAttributes(C, Index, B);1837}1838 1839AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,1840                                             const ConstantRange &CR) const {1841  AttrBuilder B(C);1842  B.addRangeAttr(CR);1843  return addRetAttributes(C, B);1844}1845 1846AttributeList AttributeList::addAllocSizeParamAttr(1847    LLVMContext &C, unsigned Index, unsigned ElemSizeArg,1848    const std::optional<unsigned> &NumElemsArg) const {1849  AttrBuilder B(C);1850  B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);1851  return addParamAttributes(C, Index, B);1852}1853 1854std::optional<AttributeList>1855AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {1856  // Trivial case, the two lists are equal.1857  if (*this == Other)1858    return *this;1859 1860  SmallVector<std::pair<unsigned, AttributeSet>> IntersectedAttrs;1861  auto IndexIt =1862      index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));1863  for (unsigned Idx : IndexIt) {1864    auto IntersectedAS =1865        getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));1866    // If any index fails to intersect, fail.1867    if (!IntersectedAS)1868      return std::nullopt;1869    if (!IntersectedAS->hasAttributes())1870      continue;1871    IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));1872  }1873 1874  llvm::sort(IntersectedAttrs, llvm::less_first());1875  return AttributeList::get(C, IntersectedAttrs);1876}1877 1878//===----------------------------------------------------------------------===//1879// AttributeList Accessor Methods1880//===----------------------------------------------------------------------===//1881 1882AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {1883  return getAttributes(ArgNo + FirstArgIndex);1884}1885 1886AttributeSet AttributeList::getRetAttrs() const {1887  return getAttributes(ReturnIndex);1888}1889 1890AttributeSet AttributeList::getFnAttrs() const {1891  return getAttributes(FunctionIndex);1892}1893 1894bool AttributeList::hasAttributeAtIndex(unsigned Index,1895                                        Attribute::AttrKind Kind) const {1896  return getAttributes(Index).hasAttribute(Kind);1897}1898 1899bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {1900  return getAttributes(Index).hasAttribute(Kind);1901}1902 1903bool AttributeList::hasAttributesAtIndex(unsigned Index) const {1904  return getAttributes(Index).hasAttributes();1905}1906 1907bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {1908  return pImpl && pImpl->hasFnAttribute(Kind);1909}1910 1911bool AttributeList::hasFnAttr(StringRef Kind) const {1912  return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);1913}1914 1915bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,1916                                     unsigned *Index) const {1917  return pImpl && pImpl->hasAttrSomewhere(Attr, Index);1918}1919 1920Attribute AttributeList::getAttributeAtIndex(unsigned Index,1921                                             Attribute::AttrKind Kind) const {1922  return getAttributes(Index).getAttribute(Kind);1923}1924 1925Attribute AttributeList::getAttributeAtIndex(unsigned Index,1926                                             StringRef Kind) const {1927  return getAttributes(Index).getAttribute(Kind);1928}1929 1930MaybeAlign AttributeList::getRetAlignment() const {1931  return getAttributes(ReturnIndex).getAlignment();1932}1933 1934MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {1935  return getAttributes(ArgNo + FirstArgIndex).getAlignment();1936}1937 1938MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {1939  return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();1940}1941 1942Type *AttributeList::getParamByValType(unsigned Index) const {1943  return getAttributes(Index+FirstArgIndex).getByValType();1944}1945 1946Type *AttributeList::getParamStructRetType(unsigned Index) const {1947  return getAttributes(Index + FirstArgIndex).getStructRetType();1948}1949 1950Type *AttributeList::getParamByRefType(unsigned Index) const {1951  return getAttributes(Index + FirstArgIndex).getByRefType();1952}1953 1954Type *AttributeList::getParamPreallocatedType(unsigned Index) const {1955  return getAttributes(Index + FirstArgIndex).getPreallocatedType();1956}1957 1958Type *AttributeList::getParamInAllocaType(unsigned Index) const {1959  return getAttributes(Index + FirstArgIndex).getInAllocaType();1960}1961 1962Type *AttributeList::getParamElementType(unsigned Index) const {1963  return getAttributes(Index + FirstArgIndex).getElementType();1964}1965 1966MaybeAlign AttributeList::getFnStackAlignment() const {1967  return getFnAttrs().getStackAlignment();1968}1969 1970MaybeAlign AttributeList::getRetStackAlignment() const {1971  return getRetAttrs().getStackAlignment();1972}1973 1974uint64_t AttributeList::getRetDereferenceableBytes() const {1975  return getRetAttrs().getDereferenceableBytes();1976}1977 1978uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {1979  return getParamAttrs(Index).getDereferenceableBytes();1980}1981 1982uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {1983  return getRetAttrs().getDereferenceableOrNullBytes();1984}1985 1986uint64_t1987AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {1988  return getParamAttrs(Index).getDereferenceableOrNullBytes();1989}1990 1991std::optional<ConstantRange>1992AttributeList::getParamRange(unsigned ArgNo) const {1993  auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);1994  if (RangeAttr.isValid())1995    return RangeAttr.getRange();1996  return std::nullopt;1997}1998 1999FPClassTest AttributeList::getRetNoFPClass() const {2000  return getRetAttrs().getNoFPClass();2001}2002 2003FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {2004  return getParamAttrs(Index).getNoFPClass();2005}2006 2007UWTableKind AttributeList::getUWTableKind() const {2008  return getFnAttrs().getUWTableKind();2009}2010 2011AllocFnKind AttributeList::getAllocKind() const {2012  return getFnAttrs().getAllocKind();2013}2014 2015MemoryEffects AttributeList::getMemoryEffects() const {2016  return getFnAttrs().getMemoryEffects();2017}2018 2019std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {2020  return getAttributes(Index).getAsString(InAttrGrp);2021}2022 2023AttributeSet AttributeList::getAttributes(unsigned Index) const {2024  Index = attrIdxToArrayIdx(Index);2025  if (!pImpl || Index >= getNumAttrSets())2026    return {};2027  return pImpl->begin()[Index];2028}2029 2030bool AttributeList::hasParentContext(LLVMContext &C) const {2031  assert(!isEmpty() && "an empty attribute list has no parent context");2032  FoldingSetNodeID ID;2033  pImpl->Profile(ID);2034  void *Unused;2035  return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;2036}2037 2038AttributeList::iterator AttributeList::begin() const {2039  return pImpl ? pImpl->begin() : nullptr;2040}2041 2042AttributeList::iterator AttributeList::end() const {2043  return pImpl ? pImpl->end() : nullptr;2044}2045 2046//===----------------------------------------------------------------------===//2047// AttributeList Introspection Methods2048//===----------------------------------------------------------------------===//2049 2050unsigned AttributeList::getNumAttrSets() const {2051  return pImpl ? pImpl->NumAttrSets : 0;2052}2053 2054void AttributeList::print(raw_ostream &O) const {2055  O << "AttributeList[\n";2056 2057  for (unsigned i : indexes()) {2058    if (!getAttributes(i).hasAttributes())2059      continue;2060    O << "  { ";2061    switch (i) {2062    case AttrIndex::ReturnIndex:2063      O << "return";2064      break;2065    case AttrIndex::FunctionIndex:2066      O << "function";2067      break;2068    default:2069      O << "arg(" << i - AttrIndex::FirstArgIndex << ")";2070    }2071    O << " => " << getAsString(i) << " }\n";2072  }2073 2074  O << "]\n";2075}2076 2077#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)2078LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }2079#endif2080 2081//===----------------------------------------------------------------------===//2082// AttrBuilder Method Implementations2083//===----------------------------------------------------------------------===//2084 2085AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {2086  append_range(Attrs, AS);2087  assert(is_sorted(Attrs) && "AttributeSet should be sorted");2088}2089 2090void AttrBuilder::clear() { Attrs.clear(); }2091 2092/// Attribute comparator that only compares attribute keys. Enum attributes are2093/// sorted before string attributes.2094struct AttributeComparator {2095  bool operator()(Attribute A0, Attribute A1) const {2096    bool A0IsString = A0.isStringAttribute();2097    bool A1IsString = A1.isStringAttribute();2098    if (A0IsString) {2099      if (A1IsString)2100        return A0.getKindAsString() < A1.getKindAsString();2101      else2102        return false;2103    }2104    if (A1IsString)2105      return true;2106    return A0.getKindAsEnum() < A1.getKindAsEnum();2107  }2108  bool operator()(Attribute A0, Attribute::AttrKind Kind) const {2109    if (A0.isStringAttribute())2110      return false;2111    return A0.getKindAsEnum() < Kind;2112  }2113  bool operator()(Attribute A0, StringRef Kind) const {2114    if (A0.isStringAttribute())2115      return A0.getKindAsString() < Kind;2116    return true;2117  }2118};2119 2120template <typename K>2121static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,2122                             Attribute Attr) {2123  auto It = lower_bound(Attrs, Kind, AttributeComparator());2124  if (It != Attrs.end() && It->hasAttribute(Kind))2125    std::swap(*It, Attr);2126  else2127    Attrs.insert(It, Attr);2128}2129 2130AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {2131  if (Attr.isStringAttribute())2132    addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);2133  else2134    addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);2135  return *this;2136}2137 2138AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {2139  addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));2140  return *this;2141}2142 2143AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {2144  addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));2145  return *this;2146}2147 2148AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {2149  assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");2150  auto It = lower_bound(Attrs, Val, AttributeComparator());2151  if (It != Attrs.end() && It->hasAttribute(Val))2152    Attrs.erase(It);2153  return *this;2154}2155 2156AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {2157  auto It = lower_bound(Attrs, A, AttributeComparator());2158  if (It != Attrs.end() && It->hasAttribute(A))2159    Attrs.erase(It);2160  return *this;2161}2162 2163std::optional<uint64_t>2164AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {2165  assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");2166  Attribute A = getAttribute(Kind);2167  if (A.isValid())2168    return A.getValueAsInt();2169  return std::nullopt;2170}2171 2172AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,2173                                        uint64_t Value) {2174  return addAttribute(Attribute::get(Ctx, Kind, Value));2175}2176 2177std::optional<std::pair<unsigned, std::optional<unsigned>>>2178AttrBuilder::getAllocSizeArgs() const {2179  Attribute A = getAttribute(Attribute::AllocSize);2180  if (A.isValid())2181    return A.getAllocSizeArgs();2182  return std::nullopt;2183}2184 2185AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {2186  if (!Align)2187    return *this;2188 2189  assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");2190  return addRawIntAttr(Attribute::Alignment, Align->value());2191}2192 2193AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {2194  // Default alignment, allow the target to define how to align it.2195  if (!Align)2196    return *this;2197 2198  assert(*Align <= 0x100 && "Alignment too large.");2199  return addRawIntAttr(Attribute::StackAlignment, Align->value());2200}2201 2202AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {2203  if (Bytes == 0) return *this;2204 2205  return addRawIntAttr(Attribute::Dereferenceable, Bytes);2206}2207 2208AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {2209  if (Bytes == 0)2210    return *this;2211 2212  return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);2213}2214 2215AttrBuilder &2216AttrBuilder::addAllocSizeAttr(unsigned ElemSize,2217                              const std::optional<unsigned> &NumElems) {2218  return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));2219}2220 2221AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {2222  // (0, 0) is our "not present" value, so we need to check for it here.2223  assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");2224  return addRawIntAttr(Attribute::AllocSize, RawArgs);2225}2226 2227AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,2228                                             std::optional<unsigned> MaxValue) {2229  return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));2230}2231 2232AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {2233  // (0, 0) is not present hence ignore this case2234  if (RawArgs == 0)2235    return *this;2236 2237  return addRawIntAttr(Attribute::VScaleRange, RawArgs);2238}2239 2240AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {2241  if (Kind == UWTableKind::None)2242    return *this;2243  return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));2244}2245 2246AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {2247  return addRawIntAttr(Attribute::Memory, ME.toIntValue());2248}2249 2250AttrBuilder &AttrBuilder::addCapturesAttr(CaptureInfo CI) {2251  return addRawIntAttr(Attribute::Captures, CI.toIntValue());2252}2253 2254AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {2255  if (Mask == fcNone)2256    return *this;2257 2258  return addRawIntAttr(Attribute::NoFPClass, Mask);2259}2260 2261AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {2262  return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));2263}2264 2265Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {2266  assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");2267  Attribute A = getAttribute(Kind);2268  return A.isValid() ? A.getValueAsType() : nullptr;2269}2270 2271AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {2272  return addAttribute(Attribute::get(Ctx, Kind, Ty));2273}2274 2275AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {2276  return addTypeAttr(Attribute::ByVal, Ty);2277}2278 2279AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {2280  return addTypeAttr(Attribute::StructRet, Ty);2281}2282 2283AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {2284  return addTypeAttr(Attribute::ByRef, Ty);2285}2286 2287AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {2288  return addTypeAttr(Attribute::Preallocated, Ty);2289}2290 2291AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {2292  return addTypeAttr(Attribute::InAlloca, Ty);2293}2294 2295AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,2296                                               const ConstantRange &CR) {2297  if (CR.isFullSet())2298    return *this;2299 2300  return addAttribute(Attribute::get(Ctx, Kind, CR));2301}2302 2303AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {2304  return addConstantRangeAttr(Attribute::Range, CR);2305}2306 2307AttrBuilder &2308AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,2309                                      ArrayRef<ConstantRange> Val) {2310  return addAttribute(Attribute::get(Ctx, Kind, Val));2311}2312 2313AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {2314  return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());2315}2316 2317AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) {2318  if (I.hasMetadata(LLVMContext::MD_nonnull))2319    addAttribute(Attribute::NonNull);2320 2321  if (I.hasMetadata(LLVMContext::MD_noundef))2322    addAttribute(Attribute::NoUndef);2323 2324  if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {2325    ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));2326    addAlignmentAttr(CI->getZExtValue());2327  }2328 2329  if (const MDNode *Dereferenceable =2330          I.getMetadata(LLVMContext::MD_dereferenceable)) {2331    ConstantInt *CI =2332        mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));2333    addDereferenceableAttr(CI->getZExtValue());2334  }2335 2336  if (const MDNode *DereferenceableOrNull =2337          I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {2338    ConstantInt *CI =2339        mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));2340    addDereferenceableAttr(CI->getZExtValue());2341  }2342 2343  if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))2344    addRangeAttr(getConstantRangeFromMetadata(*Range));2345 2346  return *this;2347}2348 2349AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {2350  // TODO: Could make this O(n) as we're merging two sorted lists.2351  for (const auto &I : B.attrs())2352    addAttribute(I);2353 2354  return *this;2355}2356 2357AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {2358  erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });2359  return *this;2360}2361 2362bool AttrBuilder::overlaps(const AttributeMask &AM) const {2363  return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });2364}2365 2366Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {2367  assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");2368  auto It = lower_bound(Attrs, A, AttributeComparator());2369  if (It != Attrs.end() && It->hasAttribute(A))2370    return *It;2371  return {};2372}2373 2374Attribute AttrBuilder::getAttribute(StringRef A) const {2375  auto It = lower_bound(Attrs, A, AttributeComparator());2376  if (It != Attrs.end() && It->hasAttribute(A))2377    return *It;2378  return {};2379}2380 2381std::optional<ConstantRange> AttrBuilder::getRange() const {2382  const Attribute RangeAttr = getAttribute(Attribute::Range);2383  if (RangeAttr.isValid())2384    return RangeAttr.getRange();2385  return std::nullopt;2386}2387 2388bool AttrBuilder::contains(Attribute::AttrKind A) const {2389  return getAttribute(A).isValid();2390}2391 2392bool AttrBuilder::contains(StringRef A) const {2393  return getAttribute(A).isValid();2394}2395 2396bool AttrBuilder::operator==(const AttrBuilder &B) const {2397  return Attrs == B.Attrs;2398}2399 2400//===----------------------------------------------------------------------===//2401// AttributeFuncs Function Defintions2402//===----------------------------------------------------------------------===//2403 2404/// Returns true if this is a type legal for the 'nofpclass' attribute. This2405/// follows the same type rules as FPMathOperator.2406bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {2407  return FPMathOperator::isSupportedFloatingPointType(Ty);2408}2409 2410/// Which attributes cannot be applied to a type.2411AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,2412                                               AttributeSafetyKind ASK) {2413  AttributeMask Incompatible;2414 2415  if (!Ty->isIntegerTy()) {2416    // Attributes that only apply to integers.2417    if (ASK & ASK_SAFE_TO_DROP)2418      Incompatible.addAttribute(Attribute::AllocAlign);2419    if (ASK & ASK_UNSAFE_TO_DROP)2420      Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);2421  }2422 2423  if (!Ty->isIntOrIntVectorTy()) {2424    // Attributes that only apply to integers or vector of integers.2425    if (ASK & ASK_SAFE_TO_DROP)2426      Incompatible.addAttribute(Attribute::Range);2427  } else {2428    Attribute RangeAttr = AS.getAttribute(Attribute::Range);2429    if (RangeAttr.isValid() &&2430        RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())2431      Incompatible.addAttribute(Attribute::Range);2432  }2433 2434  if (!Ty->isPointerTy()) {2435    // Attributes that only apply to pointers.2436    if (ASK & ASK_SAFE_TO_DROP)2437      Incompatible.addAttribute(Attribute::NoAlias)2438          .addAttribute(Attribute::NonNull)2439          .addAttribute(Attribute::ReadNone)2440          .addAttribute(Attribute::ReadOnly)2441          .addAttribute(Attribute::Dereferenceable)2442          .addAttribute(Attribute::DereferenceableOrNull)2443          .addAttribute(Attribute::Writable)2444          .addAttribute(Attribute::DeadOnUnwind)2445          .addAttribute(Attribute::Initializes)2446          .addAttribute(Attribute::Captures)2447          .addAttribute(Attribute::DeadOnReturn);2448    if (ASK & ASK_UNSAFE_TO_DROP)2449      Incompatible.addAttribute(Attribute::Nest)2450          .addAttribute(Attribute::SwiftError)2451          .addAttribute(Attribute::Preallocated)2452          .addAttribute(Attribute::InAlloca)2453          .addAttribute(Attribute::ByVal)2454          .addAttribute(Attribute::StructRet)2455          .addAttribute(Attribute::ByRef)2456          .addAttribute(Attribute::ElementType)2457          .addAttribute(Attribute::AllocatedPointer);2458  }2459 2460    // Attributes that only apply to pointers or vectors of pointers.2461  if (!Ty->isPtrOrPtrVectorTy()) {2462    if (ASK & ASK_SAFE_TO_DROP)2463      Incompatible.addAttribute(Attribute::Alignment);2464  }2465 2466  if (ASK & ASK_SAFE_TO_DROP) {2467    if (!isNoFPClassCompatibleType(Ty))2468      Incompatible.addAttribute(Attribute::NoFPClass);2469  }2470 2471  // Some attributes can apply to all "values" but there are no `void` values.2472  if (Ty->isVoidTy()) {2473    if (ASK & ASK_SAFE_TO_DROP)2474      Incompatible.addAttribute(Attribute::NoUndef);2475  }2476 2477  return Incompatible;2478}2479 2480AttributeMask AttributeFuncs::getUBImplyingAttributes() {2481  AttributeMask AM;2482  AM.addAttribute(Attribute::NoUndef);2483  AM.addAttribute(Attribute::Dereferenceable);2484  AM.addAttribute(Attribute::DereferenceableOrNull);2485  return AM;2486}2487 2488/// Callees with dynamic denormal modes are compatible with any caller mode.2489static bool denormModeCompatible(DenormalMode CallerMode,2490                                 DenormalMode CalleeMode) {2491  if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())2492    return true;2493 2494  // If they don't exactly match, it's OK if the mismatched component is2495  // dynamic.2496  if (CalleeMode.Input == CallerMode.Input &&2497      CalleeMode.Output == DenormalMode::Dynamic)2498    return true;2499 2500  if (CalleeMode.Output == CallerMode.Output &&2501      CalleeMode.Input == DenormalMode::Dynamic)2502    return true;2503  return false;2504}2505 2506static bool checkDenormMode(const Function &Caller, const Function &Callee) {2507  DenormalMode CallerMode = Caller.getDenormalModeRaw();2508  DenormalMode CalleeMode = Callee.getDenormalModeRaw();2509 2510  if (denormModeCompatible(CallerMode, CalleeMode)) {2511    DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();2512    DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();2513    if (CallerModeF32 == DenormalMode::getInvalid())2514      CallerModeF32 = CallerMode;2515    if (CalleeModeF32 == DenormalMode::getInvalid())2516      CalleeModeF32 = CalleeMode;2517    return denormModeCompatible(CallerModeF32, CalleeModeF32);2518  }2519 2520  return false;2521}2522 2523static bool checkStrictFP(const Function &Caller, const Function &Callee) {2524  // Do not inline strictfp function into non-strictfp one. It would require2525  // conversion of all FP operations in host function to constrained intrinsics.2526  return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||2527         Caller.getAttributes().hasFnAttr(Attribute::StrictFP);2528}2529 2530template<typename AttrClass>2531static bool isEqual(const Function &Caller, const Function &Callee) {2532  return Caller.getFnAttribute(AttrClass::getKind()) ==2533         Callee.getFnAttribute(AttrClass::getKind());2534}2535 2536static bool isEqual(const Function &Caller, const Function &Callee,2537                    const StringRef &AttrName) {2538  return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);2539}2540 2541/// Compute the logical AND of the attributes of the caller and the2542/// callee.2543///2544/// This function sets the caller's attribute to false if the callee's attribute2545/// is false.2546template<typename AttrClass>2547static void setAND(Function &Caller, const Function &Callee) {2548  if (AttrClass::isSet(Caller, AttrClass::getKind()) &&2549      !AttrClass::isSet(Callee, AttrClass::getKind()))2550    AttrClass::set(Caller, AttrClass::getKind(), false);2551}2552 2553/// Compute the logical OR of the attributes of the caller and the2554/// callee.2555///2556/// This function sets the caller's attribute to true if the callee's attribute2557/// is true.2558template<typename AttrClass>2559static void setOR(Function &Caller, const Function &Callee) {2560  if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&2561      AttrClass::isSet(Callee, AttrClass::getKind()))2562    AttrClass::set(Caller, AttrClass::getKind(), true);2563}2564 2565/// If the inlined function had a higher stack protection level than the2566/// calling function, then bump up the caller's stack protection level.2567static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {2568  // If the calling function has *no* stack protection level (e.g. it was built2569  // with Clang's -fno-stack-protector or no_stack_protector attribute), don't2570  // change it as that could change the program's semantics.2571  if (!Caller.hasStackProtectorFnAttr())2572    return;2573 2574  // If upgrading the SSP attribute, clear out the old SSP Attributes first.2575  // Having multiple SSP attributes doesn't actually hurt, but it adds useless2576  // clutter to the IR.2577  AttributeMask OldSSPAttr;2578  OldSSPAttr.addAttribute(Attribute::StackProtect)2579      .addAttribute(Attribute::StackProtectStrong)2580      .addAttribute(Attribute::StackProtectReq);2581 2582  if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {2583    Caller.removeFnAttrs(OldSSPAttr);2584    Caller.addFnAttr(Attribute::StackProtectReq);2585  } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&2586             !Caller.hasFnAttribute(Attribute::StackProtectReq)) {2587    Caller.removeFnAttrs(OldSSPAttr);2588    Caller.addFnAttr(Attribute::StackProtectStrong);2589  } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&2590             !Caller.hasFnAttribute(Attribute::StackProtectReq) &&2591             !Caller.hasFnAttribute(Attribute::StackProtectStrong))2592    Caller.addFnAttr(Attribute::StackProtect);2593}2594 2595/// If the inlined function required stack probes, then ensure that2596/// the calling function has those too.2597static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {2598  if (!Caller.hasFnAttribute("probe-stack") &&2599      Callee.hasFnAttribute("probe-stack")) {2600    Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));2601  }2602}2603 2604/// If the inlined function defines the size of guard region2605/// on the stack, then ensure that the calling function defines a guard region2606/// that is no larger.2607static void2608adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {2609  Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");2610  if (CalleeAttr.isValid()) {2611    Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");2612    if (CallerAttr.isValid()) {2613      uint64_t CallerStackProbeSize, CalleeStackProbeSize;2614      CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);2615      CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);2616 2617      if (CallerStackProbeSize > CalleeStackProbeSize) {2618        Caller.addFnAttr(CalleeAttr);2619      }2620    } else {2621      Caller.addFnAttr(CalleeAttr);2622    }2623  }2624}2625 2626/// If the inlined function defines a min legal vector width, then ensure2627/// the calling function has the same or larger min legal vector width. If the2628/// caller has the attribute, but the callee doesn't, we need to remove the2629/// attribute from the caller since we can't make any guarantees about the2630/// caller's requirements.2631/// This function is called after the inlining decision has been made so we have2632/// to merge the attribute this way. Heuristics that would use2633/// min-legal-vector-width to determine inline compatibility would need to be2634/// handled as part of inline cost analysis.2635static void2636adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {2637  Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");2638  if (CallerAttr.isValid()) {2639    Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");2640    if (CalleeAttr.isValid()) {2641      uint64_t CallerVectorWidth, CalleeVectorWidth;2642      CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);2643      CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);2644      if (CallerVectorWidth < CalleeVectorWidth)2645        Caller.addFnAttr(CalleeAttr);2646    } else {2647      // If the callee doesn't have the attribute then we don't know anything2648      // and must drop the attribute from the caller.2649      Caller.removeFnAttr("min-legal-vector-width");2650    }2651  }2652}2653 2654/// If the inlined function has null_pointer_is_valid attribute,2655/// set this attribute in the caller post inlining.2656static void2657adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {2658  if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {2659    Caller.addFnAttr(Attribute::NullPointerIsValid);2660  }2661}2662 2663struct EnumAttr {2664  static bool isSet(const Function &Fn,2665                    Attribute::AttrKind Kind) {2666    return Fn.hasFnAttribute(Kind);2667  }2668 2669  static void set(Function &Fn,2670                  Attribute::AttrKind Kind, bool Val) {2671    if (Val)2672      Fn.addFnAttr(Kind);2673    else2674      Fn.removeFnAttr(Kind);2675  }2676};2677 2678struct StrBoolAttr {2679  static bool isSet(const Function &Fn,2680                    StringRef Kind) {2681    auto A = Fn.getFnAttribute(Kind);2682    return A.getValueAsString() == "true";2683  }2684 2685  static void set(Function &Fn,2686                  StringRef Kind, bool Val) {2687    Fn.addFnAttr(Kind, Val ? "true" : "false");2688  }2689};2690 2691#define GET_ATTR_NAMES2692#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \2693  struct ENUM_NAME##Attr : EnumAttr {                                          \2694    static enum Attribute::AttrKind getKind() {                                \2695      return llvm::Attribute::ENUM_NAME;                                       \2696    }                                                                          \2697  };2698#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME)                             \2699  struct ENUM_NAME##Attr : StrBoolAttr {                                       \2700    static StringRef getKind() { return #DISPLAY_NAME; }                       \2701  };2702#include "llvm/IR/Attributes.inc"2703 2704#define GET_ATTR_COMPAT_FUNC2705#include "llvm/IR/Attributes.inc"2706 2707bool AttributeFuncs::areInlineCompatible(const Function &Caller,2708                                         const Function &Callee) {2709  return hasCompatibleFnAttrs(Caller, Callee);2710}2711 2712bool AttributeFuncs::areOutlineCompatible(const Function &A,2713                                          const Function &B) {2714  return hasCompatibleFnAttrs(A, B);2715}2716 2717void AttributeFuncs::mergeAttributesForInlining(Function &Caller,2718                                                const Function &Callee) {2719  mergeFnAttrs(Caller, Callee);2720}2721 2722void AttributeFuncs::mergeAttributesForOutlining(Function &Base,2723                                                const Function &ToMerge) {2724 2725  // We merge functions so that they meet the most general case.2726  // For example, if the NoNansFPMathAttr is set in one function, but not in2727  // the other, in the merged function we can say that the NoNansFPMathAttr2728  // is not set.2729  // However if we have the SpeculativeLoadHardeningAttr set true in one2730  // function, but not the other, we make sure that the function retains2731  // that aspect in the merged function.2732  mergeFnAttrs(Base, ToMerge);2733}2734 2735void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,2736                                                   uint64_t Width) {2737  Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");2738  if (Attr.isValid()) {2739    uint64_t OldWidth;2740    Attr.getValueAsString().getAsInteger(0, OldWidth);2741    if (Width > OldWidth)2742      Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));2743  }2744}2745