//===- Attributes.cpp - Implement AttributesList --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// \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/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.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/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <limits>
#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 Optional<unsigned> &NumElemsArg) {
  assert((!NumElemsArg.hasValue() ||
          *NumElemsArg != AllocSizeNumElemsNotPresent) &&
         "Attempting to pack a reserved value");

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

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

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

Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
                         uint64_t Val) {
  LLVMContextImpl *pImpl = Context.pImpl;
  FoldingSetNodeID ID;
  ID.AddInteger(Kind);
  if (Val) ID.AddInteger(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.
    if (!Val)
      PA = new EnumAttributeImpl(Kind);
    else
      PA = new 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.
    PA = new StringAttributeImpl(Kind, Val);
    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
  }

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

Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {
  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
  assert(Align <= 0x40000000 && "Alignment too large.");
  return get(Context, Alignment, Align);
}

Attribute Attribute::getWithStackAlignment(LLVMContext &Context,
                                           uint64_t Align) {
  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
  assert(Align <= 0x100 && "Alignment too large.");
  return get(Context, StackAlignment, Align);
}

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::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
                                const Optional<unsigned> &NumElemsArg) {
  assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
         "Invalid allocsize arguments -- given allocsize(0, 0)");
  return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
}

//===----------------------------------------------------------------------===//
// 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();
}

Attribute::AttrKind Attribute::getKindAsEnum() const {
  if (!pImpl) return None;
  assert((isEnumAttribute() || isIntAttribute()) &&
         "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();
}

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();
}

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);
}

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

