//===- Attributes.cpp - Implement AttributesList --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// \file
// This file implements the Attribute, AttributeImpl, AttrBuilder,
// AttributeListImpl, and AttributeList classes.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Attributes.h"
#include "AttributeImpl.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ModRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <optional>
#include <string>
#include <tuple>
#include <utility>

using namespace llvm;

//===----------------------------------------------------------------------===//
// Attribute Construction Methods
//===----------------------------------------------------------------------===//

// allocsize has two integer arguments, but because they're both 32 bits, we can
// pack them into one 64-bit value, at the cost of making said value
// nonsensical.
//
// In order to do this, we need to reserve one value of the second (optional)
// allocsize argument to signify "not present."
static const unsigned AllocSizeNumElemsNotPresent = -1;

static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
                                  const std::optional<unsigned> &NumElemsArg) {
  assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
         "Attempting to pack a reserved value");

  return uint64_t(ElemSizeArg) << 32 |
         NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
}

static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num) {
  unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
  unsigned ElemSizeArg = Num >> 32;

  std::optional<unsigned> NumElemsArg;
  if (NumElems != AllocSizeNumElemsNotPresent)
    NumElemsArg = NumElems;
  return std::make_pair(ElemSizeArg, NumElemsArg);
}

static uint64_t packVScaleRangeArgs(unsigned MinValue,
                                    std::optional<unsigned> MaxValue) {
  return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
}

static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value) {
  unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
  unsigned MinValue = Value >> 32;

  return std::make_pair(MinValue,
                        MaxValue > 0 ? MaxValue : std::optional<unsigned>());
}

Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
                         uint64_t Val) {
  bool IsIntAttr = Attribute::isIntAttrKind(Kind);
  assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
         "Not an enum or int attribute");

  LLVMContextImpl *pImpl = Context.pImpl;
  FoldingSetNodeID ID;
  ID.AddInteger(Kind);
  if (IsIntAttr)
    ID.AddInteger(Val);
  else
    assert(Val == 0 && "Value must be zero for enum attributes");

  void *InsertPoint;
  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);

  if (!PA) {
    // If we didn't find any existing attributes of the same shape then create a
    // new one and insert it.
    if (!IsIntAttr)
      PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
    else
      PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
  }

  // Return the Attribute that we found or created.
  return Attribute(PA);
}

Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
  LLVMContextImpl *pImpl = Context.pImpl;
  FoldingSetNodeID ID;
  ID.AddString(Kind);
  if (!Val.empty()) ID.AddString(Val);

  void *InsertPoint;
  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);

  if (!PA) {
    // If we didn't find any existing attributes of the same shape then create a
    // new one and insert it.
    void *Mem =
        pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
                              alignof(StringAttributeImpl));
    PA = new (Mem) StringAttributeImpl(Kind, Val);
    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
  }

  // Return the Attribute that we found or created.
  return Attribute(PA);
}

Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
                         Type *Ty) {
  assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
  LLVMContextImpl *pImpl = Context.pImpl;
  FoldingSetNodeID ID;
  ID.AddInteger(Kind);
  ID.AddPointer(Ty);

  void *InsertPoint;
  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);

  if (!PA) {
    // If we didn't find any existing attributes of the same shape then create a
    // new one and insert it.
    PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
  }

  // Return the Attribute that we found or created.
  return Attribute(PA);
}

Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
  assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
  return get(Context, Alignment, A.value());
}

Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
  assert(A <= 0x100 && "Alignment too large.");
  return get(Context, StackAlignment, A.value());
}

Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
                                                uint64_t Bytes) {
  assert(Bytes && "Bytes must be non-zero.");
  return get(Context, Dereferenceable, Bytes);
}

Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
                                                       uint64_t Bytes) {
  assert(Bytes && "Bytes must be non-zero.");
  return get(Context, DereferenceableOrNull, Bytes);
}

Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
  return get(Context, ByVal, Ty);
}

Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
  return get(Context, StructRet, Ty);
}

Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
  return get(Context, ByRef, Ty);
}

Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
  return get(Context, Preallocated, Ty);
}

Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
  return get(Context, InAlloca, Ty);
}

Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
                                        UWTableKind Kind) {
  return get(Context, UWTable, uint64_t(Kind));
}

Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
                                          MemoryEffects ME) {
  return get(Context, Memory, ME.toIntValue());
}

Attribute
Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
                                const std::optional<unsigned> &NumElemsArg) {
  assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
         "Invalid allocsize arguments -- given allocsize(0, 0)");
  return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
}

Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
                                            unsigned MinValue,
                                            unsigned MaxValue) {
  return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
}

Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
  return StringSwitch<Attribute::AttrKind>(AttrName)
#define GET_ATTR_NAMES
#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
  .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
#include "llvm/IR/Attributes.inc"
      .Default(Attribute::None);
}

StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
  switch (AttrKind) {
#define GET_ATTR_NAMES
#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
  case Attribute::ENUM_NAME:                                                   \
    return #DISPLAY_NAME;
#include "llvm/IR/Attributes.inc"
  case Attribute::None:
    return "none";
  default:
    llvm_unreachable("invalid Kind");
  }
}

bool Attribute::isExistingAttribute(StringRef Name) {
  return StringSwitch<bool>(Name)
#define GET_ATTR_NAMES
#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
#include "llvm/IR/Attributes.inc"
      .Default(false);
}

//===----------------------------------------------------------------------===//
// Attribute Accessor Methods
//===----------------------------------------------------------------------===//

bool Attribute::isEnumAttribute() const {
  return pImpl && pImpl->isEnumAttribute();
}

bool Attribute::isIntAttribute() const {
  return pImpl && pImpl->isIntAttribute();
}

bool Attribute::isStringAttribute() const {
  return pImpl && pImpl->isStringAttribute();
}

bool Attribute::isTypeAttribute() const {
  return pImpl && pImpl->isTypeAttribute();
}

Attribute::AttrKind Attribute::getKindAsEnum() const {
  if (!pImpl) return None;
  assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
         "Invalid attribute type to get the kind as an enum!");
  return pImpl->getKindAsEnum();
}

uint64_t Attribute::getValueAsInt() const {
  if (!pImpl) return 0;
  assert(isIntAttribute() &&
         "Expected the attribute to be an integer attribute!");
  return pImpl->getValueAsInt();
}

bool Attribute::getValueAsBool() const {
  if (!pImpl) return false;
  assert(isStringAttribute() &&
         "Expected the attribute to be a string attribute!");
  return pImpl->getValueAsBool();
}

StringRef Attribute::getKindAsString() const {
  if (!pImpl) return {};
  assert(isStringAttribute() &&
         "Invalid attribute type to get the kind as a string!");
  return pImpl->getKindAsString();
}

StringRef Attribute::getValueAsString() const {
  if (!pImpl) return {};
  assert(isStringAttribute() &&
         "Invalid attribute type to get the value as a string!");
  return pImpl->getValueAsString();
}

Type *Attribute::getValueAsType() const {
  if (!pImpl) return {};
  assert(isTypeAttribute() &&
         "Invalid attribute type to get the value as a type!");
  return pImpl->getValueAsType();
}


