aboutsummaryrefslogtreecommitdiff
path: root/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/Attributes.cpp')
-rw-r--r--lib/IR/Attributes.cpp190
1 files changed, 113 insertions, 77 deletions
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index 1b19a0474727..9e5f55d49756 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// \file
-// \brief This file implements the Attribute, AttributeImpl, AttrBuilder,
+// This file implements the Attribute, AttributeImpl, AttrBuilder,
// AttributeListImpl, and AttributeList classes.
//
//===----------------------------------------------------------------------===//
@@ -24,6 +24,7 @@
#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"
@@ -38,7 +39,6 @@
#include <cstddef>
#include <cstdint>
#include <limits>
-#include <map>
#include <string>
#include <tuple>
#include <utility>
@@ -186,14 +186,14 @@ uint64_t Attribute::getValueAsInt() const {
}
StringRef Attribute::getKindAsString() const {
- if (!pImpl) return StringRef();
+ 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 StringRef();
+ if (!pImpl) return {};
assert(isStringAttribute() &&
"Invalid attribute type to get the value as a string!");
return pImpl->getValueAsString();
@@ -241,7 +241,7 @@ std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
}
std::string Attribute::getAsString(bool InAttrGrp) const {
- if (!pImpl) return "";
+ if (!pImpl) return {};
if (hasAttribute(Attribute::SanitizeAddress))
return "sanitize_address";
@@ -299,10 +299,14 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
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))
@@ -329,6 +333,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "sspstrong";
if (hasAttribute(Attribute::SafeStack))
return "safestack";
+ if (hasAttribute(Attribute::ShadowCallStack))
+ return "shadowcallstack";
if (hasAttribute(Attribute::StrictFP))
return "strictfp";
if (hasAttribute(Attribute::StructRet))
@@ -413,7 +419,7 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
{
raw_string_ostream OS(Result);
OS << "=\"";
- PrintEscapedString(AttrVal, OS);
+ printEscapedString(AttrVal, OS);
OS << "\"";
}
return Result;
@@ -534,7 +540,7 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
return *this;
AttrBuilder B(AS);
- for (Attribute I : *this)
+ for (const auto I : *this)
B.addAttribute(I);
return get(C, B);
@@ -543,26 +549,21 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Kind)) return *this;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, B);
+ 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;
- B.addAttribute(Kind);
- return removeAttributes(C, B);
+ AttrBuilder B(*this);
+ B.removeAttribute(Kind);
+ return get(C, B);
}
AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
const AttrBuilder &Attrs) const {
-
- // FIXME it is not obvious how this should work for alignment.
- // For now, say we can't pass in alignment, which no current use does.
- assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!");
-
AttrBuilder B(*this);
B.remove(Attrs);
return get(C, B);
@@ -638,7 +639,7 @@ AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
// There's memory after the node where we can store the entries in.
std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>());
- for (Attribute I : *this) {
+ for (const auto I : *this) {
if (!I.isStringAttribute()) {
AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
}
@@ -655,9 +656,9 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
FoldingSetNodeID ID;
SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
- std::sort(SortedAttrs.begin(), SortedAttrs.end());
+ llvm::sort(SortedAttrs.begin(), SortedAttrs.end());
- for (Attribute Attr : SortedAttrs)
+ for (const auto Attr : SortedAttrs)
Attr.Profile(ID);
void *InsertPoint;
@@ -720,7 +721,7 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
}
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Kind))
return true;
return false;
@@ -728,43 +729,43 @@ bool AttributeSetNode::hasAttribute(StringRef Kind) const {
Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
if (hasAttribute(Kind)) {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Kind))
return I;
}
- return Attribute();
+ return {};
}
Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Kind))
return I;
- return Attribute();
+ return {};
}
unsigned AttributeSetNode::getAlignment() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::Alignment))
return I.getAlignment();
return 0;
}
unsigned AttributeSetNode::getStackAlignment() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::StackAlignment))
return I.getStackAlignment();
return 0;
}
uint64_t AttributeSetNode::getDereferenceableBytes() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::Dereferenceable))
return I.getDereferenceableBytes();
return 0;
}
uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::DereferenceableOrNull))
return I.getDereferenceableOrNullBytes();
return 0;
@@ -772,7 +773,7 @@ uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
std::pair<unsigned, Optional<unsigned>>
AttributeSetNode::getAllocSizeArgs() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::AllocSize))
return I.getAllocSizeArgs();
return std::make_pair(0, 0);
@@ -814,7 +815,7 @@ AttributeListImpl::AttributeListImpl(LLVMContext &C,
"Too many attributes");
static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
"function should be stored in slot 0");
- for (Attribute I : Sets[0]) {
+ for (const auto I : Sets[0]) {
if (!I.isStringAttribute())
AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum();
}
@@ -871,17 +872,17 @@ 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 AttributeList();
+ 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(none_of(Attrs,
- [](const std::pair<unsigned, Attribute> &Pair) {
- return Pair.second.hasAttribute(Attribute::None);
- }) &&
+ 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
@@ -907,7 +908,7 @@ 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 AttributeList();
+ return {};
assert(std::is_sorted(Attrs.begin(), Attrs.end(),
[](const std::pair<unsigned, AttributeSet> &LHS,
@@ -915,16 +916,20 @@ AttributeList::get(LLVMContext &C,
return LHS.first < RHS.first;
}) &&
"Misordered Attributes list!");
- assert(none_of(Attrs,
- [](const std::pair<unsigned, AttributeSet> &Pair) {
- return !Pair.second.hasAttributes();
- }) &&
+ 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 (auto Pair : Attrs)
+ for (const auto Pair : Attrs)
AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
return getImpl(C, AttrVec);
@@ -954,7 +959,7 @@ AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
// If all attribute sets were empty, we can use the empty attribute list.
if (NumSets == 0)
- return AttributeList();
+ return {};
SmallVector<AttributeSet, 8> AttrSets;
AttrSets.reserve(NumSets);
@@ -974,7 +979,7 @@ AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
const AttrBuilder &B) {
if (!B.hasAttributes())
- return AttributeList();
+ return {};
Index = attrIdxToArrayIdx(Index);
SmallVector<AttributeSet, 8> AttrSets(Index + 1);
AttrSets[Index] = AttributeSet::get(C, B);
@@ -984,7 +989,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
ArrayRef<Attribute::AttrKind> Kinds) {
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
- for (Attribute::AttrKind K : Kinds)
+ for (const auto K : Kinds)
Attrs.emplace_back(Index, Attribute::get(C, K));
return get(C, Attrs);
}
@@ -992,7 +997,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
ArrayRef<StringRef> Kinds) {
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
- for (StringRef K : Kinds)
+ for (const auto K : Kinds)
Attrs.emplace_back(Index, Attribute::get(C, K));
return get(C, Attrs);
}
@@ -1000,22 +1005,22 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
AttributeList AttributeList::get(LLVMContext &C,
ArrayRef<AttributeList> Attrs) {
if (Attrs.empty())
- return AttributeList();
+ return {};
if (Attrs.size() == 1)
return Attrs[0];
unsigned MaxSize = 0;
- for (AttributeList List : Attrs)
+ 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 AttributeList();
+ return {};
SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
for (unsigned I = 0; I < MaxSize; ++I) {
AttrBuilder CurBuilder;
- for (AttributeList List : Attrs)
+ for (const auto List : Attrs)
CurBuilder.merge(List.getAttributes(I - 1));
NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
}
@@ -1098,37 +1103,41 @@ AttributeList AttributeList::addParamAttribute(LLVMContext &C,
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Index, Kind)) return *this;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, Index, B);
+
+ 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;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, Index, B);
+
+ 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 AttributeList();
-
- // FIXME it is not obvious how this should work for alignment.
- // For now, say we can't pass in alignment, which no current use does.
- assert(!AttrsToRemove.hasAlignmentAttr() && "Attempt to change alignment!");
+ return {};
Index = attrIdxToArrayIdx(Index);
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
if (Index >= AttrSets.size())
AttrSets.resize(Index + 1);
- AttrBuilder B(AttrSets[Index]);
- B.remove(AttrsToRemove);
- AttrSets[Index] = AttributeSet::get(C, B);
+ AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);
return getImpl(C, AttrSets);
}
@@ -1136,7 +1145,7 @@ AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
AttributeList AttributeList::removeAttributes(LLVMContext &C,
unsigned WithoutIndex) const {
if (!pImpl)
- return AttributeList();
+ return {};
WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
if (WithoutIndex >= getNumAttrSets())
return *this;
@@ -1270,7 +1279,7 @@ std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
AttributeSet AttributeList::getAttributes(unsigned Index) const {
Index = attrIdxToArrayIdx(Index);
if (!pImpl || Index >= getNumAttrSets())
- return AttributeSet();
+ return {};
return pImpl->begin()[Index];
}
@@ -1310,12 +1319,12 @@ LLVM_DUMP_METHOD void AttributeList::dump() const {
// FIXME: Remove this ctor, use AttributeSet.
AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
AttributeSet AS = AL.getAttributes(Index);
- for (const Attribute &A : AS)
+ for (const auto &A : AS)
addAttribute(A);
}
AttrBuilder::AttrBuilder(AttributeSet AS) {
- for (const Attribute &A : AS)
+ for (const auto &A : AS)
addAttribute(A);
}
@@ -1386,7 +1395,7 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
}
AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
- std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A);
+ auto I = TargetDepAttrs.find(A);
if (I != TargetDepAttrs.end())
TargetDepAttrs.erase(I);
return *this;
@@ -1526,7 +1535,7 @@ bool AttrBuilder::hasAttributes() const {
bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
AttributeSet AS = AL.getAttributes(Index);
- for (Attribute Attr : AS) {
+ for (const auto Attr : AS) {
if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
if (contains(Attr.getKindAsEnum()))
return true;
@@ -1560,7 +1569,7 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {
// AttributeFuncs Function Defintions
//===----------------------------------------------------------------------===//
-/// \brief Which attributes cannot be applied to a type.
+/// Which attributes cannot be applied to a type.
AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
AttrBuilder Incompatible;
@@ -1592,7 +1601,7 @@ static bool isEqual(const Function &Caller, const Function &Callee) {
Callee.getFnAttribute(AttrClass::getKind());
}
-/// \brief Compute the logical AND of the attributes of the caller and the
+/// 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
@@ -1604,7 +1613,7 @@ static void setAND(Function &Caller, const Function &Callee) {
AttrClass::set(Caller, AttrClass::getKind(), false);
}
-/// \brief Compute the logical OR of the attributes of the caller and the
+/// 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
@@ -1616,7 +1625,7 @@ static void setOR(Function &Caller, const Function &Callee) {
AttrClass::set(Caller, AttrClass::getKind(), true);
}
-/// \brief If the inlined function had a higher stack protection level than the
+/// 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.
@@ -1640,7 +1649,7 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
Caller.addFnAttr(Attribute::StackProtect);
}
-/// \brief If the inlined function required stack probes, then ensure that
+/// 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") &&
@@ -1649,7 +1658,7 @@ static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
}
}
-/// \brief If the inlined function defines the size of guard region
+/// 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
@@ -1673,6 +1682,33 @@ adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
}
}
+/// 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"));
+ }
+ }
+}
+
#define GET_ATTR_COMPAT_FUNC
#include "AttributesCompatFunc.inc"