unsigned Attribute::getStackAlignment() const {
  assert(hasAttribute(Attribute::StackAlignment) &&
         "Trying to get alignment from non-alignment attribute!");
  return 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, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
  assert(hasAttribute(Attribute::AllocSize) &&
         "Trying to get allocsize args from non-allocsize attribute");
  return unpackAllocSizeArgs(pImpl->getValueAsInt());
}

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

  if (hasAttribute(Attribute::SanitizeAddress))
    return "sanitize_address";
  if (hasAttribute(Attribute::SanitizeHWAddress))
    return "sanitize_hwaddress";
  if (hasAttribute(Attribute::AlwaysInline))
    return "alwaysinline";
  if (hasAttribute(Attribute::ArgMemOnly))
    return "argmemonly";
  if (hasAttribute(Attribute::Builtin))
    return "builtin";
  if (hasAttribute(Attribute::ByVal))
    return "byval";
  if (hasAttribute(Attribute::Convergent))
    return "convergent";
  if (hasAttribute(Attribute::SwiftError))
    return "swifterror";
  if (hasAttribute(Attribute::SwiftSelf))
    return "swiftself";
  if (hasAttribute(Attribute::InaccessibleMemOnly))
    return "inaccessiblememonly";
  if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
    return "inaccessiblemem_or_argmemonly";
  if (hasAttribute(Attribute::InAlloca))
    return "inalloca";
  if (hasAttribute(Attribute::InlineHint))
    return "inlinehint";
  if (hasAttribute(Attribute::InReg))
    return "inreg";
  if (hasAttribute(Attribute::JumpTable))
    return "jumptable";
  if (hasAttribute(Attribute::MinSize))
    return "minsize";
  if (hasAttribute(Attribute::Naked))
    return "naked";
  if (hasAttribute(Attribute::Nest))
    return "nest";
  if (hasAttribute(Attribute::NoAlias))
    return "noalias";
  if (hasAttribute(Attribute::NoBuiltin))
    return "nobuiltin";
  if (hasAttribute(Attribute::NoCapture))
    return "nocapture";
  if (hasAttribute(Attribute::NoDuplicate))
    return "noduplicate";
  if (hasAttribute(Attribute::NoImplicitFloat))
    return "noimplicitfloat";
  if (hasAttribute(Attribute::NoInline))
    return "noinline";
  if (hasAttribute(Attribute::NonLazyBind))
    return "nonlazybind";
  if (hasAttribute(Attribute::NonNull))
    return "nonnull";
  if (hasAttribute(Attribute::NoRedZone))
    return "noredzone";
  if (hasAttribute(Attribute::NoReturn))
    return "noreturn";
  if (hasAttribute(Attribute::NoCfCheck))
    return "nocf_check";
  if (hasAttribute(Attribute::NoRecurse))
    return "norecurse";
  if (hasAttribute(Attribute::NoUnwind))
    return "nounwind";
  if (hasAttribute(Attribute::OptForFuzzing))
    return "optforfuzzing";
  if (hasAttribute(Attribute::OptimizeNone))
    return "optnone";
  if (hasAttribute(Attribute::OptimizeForSize))
    return "optsize";
  if (hasAttribute(Attribute::ReadNone))
    return "readnone";
  if (hasAttribute(Attribute::ReadOnly))
    return "readonly";
  if (hasAttribute(Attribute::WriteOnly))
    return "writeonly";
  if (hasAttribute(Attribute::Returned))
    return "returned";
  if (hasAttribute(Attribute::ReturnsTwice))
    return "returns_twice";
  if (hasAttribute(Attribute::SExt))
    return "signext";
  if (hasAttribute(Attribute::Speculatable))
    return "speculatable";
  if (hasAttribute(Attribute::StackProtect))
    return "ssp";
  if (hasAttribute(Attribute::StackProtectReq))
    return "sspreq";
  if (hasAttribute(Attribute::StackProtectStrong))
    return "sspstrong";
  if (hasAttribute(Attribute::SafeStack))
    return "safestack";
  if (hasAttribute(Attribute::ShadowCallStack))
    return "shadowcallstack";
  if (hasAttribute(Attribute::StrictFP))
    return "strictfp";
  if (hasAttribute(Attribute::StructRet))
    return "sret";
  if (hasAttribute(Attribute::SanitizeThread))
    return "sanitize_thread";
  if (hasAttribute(Attribute::SanitizeMemory))
    return "sanitize_memory";
  if (hasAttribute(Attribute::UWTable))
    return "uwtable";
  if (hasAttribute(Attribute::ZExt))
    return "zeroext";
  if (hasAttribute(Attribute::Cold))
    return "cold";

  // FIXME: These should be output like this:
  //
  //   align=4
  //   alignstack=8
  //
  if (hasAttribute(Attribute::Alignment)) {
    std::string Result;
    Result += "align";
    Result += (InAttrGrp) ? "=" : " ";
    Result += utostr(getValueAsInt());
    return Result;
  }

  auto AttrWithBytesToString = [&](const char *Name) {
    std::string Result;
    Result += Name;
    if (InAttrGrp) {
      Result += "=";
      Result += utostr(getValueAsInt());
    } else {
      Result += "(";
      Result += utostr(getValueAsInt());
      Result += ")";
    }
    return Result;
  };

  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;
    Optional<unsigned> NumElems;
    std::tie(ElemSize, NumElems) = getAllocSizeArgs();

    std::string Result = "allocsize(";
    Result += utostr(ElemSize);
    if (NumElems.hasValue()) {
      Result += ',';
      Result += utostr(*NumElems);
    }
    Result += ')';
    return Result;
  }

  // Convert target-dependent attributes to strings of the form:
  //
  //   "kind"
  //   "kind" = "value"
  //
  if (isStringAttribute()) {
    std::string Result;
    Result += (Twine('"') + getKindAsString() + Twine('"')).str();

    std::string AttrVal = pImpl->getValueAsString();
    if (AttrVal.empty()) return Result;

    // 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"
    {
      raw_string_ostream OS(Result);
      OS << "=\"";
      printEscapedString(AttrVal, OS);
      OS << "\"";
    }
    return Result;
  }

  llvm_unreachable("Unknown attribute");
}

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;
}

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