bool Attribute::hasAttribute(AttrKind Kind) const {
  return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
}

bool Attribute::hasAttribute(StringRef Kind) const {
  if (!isStringAttribute()) return false;
  return pImpl && pImpl->hasAttribute(Kind);
}

MaybeAlign Attribute::getAlignment() const {
  assert(hasAttribute(Attribute::Alignment) &&
         "Trying to get alignment from non-alignment attribute!");
  return MaybeAlign(pImpl->getValueAsInt());
}

MaybeAlign Attribute::getStackAlignment() const {
  assert(hasAttribute(Attribute::StackAlignment) &&
         "Trying to get alignment from non-alignment attribute!");
  return MaybeAlign(pImpl->getValueAsInt());
}

uint64_t Attribute::getDereferenceableBytes() const {
  assert(hasAttribute(Attribute::Dereferenceable) &&
         "Trying to get dereferenceable bytes from "
         "non-dereferenceable attribute!");
  return pImpl->getValueAsInt();
}

uint64_t Attribute::getDereferenceableOrNullBytes() const {
  assert(hasAttribute(Attribute::DereferenceableOrNull) &&
         "Trying to get dereferenceable bytes from "
         "non-dereferenceable attribute!");
  return pImpl->getValueAsInt();
}

std::pair<unsigned, std::optional<unsigned>>
Attribute::getAllocSizeArgs() const {
  assert(hasAttribute(Attribute::AllocSize) &&
         "Trying to get allocsize args from non-allocsize attribute");
  return unpackAllocSizeArgs(pImpl->getValueAsInt());
}

unsigned Attribute::getVScaleRangeMin() const {
  assert(hasAttribute(Attribute::VScaleRange) &&
         "Trying to get vscale args from non-vscale attribute");
  return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
}

std::optional<unsigned> Attribute::getVScaleRangeMax() const {
  assert(hasAttribute(Attribute::VScaleRange) &&
         "Trying to get vscale args from non-vscale attribute");
  return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
}

UWTableKind Attribute::getUWTableKind() const {
  assert(hasAttribute(Attribute::UWTable) &&
         "Trying to get unwind table kind from non-uwtable attribute");
  return UWTableKind(pImpl->getValueAsInt());
}

AllocFnKind Attribute::getAllocKind() const {
  assert(hasAttribute(Attribute::AllocKind) &&
         "Trying to get allockind value from non-allockind attribute");
  return AllocFnKind(pImpl->getValueAsInt());
}

MemoryEffects Attribute::getMemoryEffects() const {
  assert(hasAttribute(Attribute::Memory) &&
         "Can only call getMemoryEffects() on memory attribute");
  return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
}

static const char *getModRefStr(ModRefInfo MR) {
  switch (MR) {
  case ModRefInfo::NoModRef:
    return "none";
  case ModRefInfo::Ref:
    return "read";
  case ModRefInfo::Mod:
    return "write";
  case ModRefInfo::ModRef:
    return "readwrite";
  }
  llvm_unreachable("Invalid ModRefInfo");
}

std::string Attribute::getAsString(bool InAttrGrp) const {
  if (!pImpl) return {};

  if (isEnumAttribute())
    return getNameFromAttrKind(getKindAsEnum()).str();

  if (isTypeAttribute()) {
    std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
    Result += '(';
    raw_string_ostream OS(Result);
    getValueAsType()->print(OS, false, true);
    OS.flush();
    Result += ')';
    return Result;
  }

  // FIXME: These should be output like this:
  //
  //   align=4
  //   alignstack=8
  //
  if (hasAttribute(Attribute::Alignment))
    return (InAttrGrp ? "align=" + Twine(getValueAsInt())
                      : "align " + Twine(getValueAsInt()))
        .str();

  auto AttrWithBytesToString = [&](const char *Name) {
    return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
                      : Name + ("(" + Twine(getValueAsInt())) + ")")
        .str();
  };

  if (hasAttribute(Attribute::StackAlignment))
    return AttrWithBytesToString("alignstack");

  if (hasAttribute(Attribute::Dereferenceable))
    return AttrWithBytesToString("dereferenceable");

  if (hasAttribute(Attribute::DereferenceableOrNull))
    return AttrWithBytesToString("dereferenceable_or_null");

  if (hasAttribute(Attribute::AllocSize)) {
    unsigned ElemSize;
    std::optional<unsigned> NumElems;
    std::tie(ElemSize, NumElems) = getAllocSizeArgs();

    return (NumElems
                ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
                : "allocsize(" + Twine(ElemSize) + ")")
        .str();
  }

  if (hasAttribute(Attribute::VScaleRange)) {
    unsigned MinValue = getVScaleRangeMin();
    std::optional<unsigned> MaxValue = getVScaleRangeMax();
    return ("vscale_range(" + Twine(MinValue) + "," +
            Twine(MaxValue.value_or(0)) + ")")
        .str();
  }

  if (hasAttribute(Attribute::UWTable)) {
    UWTableKind Kind = getUWTableKind();
    if (Kind != UWTableKind::None) {
      return Kind == UWTableKind::Default
                 ? "uwtable"
                 : ("uwtable(" +
                    Twine(Kind == UWTableKind::Sync ? "sync" : "async") + ")")
                       .str();
    }
  }

  if (hasAttribute(Attribute::AllocKind)) {
    AllocFnKind Kind = getAllocKind();
    SmallVector<StringRef> parts;
    if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
      parts.push_back("alloc");
    if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
      parts.push_back("realloc");
    if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
      parts.push_back("free");
    if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
      parts.push_back("uninitialized");
    if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
      parts.push_back("zeroed");
    if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
      parts.push_back("aligned");
    return ("allockind(\"" +
            Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
        .str();
  }

  if (hasAttribute(Attribute::Memory)) {
    std::string Result;
    raw_string_ostream OS(Result);
    bool First = true;
    OS << "memory(";

    MemoryEffects ME = getMemoryEffects();

    // Print access kind for "other" as the default access kind. This way it
    // will apply to any new location kinds that get split out of "other".
    ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
    if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
      First = false;
      OS << getModRefStr(OtherMR);
    }

    for (auto Loc : MemoryEffects::locations()) {
      ModRefInfo MR = ME.getModRef(Loc);
      if (MR == OtherMR)
        continue;

      if (!First)
        OS << ", ";
      First = false;

      switch (Loc) {
      case MemoryEffects::ArgMem:
        OS << "argmem: ";
        break;
      case MemoryEffects::InaccessibleMem:
        OS << "inaccessiblemem: ";
        break;
      case MemoryEffects::Other:
        llvm_unreachable("This is represented as the default access kind");
      }
      OS << getModRefStr(MR);
    }
    OS << ")";
    OS.flush();
    return Result;
  }

  // Convert target-dependent attributes to strings of the form:
  //
  //   "kind"
  //   "kind" = "value"
  //
  if (isStringAttribute()) {
    std::string Result;
    {
      raw_string_ostream OS(Result);
      OS << '"' << getKindAsString() << '"';

      // Since some attribute strings contain special characters that cannot be
      // printable, those have to be escaped to make the attribute value
      // printable as is.  e.g. "\01__gnu_mcount_nc"
      const auto &AttrVal = pImpl->getValueAsString();
      if (!AttrVal.empty()) {
        OS << "=\"";
        printEscapedString(AttrVal, OS);
        OS << "\"";
      }
    }
    return Result;
  }

  llvm_unreachable("Unknown attribute");
}

