X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FIR%2FAttributes.cpp;h=e48ebb133527f46e4a095b98b1b41e06127a5c7b;hb=77226a03dca98e6237c1068f2652fe41bea7b687;hp=f56eb7be9ce31b90fcd77b6755191aa8bc15ba5b;hpb=c22f4aa886443507f8406d30d118fdeeac6a8c6c;p=oota-llvm.git diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index f56eb7be9ce..e48ebb13352 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -16,7 +16,6 @@ #include "llvm/IR/Attributes.h" #include "AttributeImpl.h" #include "LLVMContextImpl.h" -#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Type.h" #include "llvm/Support/Atomic.h" @@ -28,24 +27,37 @@ using namespace llvm; //===----------------------------------------------------------------------===// -// Attribute Implementation +// Attribute Construction Methods //===----------------------------------------------------------------------===// -Attribute Attribute::get(LLVMContext &Context, AttrKind Kind) { - AttrBuilder B; - return Attribute::get(Context, B.addAttribute(Kind)); -} +Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, + uint64_t Val) { + LLVMContextImpl *pImpl = Context.pImpl; + FoldingSetNodeID ID; + ID.AddInteger(Kind); + if (Val) ID.AddInteger(Val); -Attribute Attribute::get(LLVMContext &Context, AttrBuilder &B) { - // If there are no attributes, return an empty Attribute class. - if (!B.hasAttributes()) - return Attribute(); + void *InsertPoint; + AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); - // Otherwise, build a key to look up the existing attributes. + if (!PA) { + // If we didn't find any existing attributes of the same shape then create a + // new one and insert it. + PA = !Val ? + new AttributeImpl(Context, Kind) : + new AttributeImpl(Context, Kind, Val); + pImpl->AttrsSet.InsertNode(PA, InsertPoint); + } + + // Return the Attribute that we found or created. + return Attribute(PA); +} + +Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; - ConstantInt *CI = ConstantInt::get(Type::getInt64Ty(Context), B.Raw()); - ID.AddPointer(CI); + ID.AddString(Kind); + if (!Val.empty()) ID.AddString(Val); void *InsertPoint; AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); @@ -53,127 +65,205 @@ Attribute Attribute::get(LLVMContext &Context, AttrBuilder &B) { if (!PA) { // If we didn't find any existing attributes of the same shape then create a // new one and insert it. - PA = new AttributeImpl(Context, CI); + PA = new AttributeImpl(Context, Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } - // Return the AttributesList that we found or created. + // Return the Attribute that we found or created. return Attribute(PA); } Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) { - AttrBuilder B; - return get(Context, B.addAlignmentAttr(Align)); + assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); + assert(Align <= 0x40000000 && "Alignment too large."); + return get(Context, Alignment, Align); } Attribute Attribute::getWithStackAlignment(LLVMContext &Context, uint64_t Align) { - AttrBuilder B; - return get(Context, B.addStackAlignmentAttr(Align)); + assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); + assert(Align <= 0x100 && "Alignment too large."); + return get(Context, StackAlignment, Align); } -bool Attribute::hasAttribute(AttrKind Val) const { - return pImpl && pImpl->hasAttribute(Val); +//===----------------------------------------------------------------------===// +// Attribute Accessor Methods +//===----------------------------------------------------------------------===// + +bool Attribute::isEnumAttribute() const { + return pImpl && pImpl->isEnumAttribute(); } -bool Attribute::hasAttributes() const { - return pImpl && pImpl->hasAttributes(); +bool Attribute::isAlignAttribute() const { + return pImpl && pImpl->isAlignAttribute(); +} + +bool Attribute::isStringAttribute() const { + return pImpl && pImpl->isStringAttribute(); +} + +Attribute::AttrKind Attribute::getKindAsEnum() const { + assert((isEnumAttribute() || isAlignAttribute()) && + "Invalid attribute type to get the kind as an enum!"); + return pImpl ? pImpl->getKindAsEnum() : None; +} + +uint64_t Attribute::getValueAsInt() const { + assert(isAlignAttribute() && + "Expected the attribute to be an alignment attribute!"); + return pImpl ? pImpl->getValueAsInt() : 0; +} + +StringRef Attribute::getKindAsString() const { + assert(isStringAttribute() && + "Invalid attribute type to get the kind as a string!"); + return pImpl ? pImpl->getKindAsString() : StringRef(); +} + +StringRef Attribute::getValueAsString() const { + assert(isStringAttribute() && + "Invalid attribute type to get the value as a string!"); + return pImpl ? pImpl->getValueAsString() : StringRef(); +} + +bool Attribute::hasAttribute(AttrKind Kind) const { + return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); +} + +bool Attribute::hasAttribute(StringRef Kind) const { + if (!isStringAttribute()) return false; + return pImpl && pImpl->hasAttribute(Kind); } /// This returns the alignment field of an attribute as a byte alignment value. unsigned Attribute::getAlignment() const { - if (!hasAttribute(Attribute::Alignment)) - return 0; - return pImpl->getAlignment(); + assert(hasAttribute(Attribute::Alignment) && + "Trying to get alignment from non-alignment attribute!"); + return pImpl->getValueAsInt(); } /// This returns the stack alignment field of an attribute as a byte alignment /// value. unsigned Attribute::getStackAlignment() const { - if (!hasAttribute(Attribute::StackAlignment)) - return 0; - return pImpl->getStackAlignment(); + assert(hasAttribute(Attribute::StackAlignment) && + "Trying to get alignment from non-alignment attribute!"); + return pImpl->getValueAsInt(); } -std::string Attribute::getAsString() const { - std::string Result; - if (hasAttribute(Attribute::ZExt)) - Result += "zeroext "; - if (hasAttribute(Attribute::SExt)) - Result += "signext "; - if (hasAttribute(Attribute::NoReturn)) - Result += "noreturn "; - if (hasAttribute(Attribute::NoUnwind)) - Result += "nounwind "; - if (hasAttribute(Attribute::UWTable)) - Result += "uwtable "; - if (hasAttribute(Attribute::ReturnsTwice)) - Result += "returns_twice "; +std::string Attribute::getAsString(bool InAttrGrp) const { + if (!pImpl) return ""; + + if (hasAttribute(Attribute::SanitizeAddress)) + return "sanitize_address"; + if (hasAttribute(Attribute::AlwaysInline)) + return "alwaysinline"; + if (hasAttribute(Attribute::ByVal)) + return "byval"; + if (hasAttribute(Attribute::InlineHint)) + return "inlinehint"; if (hasAttribute(Attribute::InReg)) - Result += "inreg "; + return "inreg"; + if (hasAttribute(Attribute::MinSize)) + return "minsize"; + if (hasAttribute(Attribute::Naked)) + return "naked"; + if (hasAttribute(Attribute::Nest)) + return "nest"; if (hasAttribute(Attribute::NoAlias)) - Result += "noalias "; + return "noalias"; + if (hasAttribute(Attribute::NoBuiltin)) + return "nobuiltin"; if (hasAttribute(Attribute::NoCapture)) - Result += "nocapture "; - if (hasAttribute(Attribute::StructRet)) - Result += "sret "; - if (hasAttribute(Attribute::ByVal)) - Result += "byval "; - if (hasAttribute(Attribute::Nest)) - Result += "nest "; + return "nocapture"; + if (hasAttribute(Attribute::NoDuplicate)) + return "noduplicate"; + if (hasAttribute(Attribute::NoImplicitFloat)) + return "noimplicitfloat"; + if (hasAttribute(Attribute::NoInline)) + return "noinline"; + if (hasAttribute(Attribute::NonLazyBind)) + return "nonlazybind"; + if (hasAttribute(Attribute::NoRedZone)) + return "noredzone"; + if (hasAttribute(Attribute::NoReturn)) + return "noreturn"; + if (hasAttribute(Attribute::NoUnwind)) + return "nounwind"; + if (hasAttribute(Attribute::OptimizeForSize)) + return "optsize"; if (hasAttribute(Attribute::ReadNone)) - Result += "readnone "; + return "readnone"; if (hasAttribute(Attribute::ReadOnly)) - Result += "readonly "; - if (hasAttribute(Attribute::OptimizeForSize)) - Result += "optsize "; - if (hasAttribute(Attribute::NoInline)) - Result += "noinline "; - if (hasAttribute(Attribute::InlineHint)) - Result += "inlinehint "; - if (hasAttribute(Attribute::AlwaysInline)) - Result += "alwaysinline "; + return "readonly"; + if (hasAttribute(Attribute::Returned)) + return "returned"; + if (hasAttribute(Attribute::ReturnsTwice)) + return "returns_twice"; + if (hasAttribute(Attribute::SExt)) + return "signext"; if (hasAttribute(Attribute::StackProtect)) - Result += "ssp "; + return "ssp"; if (hasAttribute(Attribute::StackProtectReq)) - Result += "sspreq "; + return "sspreq"; if (hasAttribute(Attribute::StackProtectStrong)) - Result += "sspstrong "; - if (hasAttribute(Attribute::NoRedZone)) - Result += "noredzone "; - if (hasAttribute(Attribute::NoImplicitFloat)) - Result += "noimplicitfloat "; - if (hasAttribute(Attribute::Naked)) - Result += "naked "; - if (hasAttribute(Attribute::NonLazyBind)) - Result += "nonlazybind "; - if (hasAttribute(Attribute::AddressSafety)) - Result += "address_safety "; - if (hasAttribute(Attribute::MinSize)) - Result += "minsize "; + return "sspstrong"; + if (hasAttribute(Attribute::StructRet)) + return "sret"; + if (hasAttribute(Attribute::SanitizeThread)) + return "sanitize_thread"; + if (hasAttribute(Attribute::SanitizeMemory)) + return "sanitize_memory"; + if (hasAttribute(Attribute::UWTable)) + return "uwtable"; + if (hasAttribute(Attribute::ZExt)) + return "zeroext"; + if (hasAttribute(Attribute::Cold)) + return "cold"; + + // FIXME: These should be output like this: + // + // align=4 + // alignstack=8 + // + if (hasAttribute(Attribute::Alignment)) { + std::string Result; + Result += "align"; + Result += (InAttrGrp) ? "=" : " "; + Result += utostr(getValueAsInt()); + return Result; + } + if (hasAttribute(Attribute::StackAlignment)) { - Result += "alignstack("; - Result += utostr(getStackAlignment()); - Result += ") "; + std::string Result; + Result += "alignstack"; + if (InAttrGrp) { + Result += "="; + Result += utostr(getValueAsInt()); + } else { + Result += "("; + Result += utostr(getValueAsInt()); + Result += ")"; + } + return Result; } - if (hasAttribute(Attribute::Alignment)) { - Result += "align "; - Result += utostr(getAlignment()); - Result += " "; + + // Convert target-dependent attributes to strings of the form: + // + // "kind" + // "kind" = "value" + // + if (isStringAttribute()) { + std::string Result; + Result += '\"' + getKindAsString().str() + '"'; + + StringRef Val = pImpl->getValueAsString(); + if (Val.empty()) return Result; + + Result += "=\"" + Val.str() + '"'; + return Result; } - if (hasAttribute(Attribute::NoDuplicate)) - Result += "noduplicate "; - // Trim the trailing space. - assert(!Result.empty() && "Unknown attribute!"); - Result.erase(Result.end()-1); - return Result; -} -bool Attribute::operator==(AttrKind K) const { - return pImpl && *pImpl == K; -} -bool Attribute::operator!=(AttrKind K) const { - return !(*this == K); + llvm_unreachable("Unknown attribute"); } bool Attribute::operator<(Attribute A) const { @@ -183,102 +273,94 @@ bool Attribute::operator<(Attribute A) const { return *pImpl < *A.pImpl; } -uint64_t Attribute::Raw() const { - return pImpl ? pImpl->Raw() : 0; -} - //===----------------------------------------------------------------------===// // AttributeImpl Definition //===----------------------------------------------------------------------===// -AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data) +AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind Kind) + : Context(C), Entry(new EnumAttributeEntry(Kind)) {} + +AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind Kind, + unsigned Align) : Context(C) { - Data = ConstantInt::get(Type::getInt64Ty(C), data); + assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) && + "Wrong kind for alignment attribute!"); + Entry = new AlignAttributeEntry(Kind, Align); } -AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data, - ArrayRef values) - : Context(C) { - Data = ConstantInt::get(Type::getInt64Ty(C), data); - Vals.reserve(values.size()); - Vals.append(values.begin(), values.end()); + +AttributeImpl::AttributeImpl(LLVMContext &C, StringRef Kind, StringRef Val) + : Context(C), Entry(new StringAttributeEntry(Kind, Val)) {} + +AttributeImpl::~AttributeImpl() { + delete Entry; } -AttributeImpl::AttributeImpl(LLVMContext &C, StringRef data) - : Context(C) { - Data = ConstantDataArray::getString(C, data); + +bool AttributeImpl::isEnumAttribute() const { + return isa(Entry); } -bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { - return (Raw() & getAttrMask(A)) != 0; +bool AttributeImpl::isAlignAttribute() const { + return isa(Entry); } -bool AttributeImpl::hasAttributes() const { - return Raw() != 0; +bool AttributeImpl::isStringAttribute() const { + return isa(Entry); } -uint64_t AttributeImpl::getAlignment() const { - uint64_t Mask = Raw() & getAttrMask(Attribute::Alignment); - return 1ULL << ((Mask >> 16) - 1); +bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { + if (isStringAttribute()) return false; + return getKindAsEnum() == A; } -uint64_t AttributeImpl::getStackAlignment() const { - uint64_t Mask = Raw() & getAttrMask(Attribute::StackAlignment); - return 1ULL << ((Mask >> 26) - 1); +bool AttributeImpl::hasAttribute(StringRef Kind) const { + if (!isStringAttribute()) return false; + return getKindAsString() == Kind; } -bool AttributeImpl::operator==(Attribute::AttrKind Kind) const { - if (ConstantInt *CI = dyn_cast(Data)) - return CI->getZExtValue() == Kind; - return false; +Attribute::AttrKind AttributeImpl::getKindAsEnum() const { + if (EnumAttributeEntry *E = dyn_cast(Entry)) + return E->getEnumKind(); + return cast(Entry)->getEnumKind(); } -bool AttributeImpl::operator!=(Attribute::AttrKind Kind) const { - return !(*this == Kind); + +uint64_t AttributeImpl::getValueAsInt() const { + return cast(Entry)->getAlignment(); } -bool AttributeImpl::operator==(StringRef Kind) const { - if (ConstantDataArray *CDA = dyn_cast(Data)) - if (CDA->isString()) - return CDA->getAsString() == Kind; - return false; +StringRef AttributeImpl::getKindAsString() const { + return cast(Entry)->getStringKind(); } -bool AttributeImpl::operator!=(StringRef Kind) const { - return !(*this == Kind); +StringRef AttributeImpl::getValueAsString() const { + return cast(Entry)->getStringValue(); } bool AttributeImpl::operator<(const AttributeImpl &AI) const { - if (!Data && !AI.Data) return false; - if (!Data && AI.Data) return true; - if (Data && !AI.Data) return false; - - ConstantInt *ThisCI = dyn_cast(Data); - ConstantInt *ThatCI = dyn_cast(AI.Data); - - ConstantDataArray *ThisCDA = dyn_cast(Data); - ConstantDataArray *ThatCDA = dyn_cast(AI.Data); - - if (ThisCI && ThatCI) - return ThisCI->getZExtValue() < ThatCI->getZExtValue(); - - if (ThisCI && ThatCDA) - return true; - - if (ThisCDA && ThatCI) - return false; + // This sorts the attributes with Attribute::AttrKinds coming first (sorted + // relative to their enum value) and then strings. + if (isEnumAttribute()) { + if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); + if (AI.isAlignAttribute()) return true; + if (AI.isStringAttribute()) return true; + } - return ThisCDA->getAsString() < ThatCDA->getAsString(); -} + if (isAlignAttribute()) { + if (AI.isEnumAttribute()) return false; + if (AI.isAlignAttribute()) return getValueAsInt() < AI.getValueAsInt(); + if (AI.isStringAttribute()) return true; + } -uint64_t AttributeImpl::Raw() const { - // FIXME: Remove this. - return cast(Data)->getZExtValue(); + if (AI.isEnumAttribute()) return false; + if (AI.isAlignAttribute()) return false; + if (getKindAsString() == AI.getKindAsString()) + return getValueAsString() < AI.getValueAsString(); + return getKindAsString() < AI.getKindAsString(); } uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { // FIXME: Remove this. switch (Val) { case Attribute::EndAttrKinds: - case Attribute::AttrKindEmptyKey: - case Attribute::AttrKindTombstoneKey: llvm_unreachable("Synthetic enumerators which should never get here"); case Attribute::None: return 0; @@ -308,10 +390,15 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::ReturnsTwice: return 1 << 29; case Attribute::UWTable: return 1 << 30; case Attribute::NonLazyBind: return 1U << 31; - case Attribute::AddressSafety: return 1ULL << 32; + case Attribute::SanitizeAddress: return 1ULL << 32; case Attribute::MinSize: return 1ULL << 33; case Attribute::NoDuplicate: return 1ULL << 34; case Attribute::StackProtectStrong: return 1ULL << 35; + case Attribute::SanitizeThread: return 1ULL << 36; + case Attribute::SanitizeMemory: return 1ULL << 37; + case Attribute::NoBuiltin: return 1ULL << 38; + case Attribute::Returned: return 1ULL << 39; + case Attribute::Cold: return 1ULL << 40; } llvm_unreachable("Unsupported attribute type"); } @@ -330,7 +417,7 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, FoldingSetNodeID ID; SmallVector SortedAttrs(Attrs.begin(), Attrs.end()); - std::sort(SortedAttrs.begin(), SortedAttrs.end()); + array_pod_sort(SortedAttrs.begin(), SortedAttrs.end()); for (SmallVectorImpl::iterator I = SortedAttrs.begin(), E = SortedAttrs.end(); I != E; ++I) @@ -351,20 +438,93 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, return PA; } +bool AttributeSetNode::hasAttribute(Attribute::AttrKind Kind) const { + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) + if (I->hasAttribute(Kind)) + return true; + return false; +} + +bool AttributeSetNode::hasAttribute(StringRef Kind) const { + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) + if (I->hasAttribute(Kind)) + return true; + return false; +} + +Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) + if (I->hasAttribute(Kind)) + return *I; + return Attribute(); +} + +Attribute AttributeSetNode::getAttribute(StringRef Kind) const { + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) + if (I->hasAttribute(Kind)) + return *I; + return Attribute(); +} + +unsigned AttributeSetNode::getAlignment() const { + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) + if (I->hasAttribute(Attribute::Alignment)) + return I->getAlignment(); + return 0; +} + +unsigned AttributeSetNode::getStackAlignment() const { + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) + if (I->hasAttribute(Attribute::StackAlignment)) + return I->getStackAlignment(); + return 0; +} + +std::string AttributeSetNode::getAsString(bool InAttrGrp) const { + std::string Str; + for (SmallVectorImpl::const_iterator I = AttrList.begin(), + E = AttrList.end(); I != E; ++I) { + if (I != AttrList.begin()) + Str += ' '; + Str += I->getAsString(InAttrGrp); + } + return Str; +} + //===----------------------------------------------------------------------===// // AttributeSetImpl Definition //===----------------------------------------------------------------------===// -uint64_t AttributeSetImpl::Raw(uint64_t Index) const { +uint64_t AttributeSetImpl::Raw(unsigned Index) const { for (unsigned I = 0, E = getNumAttributes(); I != E; ++I) { if (getSlotIndex(I) != Index) continue; const AttributeSetNode *ASN = AttrNodes[I].second; - AttrBuilder B; + uint64_t Mask = 0; for (AttributeSetNode::const_iterator II = ASN->begin(), - IE = ASN->end(); II != IE; ++II) - B.addAttributes(*II); - return B.Raw(); + IE = ASN->end(); II != IE; ++II) { + Attribute Attr = *II; + + // This cannot handle string attributes. + if (Attr.isStringAttribute()) continue; + + Attribute::AttrKind Kind = Attr.getKindAsEnum(); + + if (Kind == Attribute::Alignment) + Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16; + else if (Kind == Attribute::StackAlignment) + Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26; + else + Mask |= AttributeImpl::getAttrMask(Kind); + } + + return Mask; } return 0; @@ -374,9 +534,9 @@ uint64_t AttributeSetImpl::Raw(uint64_t Index) const { // AttributeSet Construction and Mutation Methods //===----------------------------------------------------------------------===// -AttributeSet AttributeSet::getImpl(LLVMContext &C, - ArrayRef > Attrs) { +AttributeSet +AttributeSet::getImpl(LLVMContext &C, + ArrayRef > Attrs) { LLVMContextImpl *pImpl = C.pImpl; FoldingSetNodeID ID; AttributeSetImpl::Profile(ID, Attrs); @@ -405,7 +565,7 @@ AttributeSet AttributeSet::get(LLVMContext &C, for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { assert((!i || Attrs[i-1].first <= Attrs[i].first) && "Misordered Attributes list!"); - assert(Attrs[i].second.hasAttributes() && + assert(!Attrs[i].second.hasAttribute(Attribute::None) && "Pointless attribute!"); } #endif @@ -417,7 +577,7 @@ AttributeSet AttributeSet::get(LLVMContext &C, E = Attrs.end(); I != E; ) { unsigned Index = I->first; SmallVector AttrVec; - while (I->first == Index && I != E) { + while (I != E && I->first == Index) { AttrVec.push_back(I->second); ++I; } @@ -439,19 +599,41 @@ AttributeSet AttributeSet::get(LLVMContext &C, return getImpl(C, Attrs); } -AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, AttrBuilder &B) { +AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, AttrBuilder &B) { if (!B.hasAttributes()) return AttributeSet(); - return get(C, ArrayRef >( - std::make_pair(Idx, Attribute::get(C, B)))); + + // Add target-independent attributes. + SmallVector, 8> Attrs; + for (Attribute::AttrKind Kind = Attribute::None; + Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) { + 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 + Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind))); + } + + // Add target-dependent (string) attributes. + for (AttrBuilder::td_iterator I = B.td_begin(), E = B.td_end(); + I != E; ++I) + Attrs.push_back(std::make_pair(Index, Attribute::get(C, I->first,I->second))); + + return get(C, Attrs); } -AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, ArrayRef Kind) { SmallVector, 8> Attrs; for (ArrayRef::iterator I = Kind.begin(), E = Kind.end(); I != E; ++I) - Attrs.push_back(std::make_pair(Idx, Attribute::get(C, *I))); + Attrs.push_back(std::make_pair(Index, Attribute::get(C, *I))); return get(C, Attrs); } @@ -468,12 +650,20 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef Attrs) { return getImpl(C, AttrNodeVec); } -AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const { - return addAttributes(C, Idx, AttributeSet::get(C, Idx, Attr)); + if (hasAttribute(Index, Attr)) return *this; + return addAttributes(C, Index, AttributeSet::get(C, Index, Attr)); +} + +AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, + StringRef Kind) const { + llvm::AttrBuilder B; + B.addAttribute(Kind); + return addAttributes(C, Index, AttributeSet::get(C, Index, B)); } -AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const { if (!pImpl) return Attrs; if (!Attrs.pImpl) return *this; @@ -481,8 +671,8 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, #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 = getParamAlignment(Idx); - unsigned NewAlign = Attrs.getParamAlignment(Idx); + unsigned OldAlign = getParamAlignment(Index); + unsigned NewAlign = Attrs.getParamAlignment(Index); assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && "Attempt to change alignment!"); #endif @@ -493,8 +683,8 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, 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++); + if (getSlotIndex(I) >= Index) { + if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); break; } LastIndex = I + 1; @@ -503,17 +693,17 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, // Now add the attribute into the correct slot. There may already be an // AttributeSet there. - AttrBuilder B(AS, Idx); + AttrBuilder B(AS, Index); for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) - if (Attrs.getSlotIndex(I) == Idx) { + if (Attrs.getSlotIndex(I) == Index) { for (AttributeSetImpl::const_iterator II = Attrs.pImpl->begin(I), IE = Attrs.pImpl->end(I); II != IE; ++II) - B.addAttributes(*II); + B.addAttribute(*II); break; } - AttrSet.push_back(AttributeSet::get(C, Idx, B)); + AttrSet.push_back(AttributeSet::get(C, Index, B)); // Add the remaining attribute slots. for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) @@ -522,12 +712,13 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, return get(C, AttrSet); } -AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const { - return removeAttributes(C, Idx, AttributeSet::get(C, Idx, Attr)); + if (!hasAttribute(Index, Attr)) return *this; + return removeAttributes(C, Index, AttributeSet::get(C, Index, Attr)); } -AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const { if (!pImpl) return AttributeSet(); if (!Attrs.pImpl) return *this; @@ -535,7 +726,7 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, #ifndef NDEBUG // 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.hasAttribute(Idx, Attribute::Alignment) && + assert(!Attrs.hasAttribute(Index, Attribute::Alignment) && "Attempt to change alignment!"); #endif @@ -545,27 +736,25 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, 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++); + if (getSlotIndex(I) >= Index) { + if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); break; } LastIndex = I + 1; AttrSet.push_back(getSlotAttributes(I)); } - // Now add the attribute into the correct slot. There may already be an + // Now remove the attribute from the correct slot. There may already be an // AttributeSet there. - AttrBuilder B(AS, Idx); + AttrBuilder B(AS, Index); 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.removeAttributes(*II); + if (Attrs.getSlotIndex(I) == Index) { + B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Index); break; } - AttrSet.push_back(AttributeSet::get(C, Idx, B)); + AttrSet.push_back(AttributeSet::get(C, Index, B)); // Add the remaining attribute slots. for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) @@ -578,18 +767,22 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, // AttributeSet Accessor Methods //===----------------------------------------------------------------------===// -AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const { - return pImpl && hasAttributes(Idx) ? +LLVMContext &AttributeSet::getContext() const { + return pImpl->getContext(); +} + +AttributeSet AttributeSet::getParamAttributes(unsigned Index) const { + return pImpl && hasAttributes(Index) ? AttributeSet::get(pImpl->getContext(), - ArrayRef >( - std::make_pair(Idx, getAttributes(Idx)))) : + ArrayRef >( + std::make_pair(Index, getAttributes(Index)))) : AttributeSet(); } AttributeSet AttributeSet::getRetAttributes() const { return pImpl && hasAttributes(ReturnIndex) ? AttributeSet::get(pImpl->getContext(), - ArrayRef >( + ArrayRef >( std::make_pair(ReturnIndex, getAttributes(ReturnIndex)))) : AttributeSet(); @@ -598,18 +791,25 @@ AttributeSet AttributeSet::getRetAttributes() const { AttributeSet AttributeSet::getFnAttributes() const { return pImpl && hasAttributes(FunctionIndex) ? AttributeSet::get(pImpl->getContext(), - ArrayRef >( + ArrayRef >( std::make_pair(FunctionIndex, getAttributes(FunctionIndex)))) : AttributeSet(); } bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{ - return getAttributes(Index).hasAttribute(Kind); + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->hasAttribute(Kind) : false; +} + +bool AttributeSet::hasAttribute(unsigned Index, StringRef Kind) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->hasAttribute(Kind) : false; } bool AttributeSet::hasAttributes(unsigned Index) const { - return getAttributes(Index).hasAttributes(); + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->hasAttributes() : false; } /// \brief Return true if the specified attribute is set for at least one @@ -626,36 +826,56 @@ bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { return false; } -unsigned AttributeSet::getParamAlignment(unsigned Idx) const { - return getAttributes(Idx).getAlignment(); +Attribute AttributeSet::getAttribute(unsigned Index, + Attribute::AttrKind Kind) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getAttribute(Kind) : Attribute(); +} + +Attribute AttributeSet::getAttribute(unsigned Index, + StringRef Kind) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getAttribute(Kind) : Attribute(); +} + +unsigned AttributeSet::getParamAlignment(unsigned Index) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getAlignment() : 0; } unsigned AttributeSet::getStackAlignment(unsigned Index) const { - return getAttributes(Index).getStackAlignment(); + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getStackAlignment() : 0; } -std::string AttributeSet::getAsString(unsigned Index) const { - return getAttributes(Index).getAsString(); +std::string AttributeSet::getAsString(unsigned Index, + bool InAttrGrp) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getAsString(InAttrGrp) : std::string(""); } /// \brief The attributes for the specified index are returned. -/// -/// FIXME: This shouldn't return 'Attribute'. -Attribute AttributeSet::getAttributes(unsigned Idx) const { - if (pImpl == 0) return Attribute(); +AttributeSetNode *AttributeSet::getAttributes(unsigned Index) const { + if (!pImpl) return 0; - // Loop through to find the attribute we want. - for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) { - if (pImpl->getSlotIndex(I) != Idx) continue; + // Loop through to find the attribute node we want. + for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) + if (pImpl->getSlotIndex(I) == Index) + return pImpl->getSlotNode(I); - AttrBuilder B; - for (AttributeSetImpl::const_iterator II = pImpl->begin(I), - IE = pImpl->end(I); II != IE; ++II) - B.addAttributes(*II); - return Attribute::get(pImpl->getContext(), B); - } + return 0; +} - return Attribute(); +AttributeSet::iterator AttributeSet::begin(unsigned Slot) const { + if (!pImpl) + return ArrayRef().begin(); + return pImpl->begin(Slot); +} + +AttributeSet::iterator AttributeSet::end(unsigned Slot) const { + if (!pImpl) + return ArrayRef().end(); + return pImpl->end(Slot); } //===----------------------------------------------------------------------===// @@ -669,7 +889,7 @@ unsigned AttributeSet::getNumSlots() const { return pImpl ? pImpl->getNumAttributes() : 0; } -uint64_t AttributeSet::getSlotIndex(unsigned Slot) const { +unsigned AttributeSet::getSlotIndex(unsigned Slot) const { assert(pImpl && Slot < pImpl->getNumAttributes() && "Slot # out of range!"); return pImpl->getSlotIndex(Slot); @@ -706,52 +926,60 @@ void AttributeSet::dump() const { // AttrBuilder Method Implementations //===----------------------------------------------------------------------===// -AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Idx) - : Alignment(0), StackAlignment(0) { +AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) + : Attrs(0), Alignment(0), StackAlignment(0) { AttributeSetImpl *pImpl = AS.pImpl; if (!pImpl) return; - AttrBuilder B; - for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) { - if (pImpl->getSlotIndex(I) != Idx) continue; + if (pImpl->getSlotIndex(I) != Index) continue; - for (AttributeSetNode::const_iterator II = pImpl->begin(I), + for (AttributeSetImpl::const_iterator II = pImpl->begin(I), IE = pImpl->end(I); II != IE; ++II) - B.addAttributes(*II); + addAttribute(*II); break; } - - if (!B.hasAttributes()) return; - - uint64_t Mask = B.Raw(); - - for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; - I = Attribute::AttrKind(I + 1)) { - if (uint64_t A = (Mask & AttributeImpl::getAttrMask(I))) { - Attrs.insert(I); - - if (I == Attribute::Alignment) - Alignment = 1ULL << ((A >> 16) - 1); - else if (I == Attribute::StackAlignment) - StackAlignment = 1ULL << ((A >> 26)-1); - } - } } void AttrBuilder::clear() { - Attrs.clear(); + Attrs.reset(); Alignment = StackAlignment = 0; } AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { - Attrs.insert(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) { - Attrs.erase(Val); + assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); + Attrs[Val] = false; + if (Val == Attribute::Alignment) Alignment = 0; else if (Val == Attribute::StackAlignment) @@ -760,46 +988,52 @@ 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); +AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) { + unsigned Slot = ~0U; + for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I) + if (A.getSlotIndex(I) == Index) { + Slot = I; + break; + } - if (Attr.getAlignment()) - Alignment = Attr.getAlignment(); - if (Attr.getStackAlignment()) - StackAlignment = Attr.getStackAlignment(); - return *this; -} + assert(Slot != ~0U && "Couldn't find index in AttributeSet!"); -AttrBuilder &AttrBuilder::removeAttributes(Attribute A) { - uint64_t Mask = A.Raw(); + for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { + Attribute Attr = *I; + if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { + Attribute::AttrKind Kind = I->getKindAsEnum(); + Attrs[Kind] = false; - 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) + if (Kind == Attribute::Alignment) Alignment = 0; - else if (I == Attribute::StackAlignment) + else if (Kind == Attribute::StackAlignment) StackAlignment = 0; + } else { + assert(Attr.isStringAttribute() && "Invalid attribute type!"); + std::map::iterator + Iter = TargetDepAttrs.find(Attr.getKindAsString()); + if (Iter != TargetDepAttrs.end()) + TargetDepAttrs.erase(Iter); } } return *this; } +AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { + std::map::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.insert(Attribute::Alignment); + Attrs[Attribute::Alignment] = true; Alignment = Align; return *this; } @@ -811,21 +1045,59 @@ AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); assert(Align <= 0x100 && "Alignment too large."); - Attrs.insert(Attribute::StackAlignment); + Attrs[Attribute::StackAlignment] = true; StackAlignment = Align; return *this; } -bool AttrBuilder::contains(Attribute::AttrKind A) const { - return Attrs.count(A); +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.empty(); + return !Attrs.none() || !TargetDepAttrs.empty(); } -bool AttrBuilder::hasAttributes(const Attribute &A) const { - return Raw() & A.Raw(); +bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const { + unsigned Slot = ~0U; + for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I) + if (A.getSlotIndex(I) == Index) { + Slot = I; + break; + } + + assert(Slot != ~0U && "Couldn't find the index!"); + + for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); + 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 { @@ -833,16 +1105,25 @@ bool AttrBuilder::hasAlignmentAttr() const { } bool AttrBuilder::operator==(const AttrBuilder &B) { - SmallVector This(Attrs.begin(), Attrs.end()); - SmallVector That(B.Attrs.begin(), B.Attrs.end()); - return This == That; + 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; } 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.insert(I); + Attrs[I] = true; if (I == Attribute::Alignment) Alignment = 1ULL << ((A >> 16) - 1); @@ -854,29 +1135,12 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { return *this; } -uint64_t AttrBuilder::Raw() const { - uint64_t Mask = 0; - - for (DenseSet::const_iterator I = Attrs.begin(), - E = Attrs.end(); I != E; ++I) { - Attribute::AttrKind Kind = *I; - - if (Kind == Attribute::Alignment) - Mask |= (Log2_32(Alignment) + 1) << 16; - else if (Kind == Attribute::StackAlignment) - Mask |= (Log2_32(StackAlignment) + 1) << 26; - else - Mask |= AttributeImpl::getAttrMask(Kind); - } - - return Mask; -} - //===----------------------------------------------------------------------===// // AttributeFuncs Function Defintions //===----------------------------------------------------------------------===// -Attribute AttributeFuncs::typeIncompatible(Type *Ty) { +/// \brief Which attributes cannot be applied to a type. +AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { AttrBuilder Incompatible; if (!Ty->isIntegerTy()) @@ -892,45 +1156,5 @@ Attribute AttributeFuncs::typeIncompatible(Type *Ty) { .addAttribute(Attribute::NoCapture) .addAttribute(Attribute::StructRet); - return Attribute::get(Ty->getContext(), Incompatible); -} - -/// \brief This returns an integer containing an encoding of all the LLVM -/// attributes found in the given attribute bitset. Any change to this encoding -/// is a breaking change to bitcode compatibility. -uint64_t AttributeFuncs::encodeLLVMAttributesForBitcode(AttributeSet Attrs, - unsigned Index) { - // FIXME: It doesn't make sense to store the alignment information as an - // expanded out value, we should store it as a log2 value. However, we can't - // just change that here without breaking bitcode compatibility. If this ever - // becomes a problem in practice, we should introduce new tag numbers in the - // bitcode file and have those tags use a more efficiently encoded alignment - // field. - - // Store the alignment in the bitcode as a 16-bit raw value instead of a 5-bit - // log2 encoded value. Shift the bits above the alignment up by 11 bits. - uint64_t EncodedAttrs = Attrs.Raw(Index) & 0xffff; - if (Attrs.hasAttribute(Index, Attribute::Alignment)) - EncodedAttrs |= Attrs.getParamAlignment(Index) << 16; - EncodedAttrs |= (Attrs.Raw(Index) & (0xffffULL << 21)) << 11; - return EncodedAttrs; -} - -/// \brief This returns an attribute bitset containing the LLVM attributes that -/// have been decoded from the given integer. This function must stay in sync -/// with 'encodeLLVMAttributesForBitcode'. -Attribute AttributeFuncs::decodeLLVMAttributesForBitcode(LLVMContext &C, - uint64_t EncodedAttrs){ - // The alignment is stored as a 16-bit raw value from bits 31--16. We shift - // the bits above 31 down by 11 bits. - unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16; - assert((!Alignment || isPowerOf2_32(Alignment)) && - "Alignment must be a power of two."); - - AttrBuilder B(EncodedAttrs & 0xffff); - if (Alignment) - B.addAlignmentAttr(Alignment); - B.addRawValue((EncodedAttrs & (0xffffULL << 32)) >> 11); - return Attribute::get(C, B); + return AttributeSet::get(Ty->getContext(), Index, Incompatible); } -