aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r--llvm/lib/IR/Attributes.cpp425
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) {