diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 89a73d61824..e477b792a80 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -219,7 +219,7 @@ private: /// \brief Add the specified attribute at the specified index to this /// attribute list. Since attribute lists are immutable, this returns the new /// list. - AttributeSet addAttr(LLVMContext &C, unsigned Idx, Attribute Attrs) const; + AttributeSet addAttr(LLVMContext &C, unsigned Idx, AttributeSet Attrs) const; /// \brief Remove the specified attribute at the specified index from this /// attribute list. Since attribute lists are immutable, this returns the new @@ -284,7 +284,7 @@ public: AttributeSet Attrs) const; //===--------------------------------------------------------------------===// - // Attribute List Accessors + // Attribute Set Accessors //===--------------------------------------------------------------------===// /// \brief The attributes for the specified index are returned. @@ -296,24 +296,20 @@ public: /// \brief The function attributes are returned. AttributeSet getFnAttributes() const; - /// \brief Return the alignment for the specified function parameter. - unsigned getParamAlignment(unsigned Idx) const; - /// \brief Return true if the attribute exists at the given index. - bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; + bool hasAttribute(uint64_t Index, Attribute::AttrKind Kind) const; /// \brief Return true if attribute exists at the given index. - bool hasAttributes(unsigned Index) const; + bool hasAttributes(uint64_t Index) const; - /// \brief Returns the alignment field of an attribute as a byte alignment - /// value. - unsigned getAlignment(unsigned Index) const; + /// \brief Return the alignment for the specified function parameter. + unsigned getParamAlignment(uint64_t Idx) const; /// \brief Get the stack alignment. - unsigned getStackAlignment(unsigned Index) const; + unsigned getStackAlignment(uint64_t Index) const; /// \brief Return the attributes at the index as a string. - std::string getAsString(unsigned Index) const; + std::string getAsString(uint64_t Index) const; uint64_t Raw(unsigned Index) const; @@ -389,11 +385,14 @@ public: /// \brief Remove an attribute from the builder. AttrBuilder &removeAttribute(Attribute::AttrKind Val); - /// \brief Add the attributes from A to the builder. - AttrBuilder &addAttributes(const Attribute &A); + /// \brief Add the attributes to the builder. + AttrBuilder &addAttributes(Attribute A); - /// \brief Remove the attributes from A from the builder. - AttrBuilder &removeAttributes(const Attribute &A); + /// \brief Remove the attributes from the builder. + AttrBuilder &removeAttributes(Attribute A); + + /// \brief Add the attributes to the builder. + AttrBuilder &addAttributes(AttributeSet A); /// \brief Return true if the builder has the specified attribute. bool contains(Attribute::AttrKind A) const; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 67454864882..f341e54f273 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -246,6 +246,39 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { return *this; } +AttrBuilder &AttrBuilder::addAttributes(Attribute Attr) { + uint64_t Mask = Attr.Raw(); + + for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; + I = Attribute::AttrKind(I + 1)) + if ((Mask & AttributeImpl::getAttrMask(I)) != 0) + Attrs.insert(I); + + if (Attr.getAlignment()) + Alignment = Attr.getAlignment(); + if (Attr.getStackAlignment()) + StackAlignment = Attr.getStackAlignment(); + return *this; +} + +AttrBuilder &AttrBuilder::removeAttributes(Attribute A) { + uint64_t Mask = A.Raw(); + + for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; + I = Attribute::AttrKind(I + 1)) { + if (Mask & AttributeImpl::getAttrMask(I)) { + Attrs.erase(I); + + if (I == Attribute::Alignment) + Alignment = 0; + else if (I == Attribute::StackAlignment) + StackAlignment = 0; + } + } + + return *this; +} + AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { if (Align == 0) return *this; @@ -285,39 +318,6 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { return *this; } -AttrBuilder &AttrBuilder::addAttributes(const Attribute &Attr) { - uint64_t Mask = Attr.Raw(); - - for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; - I = Attribute::AttrKind(I + 1)) - if ((Mask & AttributeImpl::getAttrMask(I)) != 0) - Attrs.insert(I); - - if (Attr.getAlignment()) - Alignment = Attr.getAlignment(); - if (Attr.getStackAlignment()) - StackAlignment = Attr.getStackAlignment(); - return *this; -} - -AttrBuilder &AttrBuilder::removeAttributes(const Attribute &A){ - uint64_t Mask = A.Raw(); - - for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; - I = Attribute::AttrKind(I + 1)) { - if (Mask & AttributeImpl::getAttrMask(I)) { - Attrs.erase(I); - - if (I == Attribute::Alignment) - Alignment = 0; - else if (I == Attribute::StackAlignment) - StackAlignment = 0; - } - } - - return *this; -} - bool AttrBuilder::contains(Attribute::AttrKind A) const { return Attrs.count(A); } @@ -710,23 +710,23 @@ AttributeSet AttributeSet::getSlotAttributes(unsigned Slot) const { return pImpl->getSlotAttributes(Slot); } -bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{ +bool AttributeSet::hasAttribute(uint64_t Index, Attribute::AttrKind Kind) const{ return getAttributes(Index).hasAttribute(Kind); } -bool AttributeSet::hasAttributes(unsigned Index) const { +bool AttributeSet::hasAttributes(uint64_t Index) const { return getAttributes(Index).hasAttributes(); } -std::string AttributeSet::getAsString(unsigned Index) const { +std::string AttributeSet::getAsString(uint64_t Index) const { return getAttributes(Index).getAsString(); } -unsigned AttributeSet::getParamAlignment(unsigned Idx) const { +unsigned AttributeSet::getParamAlignment(uint64_t Idx) const { return getAttributes(Idx).getAlignment(); } -unsigned AttributeSet::getStackAlignment(unsigned Index) const { +unsigned AttributeSet::getStackAlignment(uint64_t Index) const { return getAttributes(Index).getStackAlignment(); } @@ -771,58 +771,61 @@ bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Idx, Attribute::AttrKind Attr) const { - return addAttr(C, Idx, Attribute::get(C, Attr)); + return addAttr(C, Idx, AttributeSet::get(C, Idx, Attr)); } AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, AttributeSet Attrs) const { - return addAttr(C, Idx, Attrs.getAttributes(Idx)); + return addAttr(C, Idx, Attrs); } AttributeSet AttributeSet::addAttr(LLVMContext &C, unsigned Idx, - Attribute Attrs) const { - Attribute OldAttrs = getAttributes(Idx); + AttributeSet Attrs) const { + if (!pImpl) return Attrs; + if (!Attrs.pImpl) return *this; + #ifndef NDEBUG - // FIXME it is not obvious how this should work for alignment. - // For now, say we can't change a known alignment. - unsigned OldAlign = OldAttrs.getAlignment(); - unsigned NewAlign = Attrs.getAlignment(); + // FIXME it is not obvious how this should work for alignment. For now, say + // we can't change a known alignment. + unsigned OldAlign = getParamAlignment(Idx); + unsigned NewAlign = Attrs.getParamAlignment(Idx); assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && "Attempt to change alignment!"); #endif - AttrBuilder NewAttrs = - AttrBuilder(OldAttrs).addAttributes(Attrs); - if (NewAttrs == AttrBuilder(OldAttrs)) - return *this; - - SmallVector NewAttrList; - if (pImpl == 0) { - NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); - } else { - ArrayRef OldAttrList = pImpl->getAttributes(); - unsigned i = 0, e = OldAttrList.size(); - - // Copy attributes for arguments before this one. - for (; i != e && OldAttrList[i].Index < Idx; ++i) - NewAttrList.push_back(OldAttrList[i]); - - // If there are attributes already at this index, merge them in. - if (i != e && OldAttrList[i].Index == Idx) { - Attrs = - Attribute::get(C, AttrBuilder(Attrs). - addAttributes(OldAttrList[i].Attrs)); - ++i; + // Add the attribute slots before the one we're trying to add. + SmallVector AttrSet; + uint64_t NumAttrs = pImpl->getNumAttributes(); + AttributeSet AS; + uint64_t LastIndex = 0; + for (unsigned I = 0, E = NumAttrs; I != E; ++I) { + if (getSlotIndex(I) >= Idx) { + if (getSlotIndex(I) == Idx) AS = getSlotAttributes(LastIndex++); + break; } - - NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); - - // Copy attributes for arguments after this one. - NewAttrList.insert(NewAttrList.end(), - OldAttrList.begin()+i, OldAttrList.end()); + LastIndex = I + 1; + AttrSet.push_back(getSlotAttributes(I)); } - return get(C, NewAttrList); + // Now add the attribute into the correct slot. There may already be an + // AttributeSet there. + AttrBuilder B(AS, Idx); + + for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) + if (Attrs.getSlotIndex(I) == Idx) { + for (AttributeSetImpl::const_iterator II = Attrs.pImpl->begin(I), + IE = Attrs.pImpl->end(I); II != IE; ++II) + B.addAttributes(*II); + break; + } + + AttrSet.push_back(AttributeSet::get(C, Idx, B)); + + // Add the remaining attribute slots. + for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) + AttrSet.push_back(getSlotAttributes(I)); + + return get(C, AttrSet); } AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Idx,