// Pin the vtables to this file.
AttributeImpl::~AttributeImpl() = default;

void EnumAttributeImpl::anchor() {}

void IntAttributeImpl::anchor() {}

void StringAttributeImpl::anchor() {}

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());
  return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
}

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

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();
}

bool AttributeImpl::operator<(const AttributeImpl &AI) const {
  // This sorts the attributes with Attribute::AttrKinds coming first (sorted
  // relative to their enum value) and then strings.
  if (isEnumAttribute()) {
    if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
    if (AI.isIntAttribute()) return true;
    if (AI.isStringAttribute()) return true;
  }

  if (isIntAttribute()) {
    if (AI.isEnumAttribute()) return false;
    if (AI.isIntAttribute()) {
      if (getKindAsEnum() == AI.getKindAsEnum())
        return getValueAsInt() < AI.getValueAsInt();
      return getKindAsEnum() < AI.getKindAsEnum();
    }
    if (AI.isStringAttribute()) return true;
  }

  if (AI.isEnumAttribute()) return false;
  if (AI.isIntAttribute()) 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;
  B.addAttribute(Kind);
  return addAttributes(C, AttributeSet::get(C, B));
}

AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
                                        StringRef Value) const {
  AttrBuilder B;
  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(AS);
  for (const auto I : *this)
    B.addAttribute(I);

 return get(C, B);
}

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

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

AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
                                              const AttrBuilder &Attrs) const {
  AttrBuilder B(*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();
}

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

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

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

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

std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
  return SetNode ? SetNode->getAllocSizeArgs()
                 : std::pair<unsigned, Optional<unsigned>>(0, 0);
}

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

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)
    : AvailableAttrs(0), NumAttrs(Attrs.size()) {
  // There's memory after the node where we can store the entries in.
  std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>());

  for (const auto I : *this) {
    if (!I.isStringAttribute()) {
      AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
    }
  }
}

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

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

  SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
  llvm::sort(SortedAttrs.begin(), SortedAttrs.end());

  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) {
  // Add target-independent attributes.
  SmallVector<Attribute, 8> Attrs;
  for (Attribute::AttrKind Kind = Attribute::None;
       Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
    if (!B.contains(Kind))
      continue;

    Attribute Attr;
    switch (Kind) {
    case Attribute::Alignment:
      Attr = Attribute::getWithAlignment(C, B.getAlignment());
      break;
    case Attribute::StackAlignment:
      Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment());
      break;
    case Attribute::Dereferenceable:
      Attr = Attribute::getWithDereferenceableBytes(
          C, B.getDereferenceableBytes());
      break;
    case Attribute::DereferenceableOrNull:
      Attr = Attribute::getWithDereferenceableOrNullBytes(
          C, B.getDereferenceableOrNullBytes());
      break;
    case Attribute::AllocSize: {
      auto A = B.getAllocSizeArgs();
      Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
      break;
    }
    default:
      Attr = Attribute::get(C, Kind);
    }
    Attrs.push_back(Attr);
  }

  // Add target-dependent (string) attributes.
  for (const auto &TDA : B.td_attrs())
    Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));

  return get(C, Attrs);
}

bool AttributeSetNode::hasAttribute(StringRef Kind) const {
  for (const auto I : *this)
    if (I.hasAttribute(Kind))
      return true;
  return false;
}

Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
  if (hasAttribute(Kind)) {
    for (const auto I : *this)
      if (I.hasAttribute(Kind))
        return I;
  }
  return {};
}

Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
  for (const auto I : *this)
    if (I.hasAttribute(Kind))
      return I;
  return {};
}

unsigned AttributeSetNode::getAlignment() const {
  for (const auto I : *this)
    if (I.hasAttribute(Attribute::Alignment))
      return I.getAlignment();
  return 0;
}