bool Attribute::hasParentContext(LLVMContext &C) const {
  assert(isValid() && "invalid Attribute doesn't refer to any context");
  FoldingSetNodeID ID;
  pImpl->Profile(ID);
  void *Unused;
  return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
}

bool Attribute::operator<(Attribute A) const {
  if (!pImpl && !A.pImpl) return false;
  if (!pImpl) return true;
  if (!A.pImpl) return false;
  return *pImpl < *A.pImpl;
}

void Attribute::Profile(FoldingSetNodeID &ID) const {
  ID.AddPointer(pImpl);
}

enum AttributeProperty {
  FnAttr = (1 << 0),
  ParamAttr = (1 << 1),
  RetAttr = (1 << 2),
};

#define GET_ATTR_PROP_TABLE
#include "llvm/IR/Attributes.inc"

static bool hasAttributeProperty(Attribute::AttrKind Kind,
                                 AttributeProperty Prop) {
  unsigned Index = Kind - 1;
  assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
  return AttrPropTable[Index] & Prop;
}

bool Attribute::canUseAsFnAttr(AttrKind Kind) {
  return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
}

bool Attribute::canUseAsParamAttr(AttrKind Kind) {
  return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
}

bool Attribute::canUseAsRetAttr(AttrKind Kind) {
  return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
}

//===----------------------------------------------------------------------===//
// AttributeImpl Definition
//===----------------------------------------------------------------------===//

bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
  if (isStringAttribute()) return false;
  return getKindAsEnum() == A;
}

bool AttributeImpl::hasAttribute(StringRef Kind) const {
  if (!isStringAttribute()) return false;
  return getKindAsString() == Kind;
}

Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
  assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
  return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
}

uint64_t AttributeImpl::getValueAsInt() const {
  assert(isIntAttribute());
  return static_cast<const IntAttributeImpl *>(this)->getValue();
}

bool AttributeImpl::getValueAsBool() const {
  assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
  return getValueAsString() == "true";
}

StringRef AttributeImpl::getKindAsString() const {
  assert(isStringAttribute());
  return static_cast<const StringAttributeImpl *>(this)->getStringKind();
}

StringRef AttributeImpl::getValueAsString() const {
  assert(isStringAttribute());
  return static_cast<const StringAttributeImpl *>(this)->getStringValue();
}

Type *AttributeImpl::getValueAsType() const {
  assert(isTypeAttribute());
  return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
}

bool AttributeImpl::operator<(const AttributeImpl &AI) const {
  if (this == &AI)
    return false;

  // This sorts the attributes with Attribute::AttrKinds coming first (sorted
  // relative to their enum value) and then strings.
  if (!isStringAttribute()) {
    if (AI.isStringAttribute())
      return true;
    if (getKindAsEnum() != AI.getKindAsEnum())
      return getKindAsEnum() < AI.getKindAsEnum();
    assert(!AI.isEnumAttribute() && "Non-unique attribute");
    assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
    // TODO: Is this actually needed?
    assert(AI.isIntAttribute() && "Only possibility left");
    return getValueAsInt() < AI.getValueAsInt();
  }

  if (!AI.isStringAttribute())
    return false;
  if (getKindAsString() == AI.getKindAsString())
    return getValueAsString() < AI.getValueAsString();
  return getKindAsString() < AI.getKindAsString();
}

//===----------------------------------------------------------------------===//
// AttributeSet Definition
//===----------------------------------------------------------------------===//

AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
  return AttributeSet(AttributeSetNode::get(C, B));
}

AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
  return AttributeSet(AttributeSetNode::get(C, Attrs));
}

AttributeSet AttributeSet::addAttribute(LLVMContext &C,
                                        Attribute::AttrKind Kind) const {
  if (hasAttribute(Kind)) return *this;
  AttrBuilder B(C);
  B.addAttribute(Kind);
  return addAttributes(C, AttributeSet::get(C, B));
}

AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
                                        StringRef Value) const {
  AttrBuilder B(C);
  B.addAttribute(Kind, Value);
  return addAttributes(C, AttributeSet::get(C, B));
}

AttributeSet AttributeSet::addAttributes(LLVMContext &C,
                                         const AttributeSet AS) const {
  if (!hasAttributes())
    return AS;

  if (!AS.hasAttributes())
    return *this;

  AttrBuilder B(C, *this);
  B.merge(AttrBuilder(C, AS));
  return get(C, B);
}

AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
                                             Attribute::AttrKind Kind) const {
  if (!hasAttribute(Kind)) return *this;
  AttrBuilder B(C, *this);
  B.removeAttribute(Kind);
  return get(C, B);
}

AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
                                             StringRef Kind) const {
  if (!hasAttribute(Kind)) return *this;
  AttrBuilder B(C, *this);
  B.removeAttribute(Kind);
  return get(C, B);
}

AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
                                            const AttributeMask &Attrs) const {
  AttrBuilder B(C, *this);
  // If there is nothing to remove, directly return the original set.
  if (!B.overlaps(Attrs))
    return *this;

  B.remove(Attrs);
  return get(C, B);
}

unsigned AttributeSet::getNumAttributes() const {
  return SetNode ? SetNode->getNumAttributes() : 0;
}

bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
  return SetNode ? SetNode->hasAttribute(Kind) : false;
}

bool AttributeSet::hasAttribute(StringRef Kind) const {
  return SetNode ? SetNode->hasAttribute(Kind) : false;
}

Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
  return SetNode ? SetNode->getAttribute(Kind) : Attribute();
}

Attribute AttributeSet::getAttribute(StringRef Kind) const {
  return SetNode ? SetNode->getAttribute(Kind) : Attribute();
}

MaybeAlign AttributeSet::getAlignment() const {
  return SetNode ? SetNode->getAlignment() : std::nullopt;
}

MaybeAlign AttributeSet::getStackAlignment() const {
  return SetNode ? SetNode->getStackAlignment() : std::nullopt;
}

uint64_t AttributeSet::getDereferenceableBytes() const {
  return SetNode ? SetNode->getDereferenceableBytes() : 0;
}

uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
  return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
}

Type *AttributeSet::getByRefType() const {
  return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
}

Type *AttributeSet::getByValType() const {
  return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
}

Type *AttributeSet::getStructRetType() const {
  return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
}

Type *AttributeSet::getPreallocatedType() const {
  return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
}

Type *AttributeSet::getInAllocaType() const {
  return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
}

Type *AttributeSet::getElementType() const {
  return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
}

std::optional<std::pair<unsigned, std::optional<unsigned>>>
AttributeSet::getAllocSizeArgs() const {
  if (SetNode)
    return SetNode->getAllocSizeArgs();
  return std::nullopt;
}

unsigned AttributeSet::getVScaleRangeMin() const {
  return SetNode ? SetNode->getVScaleRangeMin() : 1;
}

std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
  return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
}

UWTableKind AttributeSet::getUWTableKind() const {
  return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
}

