diff options
Diffstat (limited to 'contrib/llvm/lib/IR/Attributes.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/Attributes.cpp | 213 |
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); +} |