unsigned AttributeSetNode::getStackAlignment() const {
  for (const auto I : *this)
    if (I.hasAttribute(Attribute::StackAlignment))
      return I.getStackAlignment();
  return 0;
}

uint64_t AttributeSetNode::getDereferenceableBytes() const {
  for (const auto I : *this)
    if (I.hasAttribute(Attribute::Dereferenceable))
      return I.getDereferenceableBytes();
  return 0;
}

uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
  for (const auto I : *this)
    if (I.hasAttribute(Attribute::DereferenceableOrNull))
      return I.getDereferenceableOrNullBytes();
  return 0;
}

std::pair<unsigned, Optional<unsigned>>
AttributeSetNode::getAllocSizeArgs() const {
  for (const auto I : *this)
    if (I.hasAttribute(Attribute::AllocSize))
      return I.getAllocSizeArgs();
  return std::make_pair(0, 0);
}

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, but it relies on unsigned integer wrapping. MSVC warns about
/// unsigned wrapping in constexpr functions, so write out the conditional. LLVM
/// folds it to add anyway.
static constexpr unsigned attrIdxToArrayIdx(unsigned Index) {
  return Index == AttributeList::FunctionIndex ? 0 : Index + 1;
}

AttributeListImpl::AttributeListImpl(LLVMContext &C,
                                     ArrayRef<AttributeSet> Sets)
    : AvailableFunctionAttrs(0), Context(C), NumAttrSets(Sets.size()) {
  assert(!Sets.empty() && "pointless AttributeListImpl");

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

  // Initialize AvailableFunctionAttrs summary bitset.
  static_assert(Attribute::EndAttrKinds <=
                    sizeof(AvailableFunctionAttrs) * CHAR_BIT,
                "Too many attributes");
  static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
                "function should be stored in slot 0");
  for (const auto I : Sets[0]) {
    if (!I.isStringAttribute())
      AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum();
  }
}

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

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

#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 = ::operator new(
        AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()));
    PA = new (Mem) AttributeListImpl(C, 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(std::is_sorted(Attrs.begin(), Attrs.end(),
                        [](const std::pair<unsigned, Attribute> &LHS,
                           const std::pair<unsigned, Attribute> &RHS) {
                          return LHS.first < RHS.first;
                        }) && "Misordered Attributes list!");
  assert(llvm::none_of(Attrs,
                       [](const std::pair<unsigned, Attribute> &Pair) {
                         return Pair.second.hasAttribute(Attribute::None);
                       }) &&
         "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(std::is_sorted(Attrs.begin(), Attrs.end(),
                        [](const std::pair<unsigned, AttributeSet> &LHS,
                           const std::pair<unsigned, AttributeSet> &RHS) {
                          return LHS.first < RHS.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);
    AttrSets.insert(AttrSets.end(), ArgAttrs.begin(), ArgAttrs.end());
  }

  return getImpl(C, AttrSets);
}

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

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<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;
    for (const auto List : Attrs)
      CurBuilder.merge(List.getAttributes(I - 1));
    NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
  }

  return getImpl(C, NewAttrSets);
}

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

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

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

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

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

#ifndef NDEBUG
  // FIXME it is not obvious how this should work for alignment. For now, say
  // we can't change a known alignment.
  unsigned OldAlign = getAttributes(Index).getAlignment();
  unsigned NewAlign = B.getAlignment();
  assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
         "Attempt to change alignment!");
#endif

  Index = attrIdxToArrayIdx(Index);
  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  if (Index >= AttrSets.size())
    AttrSets.resize(Index + 1);

  AttrBuilder Merged(AttrSets[Index]);
  Merged.merge(B);
  AttrSets[Index] = AttributeSet::get(C, Merged);

  return getImpl(C, AttrSets);
}

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

  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(AttrSets[Index]);
    B.addAttribute(A);
    AttrSets[Index] = AttributeSet::get(C, B);
  }

  return getImpl(C, AttrSets);
}

AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
                                             Attribute::AttrKind Kind) const {
  if (!hasAttribute(Index, Kind)) return *this;

  Index = attrIdxToArrayIdx(Index);
  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  assert(Index < AttrSets.size());

  AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);

  return getImpl(C, AttrSets);
}

AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
                                             StringRef Kind) const {
  if (!hasAttribute(Index, Kind)) return *this;

  Index = attrIdxToArrayIdx(Index);
  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  assert(Index < AttrSets.size());

  AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);

  return getImpl(C, AttrSets);
}

AttributeList
AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
                                const AttrBuilder &AttrsToRemove) const {
  if (!pImpl)
    return {};

  Index = attrIdxToArrayIdx(Index);
  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  if (Index >= AttrSets.size())
    AttrSets.resize(Index + 1);

  AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);

  return getImpl(C, AttrSets);
}

AttributeList AttributeList::removeAttributes(LLVMContext &C,
                                              unsigned WithoutIndex) const {
  if (!pImpl)
    return {};
  WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
  if (WithoutIndex >= getNumAttrSets())
    return *this;
  SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
  AttrSets[WithoutIndex] = AttributeSet();
  return getImpl(C, AttrSets);
}

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

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

AttributeList
AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
                                unsigned ElemSizeArg,
                                const Optional<unsigned> &NumElemsArg) {
  AttrBuilder B;
  B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
  return addAttributes(C, Index, B);
}

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

LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); }

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

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

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

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

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

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

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

bool AttributeList::hasFnAttribute(StringRef Kind) const {
  return hasAttribute(AttributeList::FunctionIndex, Kind);
}

bool AttributeList::hasParamAttribute(unsigned ArgNo,
                                      Attribute::AttrKind Kind) const {
  return hasAttribute(ArgNo + FirstArgIndex, Kind);
}

bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
                                     unsigned *Index) const {
  if (!pImpl) return false;

  for (unsigned I = index_begin(), E = index_end(); I != E; ++I) {
    if (hasAttribute(I, Attr)) {
      if (Index)
        *Index = I;
      return true;
    }
  }

  return false;
}

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

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

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

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

unsigned AttributeList::getStackAlignment(unsigned Index) const {
  return getAttributes(Index).getStackAlignment();
}

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

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

std::pair<unsigned, Optional<unsigned>>
AttributeList::getAllocSizeArgs(unsigned Index) const {
  return getAttributes(Index).getAllocSizeArgs();
}

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];
}

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;
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void AttributeList::dump() const {
  dbgs() << "PAL[\n";

  for (unsigned i = index_begin(), e = index_end(); i != e; ++i) {
    if (getAttributes(i).hasAttributes())
      dbgs() << "  { " << i << " => " << getAsString(i) << " }\n";
  }

  dbgs() << "]\n";
}
#endif

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

// FIXME: Remove this ctor, use AttributeSet.
AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
  AttributeSet AS = AL.getAttributes(Index);
  for (const auto &A : AS)
    addAttribute(A);
}

AttrBuilder::AttrBuilder(AttributeSet AS) {
  for (const auto &A : AS)
    addAttribute(A);
}

void AttrBuilder::clear() {
  Attrs.reset();
  TargetDepAttrs.clear();
  Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
  AllocSizeArgs = 0;
}

AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
  assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
  assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
         Val != Attribute::Dereferenceable && Val != Attribute::AllocSize &&
         "Adding integer attribute without adding a value!");
  Attrs[Val] = true;
  return *this;
}

AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
  if (Attr.isStringAttribute()) {
    addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
    return *this;
  }

  Attribute::AttrKind Kind = Attr.getKindAsEnum();
  Attrs[Kind] = true;

  if (Kind == Attribute::Alignment)
    Alignment = Attr.getAlignment();
  else if (Kind == Attribute::StackAlignment)
    StackAlignment = Attr.getStackAlignment();
  else if (Kind == Attribute::Dereferenceable)
    DerefBytes = Attr.getDereferenceableBytes();
  else if (Kind == Attribute::DereferenceableOrNull)
    DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
  else if (Kind == Attribute::AllocSize)
    AllocSizeArgs = Attr.getValueAsInt();
  return *this;
}

AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
  TargetDepAttrs[A] = V;
  return *this;
}

AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
  assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
  Attrs[Val] = false;

  if (Val == Attribute::Alignment)
    Alignment = 0;
  else if (Val == Attribute::StackAlignment)
    StackAlignment = 0;
  else if (Val == Attribute::Dereferenceable)
    DerefBytes = 0;
  else if (Val == Attribute::DereferenceableOrNull)
    DerefOrNullBytes = 0;
  else if (Val == Attribute::AllocSize)
    AllocSizeArgs = 0;

  return *this;
}

AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
  remove(A.getAttributes(Index));
  return *this;
}

AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
  auto I = TargetDepAttrs.find(A);
  if (I != TargetDepAttrs.end())
    TargetDepAttrs.erase(I);
  return *this;
}

std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
  return unpackAllocSizeArgs(AllocSizeArgs);
}

AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
  if (Align == 0) return *this;

  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
  assert(Align <= 0x40000000 && "Alignment too large.");

  Attrs[Attribute::Alignment] = true;
  Alignment = Align;
  return *this;
}

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

  assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
  assert(Align <= 0x100 && "Alignment too large.");

  Attrs[Attribute::StackAlignment] = true;
  StackAlignment = Align;
  return *this;
}

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

  Attrs[Attribute::Dereferenceable] = true;
  DerefBytes = Bytes;
  return *this;
}

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

  Attrs[Attribute::DereferenceableOrNull] = true;
  DerefOrNullBytes = Bytes;
  return *this;
}

AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
                                           const 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)");

  Attrs[Attribute::AllocSize] = true;
  // Reuse existing machinery to store this as a single 64-bit integer so we can
  // save a few bytes over using a pair<unsigned, Optional<unsigned>>.
  AllocSizeArgs = RawArgs;
  return *this;
}

AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
  // FIXME: What if both have alignments, but they don't match?!
  if (!Alignment)
    Alignment = B.Alignment;

  if (!StackAlignment)
    StackAlignment = B.StackAlignment;

  if (!DerefBytes)
    DerefBytes = B.DerefBytes;

  if (!DerefOrNullBytes)
    DerefOrNullBytes = B.DerefOrNullBytes;

  if (!AllocSizeArgs)
    AllocSizeArgs = B.AllocSizeArgs;

  Attrs |= B.Attrs;

  for (auto I : B.td_attrs())
    TargetDepAttrs[I.first] = I.second;

  return *this;
}

AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
  // FIXME: What if both have alignments, but they don't match?!
  if (B.Alignment)
    Alignment = 0;

  if (B.StackAlignment)
    StackAlignment = 0;

  if (B.DerefBytes)
    DerefBytes = 0;

  if (B.DerefOrNullBytes)
    DerefOrNullBytes = 0;

  if (B.AllocSizeArgs)
    AllocSizeArgs = 0;

  Attrs &= ~B.Attrs;

  for (auto I : B.td_attrs())
    TargetDepAttrs.erase(I.first);

  return *this;
}

bool AttrBuilder::overlaps(const AttrBuilder &B) const {
  // First check if any of the target independent attributes overlap.
  if ((Attrs & B.Attrs).any())
    return true;

  // Then check if any target dependent ones do.
  for (const auto &I : td_attrs())
    if (B.contains(I.first))
      return true;

  return false;
}

bool AttrBuilder::contains(StringRef A) const {
  return TargetDepAttrs.find(A) != TargetDepAttrs.end();
}

bool AttrBuilder::hasAttributes() const {
  return !Attrs.none() || !TargetDepAttrs.empty();
}

bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
  AttributeSet AS = AL.getAttributes(Index);

  for (const auto Attr : AS) {
    if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
      if (contains(Attr.getKindAsEnum()))
        return true;
    } else {
      assert(Attr.isStringAttribute() && "Invalid attribute kind!");
      return contains(Attr.getKindAsString());
    }
  }

  return false;
}

bool AttrBuilder::hasAlignmentAttr() const {
  return Alignment != 0;
}

bool AttrBuilder::operator==(const AttrBuilder &B) {
  if (Attrs != B.Attrs)
    return false;

  for (td_const_iterator I = TargetDepAttrs.begin(),
         E = TargetDepAttrs.end(); I != E; ++I)
    if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
      return false;

  return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
         DerefBytes == B.DerefBytes;
}

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

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

  if (!Ty->isIntegerTy())
    // Attribute that only apply to integers.
    Incompatible.addAttribute(Attribute::SExt)
      .addAttribute(Attribute::ZExt);

  if (!Ty->isPointerTy())
    // Attribute that only apply to pointers.
    Incompatible.addAttribute(Attribute::ByVal)
      .addAttribute(Attribute::Nest)
      .addAttribute(Attribute::NoAlias)
      .addAttribute(Attribute::NoCapture)
      .addAttribute(Attribute::NonNull)
      .addDereferenceableAttr(1) // the int here is ignored
      .addDereferenceableOrNullAttr(1) // the int here is ignored
      .addAttribute(Attribute::ReadNone)
      .addAttribute(Attribute::ReadOnly)
      .addAttribute(Attribute::StructRet)
      .addAttribute(Attribute::InAlloca);

  return Incompatible;
}

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 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.
  AttrBuilder OldSSPAttr;
  OldSSPAttr.addAttribute(Attribute::StackProtect)
      .addAttribute(Attribute::StackProtectStrong)
      .addAttribute(Attribute::StackProtectReq);

  if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
    Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
    Caller.addFnAttr(Attribute::StackProtectReq);
  } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
             !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
    Caller.removeAttributes(AttributeList::FunctionIndex, 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) {
  if (Callee.hasFnAttribute("stack-probe-size")) {
    uint64_t CalleeStackProbeSize;
    Callee.getFnAttribute("stack-probe-size")
          .getValueAsString()
          .getAsInteger(0, CalleeStackProbeSize);
    if (Caller.hasFnAttribute("stack-probe-size")) {
      uint64_t CallerStackProbeSize;
      Caller.getFnAttribute("stack-probe-size")
            .getValueAsString()
            .getAsInteger(0, CallerStackProbeSize);
      if (CallerStackProbeSize > CalleeStackProbeSize) {
        Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size"));
      }
    } else {
      Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size"));
    }
  }
}

/// If the inlined function defines a min legal vector width, then ensure
/// the calling function has the same or larger min legal vector width. 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) {
  if (Callee.hasFnAttribute("min-legal-vector-width")) {
    uint64_t CalleeVectorWidth;
    Callee.getFnAttribute("min-legal-vector-width")
          .getValueAsString()
          .getAsInteger(0, CalleeVectorWidth);
    if (Caller.hasFnAttribute("min-legal-vector-width")) {
      uint64_t CallerVectorWidth;
      Caller.getFnAttribute("min-legal-vector-width")
            .getValueAsString()
            .getAsInteger(0, CallerVectorWidth);
      if (CallerVectorWidth < CalleeVectorWidth) {
        Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width"));
      }
    } else {
      Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width"));
    }
  }
}

/// If the inlined function has "null-pointer-is-valid=true" attribute,
/// set this attribute in the caller post inlining.
static void
adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
  if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
    Caller.addFnAttr(Callee.getFnAttribute("null-pointer-is-valid"));
  }
}

#define GET_ATTR_COMPAT_FUNC
#include "AttributesCompatFunc.inc"

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

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