AllocFnKind AttributeSet::getAllocKind() const {
  return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
}

MemoryEffects AttributeSet::getMemoryEffects() const {
  return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
}

std::string AttributeSet::getAsString(bool InAttrGrp) const {
  return SetNode ? SetNode->getAsString(InAttrGrp) : "";
}

bool AttributeSet::hasParentContext(LLVMContext &C) const {
  assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
  FoldingSetNodeID ID;
  SetNode->Profile(ID);
  void *Unused;
  return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
}

AttributeSet::iterator AttributeSet::begin() const {
  return SetNode ? SetNode->begin() : nullptr;
}

AttributeSet::iterator AttributeSet::end() const {
  return SetNode ? SetNode->end() : nullptr;
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void AttributeSet::dump() const {
  dbgs() << "AS =\n";
    dbgs() << "  { ";
    dbgs() << getAsString(true) << " }\n";
}
#endif

//===----------------------------------------------------------------------===//
// AttributeSetNode Definition
//===----------------------------------------------------------------------===//

AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
    : NumAttrs(Attrs.size()) {
  // There's memory after the node where we can store the entries in.
  llvm::copy(Attrs, getTrailingObjects<Attribute>());

  for (const auto &I : *this) {
    if (I.isStringAttribute())
      StringAttrs.insert({ I.getKindAsString(), I });
    else
      AvailableAttrs.addAttribute(I.getKindAsEnum());
  }
}

AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
                                        ArrayRef<Attribute> Attrs) {
  SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
  llvm::sort(SortedAttrs);
  return getSorted(C, SortedAttrs);
}

AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
                                              ArrayRef<Attribute> SortedAttrs) {
  if (SortedAttrs.empty())
    return nullptr;

  // Build a key to look up the existing attributes.
  LLVMContextImpl *pImpl = C.pImpl;
  FoldingSetNodeID ID;

  assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
  for (const auto &Attr : SortedAttrs)
    Attr.Profile(ID);

  void *InsertPoint;
  AttributeSetNode *PA =
    pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);

  // If we didn't find any existing attributes of the same shape then create a
  // new one and insert it.
  if (!PA) {
    // Coallocate entries after the AttributeSetNode itself.
    void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
    PA = new (Mem) AttributeSetNode(SortedAttrs);
    pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
  }

  // Return the AttributeSetNode that we found or created.
  return PA;
}

AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
  return getSorted(C, B.attrs());
}

bool AttributeSetNode::hasAttribute(StringRef Kind) const {
  return StringAttrs.count(Kind);
}

std::optional<Attribute>
AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
  // Do a quick presence check.
  if (!hasAttribute(Kind))
    return std::nullopt;

  // Attributes in a set are sorted by enum value, followed by string
  // attributes. Binary search the one we want.
  const Attribute *I =
      std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
                       [](Attribute A, Attribute::AttrKind Kind) {
                         return A.getKindAsEnum() < Kind;
                       });
  assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
  return *I;
}

Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
  if (auto A = findEnumAttribute(Kind))
    return *A;
  return {};
}

Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
  return StringAttrs.lookup(Kind);
}

MaybeAlign AttributeSetNode::getAlignment() const {
  if (auto A = findEnumAttribute(Attribute::Alignment))
    return A->getAlignment();
  return std::nullopt;
}

MaybeAlign AttributeSetNode::getStackAlignment() const {
  if (auto A = findEnumAttribute(Attribute::StackAlignment))
    return A->getStackAlignment();
  return std::nullopt;
}

Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
  if (auto A = findEnumAttribute(Kind))
    return A->getValueAsType();
  return nullptr;
}

uint64_t AttributeSetNode::getDereferenceableBytes() const {
  if (auto A = findEnumAttribute(Attribute::Dereferenceable))
    return A->getDereferenceableBytes();
  return 0;
}

uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
  if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
    return A->getDereferenceableOrNullBytes();
  return 0;
}

std::optional<std::pair<unsigned, std::optional<unsigned>>>
AttributeSetNode::getAllocSizeArgs() const {
  if (auto A = findEnumAttribute(Attribute::AllocSize))
    return A->getAllocSizeArgs();
  return std::nullopt;
}

unsigned AttributeSetNode::getVScaleRangeMin() const {
  if (auto A = findEnumAttribute(Attribute::VScaleRange))
    return A->getVScaleRangeMin();
  return 1;
}

std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
  if (auto A = findEnumAttribute(Attribute::VScaleRange))
    return A->getVScaleRangeMax();
  return std::nullopt;
}

UWTableKind AttributeSetNode::getUWTableKind() const {
  if (auto A = findEnumAttribute(Attribute::UWTable))
    return A->getUWTableKind();
  return UWTableKind::None;
}

AllocFnKind AttributeSetNode::getAllocKind() const {
  if (auto A = findEnumAttribute(Attribute::AllocKind))
    return A->getAllocKind();
  return AllocFnKind::Unknown;
}

MemoryEffects AttributeSetNode::getMemoryEffects() const {
  if (auto A = findEnumAttribute(Attribute::Memory))
    return A->getMemoryEffects();
  return MemoryEffects::unknown();
}

std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
  std::string Str;
  for (iterator I = begin(), E = end(); I != E; ++I) {
    if (I != begin())
      Str += ' ';
    Str += I->getAsString(InAttrGrp);
  }
  return Str;
}

//===----------------------------------------------------------------------===//
// AttributeListImpl Definition
//===----------------------------------------------------------------------===//

/// Map from AttributeList index to the internal array index. Adding one happens
/// to work, because -1 wraps around to 0.
static unsigned attrIdxToArrayIdx(unsigned Index) {
  return Index + 1;
}

AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
    : NumAttrSets(Sets.size()) {
  assert(!Sets.empty() && "pointless AttributeListImpl");

  // There's memory after the node where we can store the entries in.
  llvm::copy(Sets, getTrailingObjects<AttributeSet>());

  // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
  // summary bitsets.
  for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
    if (!I.isStringAttribute())
      AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());

  for (const auto &Set : Sets)
    for (const auto &I : Set)
      if (!I.isStringAttribute())
        AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
}

void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
  Profile(ID, ArrayRef(begin(), end()));
}

void AttributeListImpl::Profile(FoldingSetNodeID &ID,
                                ArrayRef<AttributeSet> Sets) {
  for (const auto &Set : Sets)
    ID.AddPointer(Set.SetNode);
}

bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
                                        unsigned *Index) const {
  if (!AvailableSomewhereAttrs.hasAttribute(Kind))
    return false;

  if (Index) {
    for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
      if (begin()[I].hasAttribute(Kind)) {
        *Index = I - 1;
        break;
      }
    }
  }

  return true;
}


#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
  AttributeList(const_cast<AttributeListImpl *>(this)).dump();
}
#endif

//===----------------------------------------------------------------------===//
// AttributeList Construction and Mutation Methods
//===----------------------------------------------------------------------===//

