+//===----------------------------------------------------------------------===//
+// AttrBuilder Method Implementations
+//===----------------------------------------------------------------------===//
+
+AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Idx)
+ : Attrs(0), Alignment(0), StackAlignment(0) {
+ AttributeSetImpl *pImpl = AS.pImpl;
+ if (!pImpl) return;
+
+ for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) {
+ if (pImpl->getSlotIndex(I) != Idx) continue;
+
+ for (AttributeSetImpl::const_iterator II = pImpl->begin(I),
+ IE = pImpl->end(I); II != IE; ++II)
+ addAttribute(*II);
+
+ break;
+ }
+}
+
+void AttrBuilder::clear() {
+ Attrs.reset();
+ Alignment = StackAlignment = 0;
+}
+
+AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
+ assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
+ assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
+ "Adding alignment attribute without adding alignment value!");
+ Attrs[Val] = true;
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
+ if (Attr.isStringAttribute()) {
+ addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
+ return *this;
+ }
+
+ Attribute::AttrKind Kind = Attr.getKindAsEnum();
+ Attrs[Kind] = true;
+
+ if (Kind == Attribute::Alignment)
+ Alignment = Attr.getAlignment();
+ else if (Kind == Attribute::StackAlignment)
+ StackAlignment = Attr.getStackAlignment();
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
+ TargetDepAttrs[A] = V;
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
+ assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
+ Attrs[Val] = false;
+
+ if (Val == Attribute::Alignment)
+ Alignment = 0;
+ else if (Val == Attribute::StackAlignment)
+ StackAlignment = 0;
+
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
+ unsigned Idx = ~0U;
+ for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I)
+ if (A.getSlotIndex(I) == Index) {
+ Idx = I;
+ break;
+ }
+
+ assert(Idx != ~0U && "Couldn't find index in AttributeSet!");
+
+ for (AttributeSet::iterator I = A.begin(Idx), E = A.end(Idx); I != E; ++I) {
+ Attribute Attr = *I;
+ if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) {
+ Attribute::AttrKind Kind = I->getKindAsEnum();
+ Attrs[Kind] = false;
+
+ if (Kind == Attribute::Alignment)
+ Alignment = 0;
+ else if (Kind == Attribute::StackAlignment)
+ StackAlignment = 0;
+ } 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);
+ }
+ }
+
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
+ std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A);
+ if (I != TargetDepAttrs.end())
+ TargetDepAttrs.erase(I);
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
+ if (Align == 0) return *this;
+
+ assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
+ assert(Align <= 0x40000000 && "Alignment too large.");
+
+ Attrs[Attribute::Alignment] = true;
+ Alignment = Align;
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
+ // Default alignment, allow the target to define how to align it.
+ if (Align == 0) return *this;
+
+ assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
+ assert(Align <= 0x100 && "Alignment too large.");
+
+ Attrs[Attribute::StackAlignment] = true;
+ StackAlignment = Align;
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
+ // FIXME: What if both have alignments, but they don't match?!
+ if (!Alignment)
+ Alignment = B.Alignment;
+
+ if (!StackAlignment)
+ StackAlignment = B.StackAlignment;
+
+ Attrs |= B.Attrs;
+
+ for (td_const_iterator I = B.TargetDepAttrs.begin(),
+ E = B.TargetDepAttrs.end(); I != E; ++I)
+ TargetDepAttrs[I->first] = I->second;
+
+ return *this;
+}
+
+bool AttrBuilder::contains(StringRef A) const {
+ return TargetDepAttrs.find(A) != TargetDepAttrs.end();
+}
+
+bool AttrBuilder::hasAttributes() const {
+ return !Attrs.none() || !TargetDepAttrs.empty();
+}
+
+bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const {
+ unsigned Idx = ~0U;
+ for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I)
+ if (A.getSlotIndex(I) == Index) {
+ Idx = I;
+ break;
+ }
+
+ assert(Idx != ~0U && "Couldn't find the index!");
+
+ for (AttributeSet::iterator I = A.begin(Idx), E = A.end(Idx);
+ I != E; ++I) {
+ Attribute Attr = *I;
+ if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) {
+ if (Attrs[I->getKindAsEnum()])
+ return true;
+ } else {
+ assert(Attr.isStringAttribute() && "Invalid attribute kind!");
+ return TargetDepAttrs.find(Attr.getKindAsString())!=TargetDepAttrs.end();
+ }
+ }
+
+ return false;
+}
+
+bool AttrBuilder::hasAlignmentAttr() const {
+ return Alignment != 0;
+}
+
+bool AttrBuilder::operator==(const AttrBuilder &B) {
+ if (Attrs != B.Attrs)
+ return false;
+
+ for (td_const_iterator I = TargetDepAttrs.begin(),
+ E = TargetDepAttrs.end(); I != E; ++I)
+ if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
+ return false;
+
+ return Alignment == B.Alignment && StackAlignment == B.StackAlignment;
+}
+
+void AttrBuilder::removeFunctionOnlyAttrs() {
+ removeAttribute(Attribute::NoReturn)
+ .removeAttribute(Attribute::NoUnwind)
+ .removeAttribute(Attribute::ReadNone)
+ .removeAttribute(Attribute::ReadOnly)
+ .removeAttribute(Attribute::NoInline)
+ .removeAttribute(Attribute::AlwaysInline)
+ .removeAttribute(Attribute::OptimizeForSize)
+ .removeAttribute(Attribute::StackProtect)
+ .removeAttribute(Attribute::StackProtectReq)
+ .removeAttribute(Attribute::StackProtectStrong)
+ .removeAttribute(Attribute::NoRedZone)
+ .removeAttribute(Attribute::NoImplicitFloat)
+ .removeAttribute(Attribute::Naked)
+ .removeAttribute(Attribute::InlineHint)
+ .removeAttribute(Attribute::StackAlignment)
+ .removeAttribute(Attribute::UWTable)
+ .removeAttribute(Attribute::NonLazyBind)
+ .removeAttribute(Attribute::ReturnsTwice)
+ .removeAttribute(Attribute::SanitizeAddress)
+ .removeAttribute(Attribute::SanitizeThread)
+ .removeAttribute(Attribute::SanitizeMemory)
+ .removeAttribute(Attribute::MinSize)
+ .removeAttribute(Attribute::NoDuplicate)
+ .removeAttribute(Attribute::NoBuiltin);
+}
+
+AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
+ // FIXME: Remove this in 4.0.
+ if (!Val) return *this;
+
+ for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
+ I = Attribute::AttrKind(I + 1)) {
+ if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
+ Attrs[I] = true;
+
+ if (I == Attribute::Alignment)
+ Alignment = 1ULL << ((A >> 16) - 1);
+ else if (I == Attribute::StackAlignment)
+ StackAlignment = 1ULL << ((A >> 26)-1);
+ }
+ }
+
+ return *this;
+}
+