aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/IR/Attributes.cpp')
-rw-r--r--contrib/llvm/lib/IR/Attributes.cpp213
1 files changed, 158 insertions, 55 deletions
diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp
index 546a98670a29..bcf7dc365ce5 100644
--- a/contrib/llvm/lib/IR/Attributes.cpp
+++ b/contrib/llvm/lib/IR/Attributes.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
#include "AttributeImpl.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/STLExtras.h"
@@ -120,28 +121,28 @@ Attribute::AttrKind Attribute::getKindAsEnum() const {
if (!pImpl) return None;
assert((isEnumAttribute() || isIntAttribute()) &&
"Invalid attribute type to get the kind as an enum!");
- return pImpl ? pImpl->getKindAsEnum() : None;
+ return pImpl->getKindAsEnum();
}
uint64_t Attribute::getValueAsInt() const {
if (!pImpl) return 0;
assert(isIntAttribute() &&
"Expected the attribute to be an integer attribute!");
- return pImpl ? pImpl->getValueAsInt() : 0;
+ return pImpl->getValueAsInt();
}
StringRef Attribute::getKindAsString() const {
if (!pImpl) return StringRef();
assert(isStringAttribute() &&
"Invalid attribute type to get the kind as a string!");
- return pImpl ? pImpl->getKindAsString() : StringRef();
+ return pImpl->getKindAsString();
}
StringRef Attribute::getValueAsString() const {
if (!pImpl) return StringRef();
assert(isStringAttribute() &&
"Invalid attribute type to get the value as a string!");
- return pImpl ? pImpl->getValueAsString() : StringRef();
+ return pImpl->getValueAsString();
}
bool Attribute::hasAttribute(AttrKind Kind) const {
@@ -198,6 +199,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "byval";
if (hasAttribute(Attribute::Convergent))
return "convergent";
+ if (hasAttribute(Attribute::InaccessibleMemOnly))
+ return "inaccessiblememonly";
+ if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
+ return "inaccessiblemem_or_argmemonly";
if (hasAttribute(Attribute::InAlloca))
return "inalloca";
if (hasAttribute(Attribute::InlineHint))
@@ -232,6 +237,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "noredzone";
if (hasAttribute(Attribute::NoReturn))
return "noreturn";
+ if (hasAttribute(Attribute::NoRecurse))
+ return "norecurse";
if (hasAttribute(Attribute::NoUnwind))
return "nounwind";
if (hasAttribute(Attribute::OptimizeNone))
@@ -442,6 +449,9 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::JumpTable: return 1ULL << 45;
case Attribute::Convergent: return 1ULL << 46;
case Attribute::SafeStack: return 1ULL << 47;
+ case Attribute::NoRecurse: return 1ULL << 48;
+ case Attribute::InaccessibleMemOnly: return 1ULL << 49;
+ case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
@@ -472,9 +482,8 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
array_pod_sort(SortedAttrs.begin(), SortedAttrs.end());
- for (SmallVectorImpl<Attribute>::iterator I = SortedAttrs.begin(),
- E = SortedAttrs.end(); I != E; ++I)
- I->Profile(ID);
+ for (Attribute Attr : SortedAttrs)
+ Attr.Profile(ID);
void *InsertPoint;
AttributeSetNode *PA =
@@ -484,8 +493,7 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
// new one and insert it.
if (!PA) {
// Coallocate entries after the AttributeSetNode itself.
- void *Mem = ::operator new(sizeof(AttributeSetNode) +
- sizeof(Attribute) * SortedAttrs.size());
+ void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
PA = new (Mem) AttributeSetNode(SortedAttrs);
pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
}
@@ -617,9 +625,8 @@ AttributeSet::getImpl(LLVMContext &C,
// create a new one and insert it.
if (!PA) {
// Coallocate entries after the AttributeSetImpl itself.
- void *Mem = ::operator new(sizeof(AttributeSetImpl) +
- sizeof(std::pair<unsigned, AttributeSetNode *>) *
- Attrs.size());
+ void *Mem = ::operator new(
+ AttributeSetImpl::totalSizeToAlloc<IndexAttrPair>(Attrs.size()));
PA = new (Mem) AttributeSetImpl(C, Attrs);
pImpl->AttrsLists.InsertNode(PA, InsertPoint);
}
@@ -684,22 +691,26 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
if (!B.contains(Kind))
continue;
- if (Kind == Attribute::Alignment)
- Attrs.push_back(std::make_pair(Index, Attribute::
- getWithAlignment(C, B.getAlignment())));
- else if (Kind == Attribute::StackAlignment)
- Attrs.push_back(std::make_pair(Index, Attribute::
- getWithStackAlignment(C, B.getStackAlignment())));
- else if (Kind == Attribute::Dereferenceable)
- Attrs.push_back(std::make_pair(Index,
- Attribute::getWithDereferenceableBytes(C,
- B.getDereferenceableBytes())));
- else if (Kind == Attribute::DereferenceableOrNull)
- Attrs.push_back(
- std::make_pair(Index, Attribute::getWithDereferenceableOrNullBytes(
- C, B.getDereferenceableOrNullBytes())));
- else
- Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind)));
+ 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;
+ default:
+ Attr = Attribute::get(C, Kind);
+ }
+ Attrs.push_back(std::make_pair(Index, Attr));
}
// Add target-dependent (string) attributes.
@@ -713,9 +724,8 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
ArrayRef<Attribute::AttrKind> Kind) {
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
- for (ArrayRef<Attribute::AttrKind>::iterator I = Kind.begin(),
- E = Kind.end(); I != E; ++I)
- Attrs.push_back(std::make_pair(Index, Attribute::get(C, *I)));
+ for (Attribute::AttrKind K : Kind)
+ Attrs.push_back(std::make_pair(Index, Attribute::get(C, K)));
return get(C, Attrs);
}
@@ -736,9 +746,8 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) {
if (!AS) continue;
SmallVector<std::pair<unsigned, AttributeSetNode *>, 8>::iterator
ANVI = AttrNodeVec.begin(), ANVE;
- for (const AttributeSetImpl::IndexAttrPair
- *AI = AS->getNode(0),
- *AE = AS->getNode(AS->getNumAttributes());
+ for (const IndexAttrPair *AI = AS->getNode(0),
+ *AE = AS->getNode(AS->getNumAttributes());
AI != AE; ++AI) {
ANVE = AttrNodeVec.end();
while (ANVI != ANVE && ANVI->first <= AI->first)
@@ -770,6 +779,36 @@ AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
return addAttributes(C, Index, AttributeSet::get(C, Index, B));
}
+AttributeSet AttributeSet::addAttribute(LLVMContext &C,
+ ArrayRef<unsigned> Indices,
+ Attribute A) const {
+ unsigned I = 0, E = pImpl ? pImpl->getNumAttributes() : 0;
+ auto IdxI = Indices.begin(), IdxE = Indices.end();
+ SmallVector<AttributeSet, 4> AttrSet;
+
+ while (I != E && IdxI != IdxE) {
+ if (getSlotIndex(I) < *IdxI)
+ AttrSet.emplace_back(getSlotAttributes(I++));
+ else if (getSlotIndex(I) > *IdxI)
+ AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
+ else {
+ AttrBuilder B(getSlotAttributes(I), *IdxI);
+ B.addAttribute(A);
+ AttrSet.emplace_back(AttributeSet::get(C, *IdxI, B));
+ ++I;
+ ++IdxI;
+ }
+ }
+
+ while (I != E)
+ AttrSet.emplace_back(getSlotAttributes(I++));
+
+ while (IdxI != IdxE)
+ AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
+
+ return get(C, AttrSet);
+}
+
AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
AttributeSet Attrs) const {
if (!pImpl) return Attrs;
@@ -955,17 +994,17 @@ AttributeSet AttributeSet::getFnAttributes() const {
bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{
AttributeSetNode *ASN = getAttributes(Index);
- return ASN ? ASN->hasAttribute(Kind) : false;
+ return ASN && ASN->hasAttribute(Kind);
}
bool AttributeSet::hasAttribute(unsigned Index, StringRef Kind) const {
AttributeSetNode *ASN = getAttributes(Index);
- return ASN ? ASN->hasAttribute(Kind) : false;
+ return ASN && ASN->hasAttribute(Kind);
}
bool AttributeSet::hasAttributes(unsigned Index) const {
AttributeSetNode *ASN = getAttributes(Index);
- return ASN ? ASN->hasAttributes() : false;
+ return ASN && ASN->hasAttributes();
}
/// \brief Return true if the specified attribute is set for at least one
@@ -1111,6 +1150,7 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
void AttrBuilder::clear() {
Attrs.reset();
+ TargetDepAttrs.clear();
Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
}
@@ -1177,23 +1217,10 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
Attribute Attr = *I;
if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
- Attribute::AttrKind Kind = I->getKindAsEnum();
- Attrs[Kind] = false;
-
- if (Kind == Attribute::Alignment)
- Alignment = 0;
- else if (Kind == Attribute::StackAlignment)
- StackAlignment = 0;
- else if (Kind == Attribute::Dereferenceable)
- DerefBytes = 0;
- else if (Kind == Attribute::DereferenceableOrNull)
- DerefOrNullBytes = 0;
+ removeAttribute(Attr.getKindAsEnum());
} else {
assert(Attr.isStringAttribute() && "Invalid attribute type!");
- std::map<std::string, std::string>::iterator
- Iter = TargetDepAttrs.find(Attr.getKindAsString());
- if (Iter != TargetDepAttrs.end())
- TargetDepAttrs.erase(Iter);
+ removeAttribute(Attr.getKindAsString());
}
}
@@ -1322,8 +1349,7 @@ bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const {
assert(Slot != ~0U && "Couldn't find the index!");
- for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot);
- I != E; ++I) {
+ for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
Attribute Attr = *I;
if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
if (Attrs[I->getKindAsEnum()])
@@ -1382,7 +1408,7 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
//===----------------------------------------------------------------------===//
/// \brief Which attributes cannot be applied to a type.
-AttrBuilder AttributeFuncs::typeIncompatible(const Type *Ty) {
+AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
AttrBuilder Incompatible;
if (!Ty->isIntegerTy())
@@ -1406,3 +1432,80 @@ AttrBuilder AttributeFuncs::typeIncompatible(const Type *Ty) {
return Incompatible;
}
+
+template<typename AttrClass>
+static bool isEqual(const Function &Caller, const Function &Callee) {
+ return Caller.getFnAttribute(AttrClass::getKind()) ==
+ Callee.getFnAttribute(AttrClass::getKind());
+}
+
+/// \brief 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);
+}
+
+/// \brief 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);
+}
+
+/// \brief 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 B;
+ B.addAttribute(Attribute::StackProtect)
+ .addAttribute(Attribute::StackProtectStrong)
+ .addAttribute(Attribute::StackProtectReq);
+ AttributeSet OldSSPAttr = AttributeSet::get(Caller.getContext(),
+ AttributeSet::FunctionIndex,
+ B);
+
+ if (Callee.hasFnAttribute(Attribute::SafeStack)) {
+ Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller.addFnAttr(Attribute::SafeStack);
+ } else if (Callee.hasFnAttribute(Attribute::StackProtectReq) &&
+ !Caller.hasFnAttribute(Attribute::SafeStack)) {
+ Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller.addFnAttr(Attribute::StackProtectReq);
+ } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
+ !Caller.hasFnAttribute(Attribute::SafeStack) &&
+ !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
+ Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller.addFnAttr(Attribute::StackProtectStrong);
+ } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
+ !Caller.hasFnAttribute(Attribute::SafeStack) &&
+ !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
+ !Caller.hasFnAttribute(Attribute::StackProtectStrong))
+ Caller.addFnAttr(Attribute::StackProtect);
+}
+
+#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);
+}