AttributeList AttributeList::getImpl(LLVMContext &C,
                                     ArrayRef<AttributeSet> AttrSets) {
  assert(!AttrSets.empty() && "pointless AttributeListImpl");

  LLVMContextImpl *pImpl = C.pImpl;
  FoldingSetNodeID ID;
  AttributeListImpl::Profile(ID, AttrSets);

  void *InsertPoint;
  AttributeListImpl *PA =
      pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);

  // If we didn't find any existing attributes of the same shape then
  // create a new one and insert it.
  if (!PA) {
    // Coallocate entries after the AttributeListImpl itself.
    void *Mem = pImpl->Alloc.Allocate(
        AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
        alignof(AttributeListImpl));
    PA = new (Mem) AttributeListImpl(AttrSets);
    pImpl->AttrsLists.InsertNode(PA, InsertPoint);
  }

  // Return the AttributesList that we found or created.
  return AttributeList(PA);
}

AttributeList
AttributeList::get(LLVMContext &C,
                   ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
  // If there are no attributes then return a null AttributesList pointer.
  if (Attrs.empty())
    return {};

  assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
         "Misordered Attributes list!");
  assert(llvm::all_of(Attrs,
                      [](const std::pair<unsigned, Attribute> &Pair) {
                        return Pair.second.isValid();
                      }) &&
         "Pointless attribute!");

  // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
  // list.
  SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
  for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
         E = Attrs.end(); I != E; ) {
    unsigned Index = I->first;
    SmallVector<Attribute, 4> AttrVec;
    while (I != E && I->first == Index) {
      AttrVec.push_back(I->second);
      ++I;
    }

    AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
  }

  return get(C, AttrPairVec);
}

AttributeList
AttributeList::get(LLVMContext &C,
                   ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
  // If there are no attributes then return a null AttributesList pointer.
  if (Attrs.empty())
    return {};

  assert(llvm::is_sorted(Attrs, llvm::less_first()) &&
         "Misordered Attributes list!");
  assert(llvm::none_of(Attrs,
                       [](const std::pair<unsigned, AttributeSet> &Pair) {
                         return !Pair.second.hasAttributes();
                       }) &&
         "Pointless attribute!");

  unsigned MaxIndex = Attrs.back().first;
  // If the MaxIndex is FunctionIndex and there are other indices in front
  // of it, we need to use the largest of those to get the right size.
  if (MaxIndex == FunctionIndex && Attrs.size() > 1)
    MaxIndex = Attrs[Attrs.size() - 2].first;

  SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
  for (const auto &Pair : Attrs)
    AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;

  return getImpl(C, AttrVec);
}

AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
                                 AttributeSet RetAttrs,
                                 ArrayRef<AttributeSet> ArgAttrs) {
  // Scan from the end to find the last argument with attributes.  Most
  // arguments don't have attributes, so it's nice if we can have fewer unique
  // AttributeListImpls by dropping empty attribute sets at the end of the list.
  unsigned NumSets = 0;
  for (size_t I = ArgAttrs.size(); I != 0; --I) {
    if (ArgAttrs[I - 1].hasAttributes()) {
      NumSets = I + 2;
      break;
    }
  }
  if (NumSets == 0) {
    // Check function and return attributes if we didn't have argument
    // attributes.
    if (RetAttrs.hasAttributes())
      NumSets = 2;
    else if (FnAttrs.hasAttributes())
      NumSets = 1;
  }

  // If all attribute sets were empty, we can use the empty attribute list.
  if (NumSets == 0)
    return {};

  SmallVector<AttributeSet, 8> AttrSets;
  AttrSets.reserve(NumSets);
  // If we have any attributes, we always have function attributes.
  AttrSets.push_back(FnAttrs);
  if (NumSets > 1)
    AttrSets.push_back(RetAttrs);
  if (NumSets > 2) {
    // Drop the empty argument attribute sets at the end.
    ArgAttrs = ArgAttrs.take_front(NumSets - 2);
    llvm::append_range(AttrSets, ArgAttrs);
  }

  return getImpl(C, AttrSets);
}

AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
                                 AttributeSet Attrs) {
  if (!Attrs.hasAttributes())
    return {};
  Index = attrIdxToArrayIdx(Index);
  SmallVector<AttributeSet, 8> AttrSets(Index + 1);
  AttrSets[Index] = Attrs;
  return getImpl(C, AttrSets);
}

AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
                                 const AttrBuilder &B) {
  return get(C, Index, AttributeSet::get(C, B));
}

AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
                                 ArrayRef<Attribute::AttrKind> Kinds) {
  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
  for (const auto K : Kinds)
    Attrs.emplace_back(Index, Attribute::get(C, K));
  return get(C, Attrs);
}

AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
                                 ArrayRef<Attribute::AttrKind> Kinds,
                                 ArrayRef<uint64_t> Values) {
  assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
  auto VI = Values.begin();
  for (const auto K : Kinds)
    Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
  return get(C, Attrs);
}

AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
                                 ArrayRef<StringRef> Kinds) {
  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
  for (const auto &K : Kinds)
    Attrs.emplace_back(Index, Attribute::get(C, K));
  return get(C, Attrs);
}

AttributeList AttributeList::get(LLVMContext &C,
                                 ArrayRef<AttributeList> Attrs) {
  if (Attrs.empty())
    return {};
  if (Attrs.size() == 1)
    return Attrs[0];

  unsigned MaxSize = 0;
  for (const auto &List : Attrs)
    MaxSize = std::max(MaxSize, List.getNumAttrSets());

  // If every list was empty, there is no point in merging the lists.
  if (MaxSize == 0)
    return {};

  SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
  for (unsigned I = 0; I < MaxSize; ++I) {
    AttrBuilder CurBuilder(C);
    for (const auto &List : Attrs)
      CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
    NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
  }

  return getImpl(C, NewAttrSets);
}

AttributeList
AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
                                   Attribute::AttrKind Kind) const {
  AttributeSet Attrs = getAttributes(Index);
  if (Attrs.hasAttribute(Kind))
    return *this;
  // TODO: Insert at correct position and avoid sort.
  SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
  NewAttrs.push_back(Attribute::get(C, Kind));
  return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
}

AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
                                                 StringRef Kind,
                                                 StringRef Value) const {
  AttrBuilder B(C);
  B.addAttribute(Kind, Value);
  return addAttributesAtIndex(C, Index, B);
}

AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
                                                 Attribute A) const {
  AttrBuilder B(C);
  B.addAttribute(A);
  return addAttributesAtIndex(C, Index, B);
}

AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
                                                  unsigned Index,
                                                  AttributeSet Attrs) const {
  Index = attrIdxToArrayIdx(Index);
  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  if (Index >= AttrSets.size())
    AttrSets.resize(Index + 1);
  AttrSets[Index] = Attrs;

  // Remove trailing empty attribute sets.
  while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
    AttrSets.pop_back();
  if (AttrSets.empty())
    return {};
  return AttributeList::getImpl(C, AttrSets);
}

AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
                                                  unsigned Index,
                                                  const AttrBuilder &B) const {
  if (!B.hasAttributes())
    return *this;

  if (!pImpl)
    return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});

  AttrBuilder Merged(C, getAttributes(Index));
  Merged.merge(B);
  return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
}

