diff options
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r-- | llvm/lib/IR/Attributes.cpp | 425 |
1 files changed, 290 insertions, 135 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 5ca99c981739..f67d96a854f4 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Function.h" @@ -91,9 +92,9 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, // 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); + PA = new (pImpl->Alloc) EnumAttributeImpl(Kind); else - PA = new IntAttributeImpl(Kind, Val); + PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } @@ -113,7 +114,10 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { 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); + void *Mem = + pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val), + alignof(StringAttributeImpl)); + PA = new (Mem) StringAttributeImpl(Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } @@ -134,7 +138,7 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, if (!PA) { // If we didn't find any existing attributes of the same shape then create a // new one and insert it. - PA = new TypeAttributeImpl(Kind, Ty); + PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } @@ -143,7 +147,7 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, } Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) { - assert(A <= 0x40000000 && "Alignment too large."); + assert(A <= llvm::Value::MaximumAlignment && "Alignment too large."); return get(Context, Alignment, A.value()); } @@ -168,6 +172,10 @@ Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) { return get(Context, ByVal, Ty); } +Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) { + return get(Context, Preallocated, Ty); +} + Attribute Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const Optional<unsigned> &NumElemsArg) { @@ -176,6 +184,45 @@ Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg)); } +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::doesAttrKindHaveArgument(Attribute::AttrKind AttrKind) { + return AttrKind == Attribute::Alignment || + AttrKind == Attribute::StackAlignment || + AttrKind == Attribute::Dereferenceable || + AttrKind == Attribute::AllocSize || + AttrKind == Attribute::DereferenceableOrNull; +} + +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 //===----------------------------------------------------------------------===// @@ -328,6 +375,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "noinline"; if (hasAttribute(Attribute::NonLazyBind)) return "nonlazybind"; + if (hasAttribute(Attribute::NoMerge)) + return "nomerge"; if (hasAttribute(Attribute::NonNull)) return "nonnull"; if (hasAttribute(Attribute::NoRedZone)) @@ -336,6 +385,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "noreturn"; if (hasAttribute(Attribute::NoSync)) return "nosync"; + if (hasAttribute(Attribute::NullPointerIsValid)) + return "null_pointer_is_valid"; if (hasAttribute(Attribute::WillReturn)) return "willreturn"; if (hasAttribute(Attribute::NoCfCheck)) @@ -392,6 +443,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "cold"; if (hasAttribute(Attribute::ImmArg)) return "immarg"; + if (hasAttribute(Attribute::NoUndef)) + return "noundef"; if (hasAttribute(Attribute::ByVal)) { std::string Result; @@ -406,6 +459,17 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return Result; } + if (hasAttribute(Attribute::Preallocated)) { + std::string Result; + Result += "preallocated"; + raw_string_ostream OS(Result); + Result += '('; + getValueAsType()->print(OS, false, true); + OS.flush(); + Result += ')'; + return Result; + } + // FIXME: These should be output like this: // // align=4 @@ -464,19 +528,19 @@ std::string Attribute::getAsString(bool InAttrGrp) const { // 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 << "\""; + 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; } @@ -491,21 +555,14 @@ bool Attribute::operator<(Attribute A) const { return *pImpl < *A.pImpl; } +void Attribute::Profile(FoldingSetNodeID &ID) const { + ID.AddPointer(pImpl); +} + //===----------------------------------------------------------------------===// // AttributeImpl Definition //===----------------------------------------------------------------------===// -// Pin the vtables to this file. -AttributeImpl::~AttributeImpl() = default; - -void EnumAttributeImpl::anchor() {} - -void IntAttributeImpl::anchor() {} - -void StringAttributeImpl::anchor() {} - -void TypeAttributeImpl::anchor() {} - bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { if (isStringAttribute()) return false; return getKindAsEnum() == A; @@ -542,6 +599,8 @@ Type *AttributeImpl::getValueAsType() const { } 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 (isEnumAttribute()) { @@ -687,6 +746,10 @@ Type *AttributeSet::getByValType() const { return SetNode ? SetNode->getByValType() : nullptr; } +Type *AttributeSet::getPreallocatedType() const { + return SetNode ? SetNode->getPreallocatedType() : nullptr; +} + std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const { return SetNode ? SetNode->getAllocSizeArgs() : std::pair<unsigned, Optional<unsigned>>(0, 0); @@ -721,30 +784,31 @@ AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs) // There's memory after the node where we can store the entries in. llvm::copy(Attrs, getTrailingObjects<Attribute>()); - static_assert(Attribute::EndAttrKinds <= - sizeof(AvailableAttrs) * CHAR_BIT, - "Too many attributes"); - for (const auto &I : *this) { - if (!I.isStringAttribute()) { - Attribute::AttrKind Kind = I.getKindAsEnum(); - AvailableAttrs[Kind / 8] |= 1ULL << (Kind % 8); - } + if (I.isStringAttribute()) + StringAttrs.insert({ I.getKindAsString(), I }); + else + AvailableAttrs.addAttribute(I.getKindAsEnum()); } } AttributeSetNode *AttributeSetNode::get(LLVMContext &C, ArrayRef<Attribute> Attrs) { - if (Attrs.empty()) + 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; - // Otherwise, build a key to look up the existing attributes. + // 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); - + assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!"); for (const auto &Attr : SortedAttrs) Attr.Profile(ID); @@ -778,6 +842,9 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { case Attribute::ByVal: Attr = Attribute::getWithByValType(C, B.getByValType()); break; + case Attribute::Preallocated: + Attr = Attribute::getWithPreallocatedType(C, B.getPreallocatedType()); + break; case Attribute::Alignment: assert(B.getAlignment() && "Alignment must be set"); Attr = Attribute::getWithAlignment(C, *B.getAlignment()); @@ -809,72 +876,81 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { for (const auto &TDA : B.td_attrs()) Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second)); - return get(C, Attrs); + return getSorted(C, Attrs); } bool AttributeSetNode::hasAttribute(StringRef Kind) const { - for (const auto &I : *this) - if (I.hasAttribute(Kind)) - return true; - return false; + return StringAttrs.count(Kind); +} + +Optional<Attribute> +AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const { + // Do a quick presence check. + if (!hasAttribute(Kind)) + return None; + + // 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 (hasAttribute(Kind)) { - for (const auto &I : *this) - if (I.hasAttribute(Kind)) - return I; - } + if (auto A = findEnumAttribute(Kind)) + return *A; return {}; } Attribute AttributeSetNode::getAttribute(StringRef Kind) const { - for (const auto &I : *this) - if (I.hasAttribute(Kind)) - return I; - return {}; + return StringAttrs.lookup(Kind); } MaybeAlign AttributeSetNode::getAlignment() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::Alignment)) - return I.getAlignment(); + if (auto A = findEnumAttribute(Attribute::Alignment)) + return A->getAlignment(); return None; } MaybeAlign AttributeSetNode::getStackAlignment() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::StackAlignment)) - return I.getStackAlignment(); + if (auto A = findEnumAttribute(Attribute::StackAlignment)) + return A->getStackAlignment(); return None; } Type *AttributeSetNode::getByValType() const { + if (auto A = findEnumAttribute(Attribute::ByVal)) + return A->getValueAsType(); + return 0; +} + +Type *AttributeSetNode::getPreallocatedType() const { for (const auto &I : *this) - if (I.hasAttribute(Attribute::ByVal)) + if (I.hasAttribute(Attribute::Preallocated)) return I.getValueAsType(); return 0; } uint64_t AttributeSetNode::getDereferenceableBytes() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::Dereferenceable)) - return I.getDereferenceableBytes(); + if (auto A = findEnumAttribute(Attribute::Dereferenceable)) + return A->getDereferenceableBytes(); return 0; } uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::DereferenceableOrNull)) - return I.getDereferenceableOrNullBytes(); + if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull)) + return A->getDereferenceableOrNullBytes(); return 0; } std::pair<unsigned, Optional<unsigned>> AttributeSetNode::getAllocSizeArgs() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::AllocSize)) - return I.getAllocSizeArgs(); + if (auto A = findEnumAttribute(Attribute::AllocSize)) + return A->getAllocSizeArgs(); return std::make_pair(0, 0); } @@ -893,33 +969,30 @@ std::string AttributeSetNode::getAsString(bool InAttrGrp) const { //===----------------------------------------------------------------------===// /// 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. +/// to work, because -1 wraps around to 0. static constexpr unsigned attrIdxToArrayIdx(unsigned Index) { - return Index == AttributeList::FunctionIndex ? 0 : Index + 1; + return Index + 1; } -AttributeListImpl::AttributeListImpl(LLVMContext &C, - ArrayRef<AttributeSet> Sets) - : Context(C), NumAttrSets(Sets.size()) { +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 summary bitset. - static_assert(Attribute::EndAttrKinds <= - sizeof(AvailableFunctionAttrs) * CHAR_BIT, - "Too many attributes"); + // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs + // summary bitsets. static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U, "function should be stored in slot 0"); - for (const auto &I : Sets[0]) { - if (!I.isStringAttribute()) { - Attribute::AttrKind Kind = I.getKindAsEnum(); - AvailableFunctionAttrs[Kind / 8] |= 1ULL << (Kind % 8); - } - } + for (const auto &I : Sets[0]) + 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 { @@ -932,6 +1005,24 @@ void AttributeListImpl::Profile(FoldingSetNodeID &ID, 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(); @@ -958,9 +1049,10 @@ AttributeList AttributeList::getImpl(LLVMContext &C, // 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); + void *Mem = pImpl->Alloc.Allocate( + AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()), + alignof(AttributeListImpl)); + PA = new (Mem) AttributeListImpl(AttrSets); pImpl->AttrsLists.InsertNode(PA, InsertPoint); } @@ -975,11 +1067,12 @@ AttributeList::get(LLVMContext &C, 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::is_sorted(Attrs, + [](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); @@ -1011,11 +1104,11 @@ AttributeList::get(LLVMContext &C, 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; - }) && + assert(llvm::is_sorted(Attrs, + [](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) { @@ -1096,6 +1189,17 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index, } 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) @@ -1184,7 +1288,7 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, AttributeList AttributeList::addParamAttribute(LLVMContext &C, ArrayRef<unsigned> ArgNos, Attribute A) const { - assert(std::is_sorted(ArgNos.begin(), ArgNos.end())); + assert(llvm::is_sorted(ArgNos)); SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex); @@ -1284,8 +1388,6 @@ AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index, // AttributeList Accessor Methods //===----------------------------------------------------------------------===// -LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); } - AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const { return getAttributes(ArgNo + FirstArgIndex); } @@ -1326,17 +1428,7 @@ bool AttributeList::hasParamAttribute(unsigned ArgNo, 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; + return pImpl && pImpl->hasAttrSomewhere(Attr, Index); } Attribute AttributeList::getAttribute(unsigned Index, @@ -1360,6 +1452,10 @@ Type *AttributeList::getParamByValType(unsigned Index) const { return getAttributes(Index+FirstArgIndex).getByValType(); } +Type *AttributeList::getParamPreallocatedType(unsigned Index) const { + return getAttributes(Index + FirstArgIndex).getPreallocatedType(); +} + MaybeAlign AttributeList::getStackAlignment(unsigned Index) const { return getAttributes(Index).getStackAlignment(); } @@ -1441,12 +1537,12 @@ void AttrBuilder::clear() { DerefBytes = DerefOrNullBytes = 0; AllocSizeArgs = 0; ByValType = nullptr; + PreallocatedType = nullptr; } 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 && + assert(!Attribute::doesAttrKindHaveArgument(Val) && "Adding integer attribute without adding a value!"); Attrs[Val] = true; return *this; @@ -1467,6 +1563,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { StackAlignment = Attr.getStackAlignment(); else if (Kind == Attribute::ByVal) ByValType = Attr.getValueAsType(); + else if (Kind == Attribute::Preallocated) + PreallocatedType = Attr.getValueAsType(); else if (Kind == Attribute::Dereferenceable) DerefBytes = Attr.getDereferenceableBytes(); else if (Kind == Attribute::DereferenceableOrNull) @@ -1477,7 +1575,7 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { } AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) { - TargetDepAttrs[A] = V; + TargetDepAttrs[std::string(A)] = std::string(V); return *this; } @@ -1491,6 +1589,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { StackAlignment.reset(); else if (Val == Attribute::ByVal) ByValType = nullptr; + else if (Val == Attribute::Preallocated) + PreallocatedType = nullptr; else if (Val == Attribute::Dereferenceable) DerefBytes = 0; else if (Val == Attribute::DereferenceableOrNull) @@ -1521,7 +1621,7 @@ AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) { if (!Align) return *this; - assert(*Align <= 0x40000000 && "Alignment too large."); + assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large."); Attrs[Attribute::Alignment] = true; Alignment = Align; @@ -1579,6 +1679,12 @@ AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) { return *this; } +AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) { + Attrs[Attribute::Preallocated] = true; + PreallocatedType = Ty; + return *this; +} + AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { // FIXME: What if both have alignments, but they don't match?! if (!Alignment) @@ -1599,9 +1705,12 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { if (!ByValType) ByValType = B.ByValType; + if (!PreallocatedType) + PreallocatedType = B.PreallocatedType; + Attrs |= B.Attrs; - for (auto I : B.td_attrs()) + for (const auto &I : B.td_attrs()) TargetDepAttrs[I.first] = I.second; return *this; @@ -1627,9 +1736,12 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { if (B.ByValType) ByValType = nullptr; + if (B.PreallocatedType) + PreallocatedType = nullptr; + Attrs &= ~B.Attrs; - for (auto I : B.td_attrs()) + for (const auto &I : B.td_attrs()) TargetDepAttrs.erase(I.first); return *this; @@ -1686,7 +1798,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) { return false; return Alignment == B.Alignment && StackAlignment == B.StackAlignment && - DerefBytes == B.DerefBytes && ByValType == B.ByValType; + DerefBytes == B.DerefBytes && ByValType == B.ByValType && + PreallocatedType == B.PreallocatedType; } //===----------------------------------------------------------------------===// @@ -1704,17 +1817,18 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { 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); + Incompatible.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) + .addPreallocatedAttr(Ty) + .addByValAttr(Ty); return Incompatible; } @@ -1837,17 +1951,58 @@ adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) { } } -/// If the inlined function has "null-pointer-is-valid=true" attribute, +/// 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(Callee.getFnAttribute("null-pointer-is-valid")); + 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 "AttributesCompatFunc.inc" +#include "llvm/IR/Attributes.inc" bool AttributeFuncs::areInlineCompatible(const Function &Caller, const Function &Callee) { |