AttributeList AttributeList::addParamAttribute(LLVMContext &C,
                                               ArrayRef<unsigned> ArgNos,
                                               Attribute A) const {
  assert(llvm::is_sorted(ArgNos));

  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
  if (MaxIndex >= AttrSets.size())
    AttrSets.resize(MaxIndex + 1);

  for (unsigned ArgNo : ArgNos) {
    unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
    AttrBuilder B(C, AttrSets[Index]);
    B.addAttribute(A);
    AttrSets[Index] = AttributeSet::get(C, B);
  }

  return getImpl(C, AttrSets);
}

AttributeList
AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
                                      Attribute::AttrKind Kind) const {
  AttributeSet Attrs = getAttributes(Index);
  AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
  if (Attrs == NewAttrs)
    return *this;
  return setAttributesAtIndex(C, Index, NewAttrs);
}

AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
                                                    unsigned Index,
                                                    StringRef Kind) const {
  AttributeSet Attrs = getAttributes(Index);
  AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
  if (Attrs == NewAttrs)
    return *this;
  return setAttributesAtIndex(C, Index, NewAttrs);
}

AttributeList AttributeList::removeAttributesAtIndex(
    LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
  AttributeSet Attrs = getAttributes(Index);
  AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
  // If nothing was removed, return the original list.
  if (Attrs == NewAttrs)
    return *this;
  return setAttributesAtIndex(C, Index, NewAttrs);
}

AttributeList
AttributeList::removeAttributesAtIndex(LLVMContext &C,
                                       unsigned WithoutIndex) const {
  if (!pImpl)
    return {};
  if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
    return *this;
  return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
}

AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
                                                       uint64_t Bytes) const {
  AttrBuilder B(C);
  B.addDereferenceableAttr(Bytes);
  return addRetAttributes(C, B);
}

AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
                                                         unsigned Index,
                                                         uint64_t Bytes) const {
  AttrBuilder B(C);
  B.addDereferenceableAttr(Bytes);
  return addParamAttributes(C, Index, B);
}

AttributeList
AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
                                                 uint64_t Bytes) const {
  AttrBuilder B(C);
  B.addDereferenceableOrNullAttr(Bytes);
  return addParamAttributes(C, Index, B);
}

AttributeList AttributeList::addAllocSizeParamAttr(
    LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
    const std::optional<unsigned> &NumElemsArg) {
  AttrBuilder B(C);
  B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
  return addParamAttributes(C, Index, B);
}

//===----------------------------------------------------------------------===//
// AttributeList Accessor Methods
//===----------------------------------------------------------------------===//

AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
  return getAttributes(ArgNo + FirstArgIndex);
}

AttributeSet AttributeList::getRetAttrs() const {
  return getAttributes(ReturnIndex);
}

AttributeSet AttributeList::getFnAttrs() const {
  return getAttributes(FunctionIndex);
}

bool AttributeList::hasAttributeAtIndex(unsigned Index,
                                        Attribute::AttrKind Kind) const {
  return getAttributes(Index).hasAttribute(Kind);
}

bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
  return getAttributes(Index).hasAttribute(Kind);
}

bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
  return getAttributes(Index).hasAttributes();
}

bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
  return pImpl && pImpl->hasFnAttribute(Kind);
}

bool AttributeList::hasFnAttr(StringRef Kind) const {
  return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
}

bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
                                     unsigned *Index) const {
  return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
}

Attribute AttributeList::getAttributeAtIndex(unsigned Index,
                                             Attribute::AttrKind Kind) const {
  return getAttributes(Index).getAttribute(Kind);
}

Attribute AttributeList::getAttributeAtIndex(unsigned Index,
                                             StringRef Kind) const {
  return getAttributes(Index).getAttribute(Kind);
}

MaybeAlign AttributeList::getRetAlignment() const {
  return getAttributes(ReturnIndex).getAlignment();
}

MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
  return getAttributes(ArgNo + FirstArgIndex).getAlignment();
}

MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
  return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
}

Type *AttributeList::getParamByValType(unsigned Index) const {
  return getAttributes(Index+FirstArgIndex).getByValType();
}

Type *AttributeList::getParamStructRetType(unsigned Index) const {
  return getAttributes(Index + FirstArgIndex).getStructRetType();
}

Type *AttributeList::getParamByRefType(unsigned Index) const {
  return getAttributes(Index + FirstArgIndex).getByRefType();
}

Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
  return getAttributes(Index + FirstArgIndex).getPreallocatedType();
}

Type *AttributeList::getParamInAllocaType(unsigned Index) const {
  return getAttributes(Index + FirstArgIndex).getInAllocaType();
}

Type *AttributeList::getParamElementType(unsigned Index) const {
  return getAttributes(Index + FirstArgIndex).getElementType();
}

MaybeAlign AttributeList::getFnStackAlignment() const {
  return getFnAttrs().getStackAlignment();
}

MaybeAlign AttributeList::getRetStackAlignment() const {
  return getRetAttrs().getStackAlignment();
}

uint64_t AttributeList::getRetDereferenceableBytes() const {
  return getRetAttrs().getDereferenceableBytes();
}

uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
  return getParamAttrs(Index).getDereferenceableBytes();
}

uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
  return getRetAttrs().getDereferenceableOrNullBytes();
}

uint64_t
AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
  return getParamAttrs(Index).getDereferenceableOrNullBytes();
}

UWTableKind AttributeList::getUWTableKind() const {
  return getFnAttrs().getUWTableKind();
}

AllocFnKind AttributeList::getAllocKind() const {
  return getFnAttrs().getAllocKind();
}

MemoryEffects AttributeList::getMemoryEffects() const {
  return getFnAttrs().getMemoryEffects();
}

std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
  return getAttributes(Index).getAsString(InAttrGrp);
}

AttributeSet AttributeList::getAttributes(unsigned Index) const {
  Index = attrIdxToArrayIdx(Index);
  if (!pImpl || Index >= getNumAttrSets())
    return {};
  return pImpl->begin()[Index];
}

bool AttributeList::hasParentContext(LLVMContext &C) const {
  assert(!isEmpty() && "an empty attribute list has no parent context");
  FoldingSetNodeID ID;
  pImpl->Profile(ID);
  void *Unused;
  return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
}

AttributeList::iterator AttributeList::begin() const {
  return pImpl ? pImpl->begin() : nullptr;
}

AttributeList::iterator AttributeList::end() const {
  return pImpl ? pImpl->end() : nullptr;
}

//===----------------------------------------------------------------------===//
// AttributeList Introspection Methods
//===----------------------------------------------------------------------===//

unsigned AttributeList::getNumAttrSets() const {
  return pImpl ? pImpl->NumAttrSets : 0;
}

void AttributeList::print(raw_ostream &O) const {
  O << "AttributeList[\n";

  for (unsigned i : indexes()) {
    if (!getAttributes(i).hasAttributes())
      continue;
    O << "  { ";
    switch (i) {
    case AttrIndex::ReturnIndex:
      O << "return";
      break;
    case AttrIndex::FunctionIndex:
      O << "function";
      break;
    default:
      O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
    }
    O << " => " << getAsString(i) << " }\n";
  }

  O << "]\n";
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
#endif

//===----------------------------------------------------------------------===//
// AttrBuilder Method Implementations
//===----------------------------------------------------------------------===//

AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
  append_range(Attrs, AS);
  assert(is_sorted(Attrs) && "AttributeSet should be sorted");
}

void AttrBuilder::clear() { Attrs.clear(); }

/// Attribute comparator that only compares attribute keys. Enum attributes are
/// sorted before string attributes.
struct AttributeComparator {
  bool operator()(Attribute A0, Attribute A1) const {
    bool A0IsString = A0.isStringAttribute();
    bool A1IsString = A1.isStringAttribute();
    if (A0IsString) {
      if (A1IsString)
        return A0.getKindAsString() < A1.getKindAsString();
      else
        return false;
    }
    if (A1IsString)
      return true;
    return A0.getKindAsEnum() < A1.getKindAsEnum();
  }
  bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
    if (A0.isStringAttribute())
      return false;
    return A0.getKindAsEnum() < Kind;
  }
  bool operator()(Attribute A0, StringRef Kind) const {
    if (A0.isStringAttribute())
      return A0.getKindAsString() < Kind;
    return true;
  }
};

template <typename K>
static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
                             Attribute Attr) {
  auto It = lower_bound(Attrs, Kind, AttributeComparator());
  if (It != Attrs.end() && It->hasAttribute(Kind))
    std::swap(*It, Attr);
  else
    Attrs.insert(It, Attr);
}

AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
  if (Attr.isStringAttribute())
    addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
  else
    addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
  return *this;
}

AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
  addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
  return *this;
}

AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
  addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
  return *this;
}

AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
  assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
  auto It = lower_bound(Attrs, Val, AttributeComparator());
  if (It != Attrs.end() && It->hasAttribute(Val))
    Attrs.erase(It);
  return *this;
}

AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
  auto It = lower_bound(Attrs, A, AttributeComparator());
  if (It != Attrs.end() && It->hasAttribute(A))
    Attrs.erase(It);
  return *this;
}

std::optional<uint64_t>
AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
  assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
  Attribute A = getAttribute(Kind);
  if (A.isValid())
    return A.getValueAsInt();
  return std::nullopt;
}

AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
                                        uint64_t Value) {
  return addAttribute(Attribute::get(Ctx, Kind, Value));
}

std::optional<std::pair<unsigned, std::optional<unsigned>>>
AttrBuilder::getAllocSizeArgs() const {
  Attribute A = getAttribute(Attribute::AllocSize);
  if (A.isValid())
    return A.getAllocSizeArgs();
  return std::nullopt;
}

AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
  if (!Align)
    return *this;

  assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
  return addRawIntAttr(Attribute::Alignment, Align->value());
}

AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
  // Default alignment, allow the target to define how to align it.
  if (!Align)
    return *this;

  assert(*Align <= 0x100 && "Alignment too large.");
  return addRawIntAttr(Attribute::StackAlignment, Align->value());
}

AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
  if (Bytes == 0) return *this;

  return addRawIntAttr(Attribute::Dereferenceable, Bytes);
}

AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
  if (Bytes == 0)
    return *this;

  return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
}

AttrBuilder &
AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
                              const std::optional<unsigned> &NumElems) {
  return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
}

AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
  // (0, 0) is our "not present" value, so we need to check for it here.
  assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
  return addRawIntAttr(Attribute::AllocSize, RawArgs);
}

AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
                                             std::optional<unsigned> MaxValue) {
  return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
}

AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
  // (0, 0) is not present hence ignore this case
  if (RawArgs == 0)
    return *this;

  return addRawIntAttr(Attribute::VScaleRange, RawArgs);
}

AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
  if (Kind == UWTableKind::None)
    return *this;
  return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
}

AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
  return addRawIntAttr(Attribute::Memory, ME.toIntValue());
}

AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
  return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
}

Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
  assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
  Attribute A = getAttribute(Kind);
  return A.isValid() ? A.getValueAsType() : nullptr;
}

AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
  return addAttribute(Attribute::get(Ctx, Kind, Ty));
}

AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
  return addTypeAttr(Attribute::ByVal, Ty);
}

AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
  return addTypeAttr(Attribute::StructRet, Ty);
}

AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
  return addTypeAttr(Attribute::ByRef, Ty);
}

AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
  return addTypeAttr(Attribute::Preallocated, Ty);
}

AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
  return addTypeAttr(Attribute::InAlloca, Ty);
}

AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
  // TODO: Could make this O(n) as we're merging two sorted lists.
  for (const auto &I : B.attrs())
    addAttribute(I);

  return *this;
}

AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
  erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
  return *this;
}

bool AttrBuilder::overlaps(const AttributeMask &AM) const {
  return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
}

Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
  assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
  auto It = lower_bound(Attrs, A, AttributeComparator());
  if (It != Attrs.end() && It->hasAttribute(A))
    return *It;
  return {};
}

Attribute AttrBuilder::getAttribute(StringRef A) const {
  auto It = lower_bound(Attrs, A, AttributeComparator());
  if (It != Attrs.end() && It->hasAttribute(A))
    return *It;
  return {};
}

bool AttrBuilder::contains(Attribute::AttrKind A) const {
  return getAttribute(A).isValid();
}

bool AttrBuilder::contains(StringRef A) const {
  return getAttribute(A).isValid();
}

bool AttrBuilder::operator==(const AttrBuilder &B) const {
  return Attrs == B.Attrs;
}

//===----------------------------------------------------------------------===//
// AttributeFuncs Function Defintions
//===----------------------------------------------------------------------===//

/// Which attributes cannot be applied to a type.
AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
                                               AttributeSafetyKind ASK) {
  AttributeMask Incompatible;

  if (!Ty->isIntegerTy()) {
    // Attributes that only apply to integers.
    if (ASK & ASK_SAFE_TO_DROP)
      Incompatible.addAttribute(Attribute::AllocAlign);
    if (ASK & ASK_UNSAFE_TO_DROP)
      Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
  }

  if (!Ty->isPointerTy()) {
    // Attributes that only apply to pointers.
    if (ASK & ASK_SAFE_TO_DROP)
      Incompatible.addAttribute(Attribute::NoAlias)
          .addAttribute(Attribute::NoCapture)
          .addAttribute(Attribute::NonNull)
          .addAttribute(Attribute::ReadNone)
          .addAttribute(Attribute::ReadOnly)
          .addAttribute(Attribute::Dereferenceable)
          .addAttribute(Attribute::DereferenceableOrNull);
    if (ASK & ASK_UNSAFE_TO_DROP)
      Incompatible.addAttribute(Attribute::Nest)
          .addAttribute(Attribute::SwiftError)
          .addAttribute(Attribute::Preallocated)
          .addAttribute(Attribute::InAlloca)
          .addAttribute(Attribute::ByVal)
          .addAttribute(Attribute::StructRet)
          .addAttribute(Attribute::ByRef)
          .addAttribute(Attribute::ElementType)
          .addAttribute(Attribute::AllocatedPointer);
  }

    // Attributes that only apply to pointers or vectors of pointers.
  if (!Ty->isPtrOrPtrVectorTy()) {
    if (ASK & ASK_SAFE_TO_DROP)
      Incompatible.addAttribute(Attribute::Alignment);
  }

  // Some attributes can apply to all "values" but there are no `void` values.
  if (Ty->isVoidTy()) {
    if (ASK & ASK_SAFE_TO_DROP)
      Incompatible.addAttribute(Attribute::NoUndef);
  }

  return Incompatible;
}

AttributeMask AttributeFuncs::getUBImplyingAttributes() {
  AttributeMask AM;
  AM.addAttribute(Attribute::NoUndef);
  AM.addAttribute(Attribute::Dereferenceable);
  AM.addAttribute(Attribute::DereferenceableOrNull);
  return AM;
}

template<typename AttrClass>
static bool isEqual(const Function &Caller, const Function &Callee) {
  return Caller.getFnAttribute(AttrClass::getKind()) ==
         Callee.getFnAttribute(AttrClass::getKind());
}

/// Compute the logical AND of the attributes of the caller and the
/// callee.
///
/// This function sets the caller's attribute to false if the callee's attribute
/// is false.
template<typename AttrClass>
static void setAND(Function &Caller, const Function &Callee) {
  if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
      !AttrClass::isSet(Callee, AttrClass::getKind()))
    AttrClass::set(Caller, AttrClass::getKind(), false);
}

/// Compute the logical OR of the attributes of the caller and the
/// callee.
///
/// This function sets the caller's attribute to true if the callee's attribute
/// is true.
template<typename AttrClass>
static void setOR(Function &Caller, const Function &Callee) {
  if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
      AttrClass::isSet(Callee, AttrClass::getKind()))
    AttrClass::set(Caller, AttrClass::getKind(), true);
}

/// If the inlined function had a higher stack protection level than the
/// calling function, then bump up the caller's stack protection level.
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
  // If the calling function has *no* stack protection level (e.g. it was built
  // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
  // change it as that could change the program's semantics.
  if (!Caller.hasStackProtectorFnAttr())
    return;

  // If upgrading the SSP attribute, clear out the old SSP Attributes first.
  // Having multiple SSP attributes doesn't actually hurt, but it adds useless
  // clutter to the IR.
  AttributeMask OldSSPAttr;
  OldSSPAttr.addAttribute(Attribute::StackProtect)
      .addAttribute(Attribute::StackProtectStrong)
      .addAttribute(Attribute::StackProtectReq);

  if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
    Caller.removeFnAttrs(OldSSPAttr);
    Caller.addFnAttr(Attribute::StackProtectReq);
  } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
             !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
    Caller.removeFnAttrs(OldSSPAttr);
    Caller.addFnAttr(Attribute::StackProtectStrong);
  } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
             !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
             !Caller.hasFnAttribute(Attribute::StackProtectStrong))
    Caller.addFnAttr(Attribute::StackProtect);
}

/// If the inlined function required stack probes, then ensure that
/// the calling function has those too.
static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
  if (!Caller.hasFnAttribute("probe-stack") &&
      Callee.hasFnAttribute("probe-stack")) {
    Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
  }
}

/// If the inlined function defines the size of guard region
/// on the stack, then ensure that the calling function defines a guard region
/// that is no larger.
static void
adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
  Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
  if (CalleeAttr.isValid()) {
    Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
    if (CallerAttr.isValid()) {
      uint64_t CallerStackProbeSize, CalleeStackProbeSize;
      CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
      CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);

      if (CallerStackProbeSize > CalleeStackProbeSize) {
        Caller.addFnAttr(CalleeAttr);
      }
    } else {
      Caller.addFnAttr(CalleeAttr);
    }
  }
}

/// If the inlined function defines a min legal vector width, then ensure
/// the calling function has the same or larger min legal vector width. If the
/// caller has the attribute, but the callee doesn't, we need to remove the
/// attribute from the caller since we can't make any guarantees about the
/// caller's requirements.
/// This function is called after the inlining decision has been made so we have
/// to merge the attribute this way. Heuristics that would use
/// min-legal-vector-width to determine inline compatibility would need to be
/// handled as part of inline cost analysis.
static void
adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
  Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
  if (CallerAttr.isValid()) {
    Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
    if (CalleeAttr.isValid()) {
      uint64_t CallerVectorWidth, CalleeVectorWidth;
      CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
      CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
      if (CallerVectorWidth < CalleeVectorWidth)
        Caller.addFnAttr(CalleeAttr);
    } else {
      // If the callee doesn't have the attribute then we don't know anything
      // and must drop the attribute from the caller.
      Caller.removeFnAttr("min-legal-vector-width");
    }
  }
}

/// If the inlined function has null_pointer_is_valid attribute,
/// set this attribute in the caller post inlining.
static void
adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
  if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
    Caller.addFnAttr(Attribute::NullPointerIsValid);
  }
}

struct EnumAttr {
  static bool isSet(const Function &Fn,
                    Attribute::AttrKind Kind) {
    return Fn.hasFnAttribute(Kind);
  }

  static void set(Function &Fn,
                  Attribute::AttrKind Kind, bool Val) {
    if (Val)
      Fn.addFnAttr(Kind);
    else
      Fn.removeFnAttr(Kind);
  }
};

struct StrBoolAttr {
  static bool isSet(const Function &Fn,
                    StringRef Kind) {
    auto A = Fn.getFnAttribute(Kind);
    return A.getValueAsString().equals("true");
  }

  static void set(Function &Fn,
                  StringRef Kind, bool Val) {
    Fn.addFnAttr(Kind, Val ? "true" : "false");
  }
};

#define GET_ATTR_NAMES
#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)                                \
  struct ENUM_NAME##Attr : EnumAttr {                                          \
    static enum Attribute::AttrKind getKind() {                                \
      return llvm::Attribute::ENUM_NAME;                                       \
    }                                                                          \
  };
#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME)                             \
  struct ENUM_NAME##Attr : StrBoolAttr {                                       \
    static StringRef getKind() { return #DISPLAY_NAME; }                       \
  };
#include "llvm/IR/Attributes.inc"

#define GET_ATTR_COMPAT_FUNC
#include "llvm/IR/Attributes.inc"

bool AttributeFuncs::areInlineCompatible(const Function &Caller,
                                         const Function &Callee) {
  return hasCompatibleFnAttrs(Caller, Callee);
}

bool AttributeFuncs::areOutlineCompatible(const Function &A,
                                          const Function &B) {
  return hasCompatibleFnAttrs(A, B);
}

void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
                                                const Function &Callee) {
  mergeFnAttrs(Caller, Callee);
}

void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
                                                const Function &ToMerge) {

  // We merge functions so that they meet the most general case.
  // For example, if the NoNansFPMathAttr is set in one function, but not in
  // the other, in the merged function we can say that the NoNansFPMathAttr
  // is not set.
  // However if we have the SpeculativeLoadHardeningAttr set true in one
  // function, but not the other, we make sure that the function retains
  // that aspect in the merged function.
  mergeFnAttrs(Base, ToMerge);
}

void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
                                                   uint64_t Width) {
  Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
  if (Attr.isValid()) {
    uint64_t OldWidth;
    Attr.getValueAsString().getAsInteger(0, OldWidth);
    if (Width > OldWidth)
      Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
  }
}
