Convert getAttributes() to return an AttributeSetNode.

The AttributeSetNode contains all of the attributes. This removes one (hopefully
last) use of the Attribute class as a container of multiple attributes.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173761 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling
2013-01-29 03:20:31 +00:00
parent 3a57c37964
commit 606c8e36df
5 changed files with 120 additions and 75 deletions

View File

@ -180,7 +180,7 @@ private:
/// \brief The attributes for the specified index are returned. Attributes /// \brief The attributes for the specified index are returned. Attributes
/// for the result are denoted with Idx = 0. /// for the result are denoted with Idx = 0.
Attribute getAttributes(unsigned Idx) const; AttributeSetNode *getAttributes(unsigned Idx) const;
/// \brief Create an AttributeSet with the specified parameters in it. /// \brief Create an AttributeSet with the specified parameters in it.
static AttributeSet get(LLVMContext &C, static AttributeSet get(LLVMContext &C,

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/FoldingSet.h"
#include "llvm/IR/Attributes.h" #include "llvm/IR/Attributes.h"
#include <string>
namespace llvm { namespace llvm {
@ -92,6 +93,13 @@ class AttributeSetNode : public FoldingSetNode {
public: public:
static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
bool hasAttribute(Attribute::AttrKind Kind) const;
bool hasAttributes() const { return !AttrList.empty(); }
unsigned getAlignment() const;
unsigned getStackAlignment() const;
std::string getAsString() const;
typedef SmallVectorImpl<Attribute>::iterator iterator; typedef SmallVectorImpl<Attribute>::iterator iterator;
typedef SmallVectorImpl<Attribute>::const_iterator const_iterator; typedef SmallVectorImpl<Attribute>::const_iterator const_iterator;
@ -152,6 +160,12 @@ public:
return AttributeSet::get(Context, AttrNodes[Slot]); return AttributeSet::get(Context, AttrNodes[Slot]);
} }
/// \brief Retrieve the attribute set node for the given "slot" in the
/// AttrNode list.
AttributeSetNode *getSlotNode(unsigned Slot) const {
return AttrNodes[Slot].second;
}
typedef AttributeSetNode::iterator iterator; typedef AttributeSetNode::iterator iterator;
typedef AttributeSetNode::const_iterator const_iterator; typedef AttributeSetNode::const_iterator const_iterator;

View File

@ -99,77 +99,78 @@ unsigned Attribute::getStackAlignment() const {
} }
std::string Attribute::getAsString() const { std::string Attribute::getAsString() const {
std::string Result;
if (hasAttribute(Attribute::ZExt)) if (hasAttribute(Attribute::ZExt))
Result += "zeroext "; return "zeroext";
if (hasAttribute(Attribute::SExt)) if (hasAttribute(Attribute::SExt))
Result += "signext "; return "signext";
if (hasAttribute(Attribute::NoReturn)) if (hasAttribute(Attribute::NoReturn))
Result += "noreturn "; return "noreturn";
if (hasAttribute(Attribute::NoUnwind)) if (hasAttribute(Attribute::NoUnwind))
Result += "nounwind "; return "nounwind";
if (hasAttribute(Attribute::UWTable)) if (hasAttribute(Attribute::UWTable))
Result += "uwtable "; return "uwtable";
if (hasAttribute(Attribute::ReturnsTwice)) if (hasAttribute(Attribute::ReturnsTwice))
Result += "returns_twice "; return "returns_twice";
if (hasAttribute(Attribute::InReg)) if (hasAttribute(Attribute::InReg))
Result += "inreg "; return "inreg";
if (hasAttribute(Attribute::NoAlias)) if (hasAttribute(Attribute::NoAlias))
Result += "noalias "; return "noalias";
if (hasAttribute(Attribute::NoCapture)) if (hasAttribute(Attribute::NoCapture))
Result += "nocapture "; return "nocapture";
if (hasAttribute(Attribute::StructRet)) if (hasAttribute(Attribute::StructRet))
Result += "sret "; return "sret";
if (hasAttribute(Attribute::ByVal)) if (hasAttribute(Attribute::ByVal))
Result += "byval "; return "byval";
if (hasAttribute(Attribute::Nest)) if (hasAttribute(Attribute::Nest))
Result += "nest "; return "nest";
if (hasAttribute(Attribute::ReadNone)) if (hasAttribute(Attribute::ReadNone))
Result += "readnone "; return "readnone";
if (hasAttribute(Attribute::ReadOnly)) if (hasAttribute(Attribute::ReadOnly))
Result += "readonly "; return "readonly";
if (hasAttribute(Attribute::OptimizeForSize)) if (hasAttribute(Attribute::OptimizeForSize))
Result += "optsize "; return "optsize";
if (hasAttribute(Attribute::NoInline)) if (hasAttribute(Attribute::NoInline))
Result += "noinline "; return "noinline";
if (hasAttribute(Attribute::InlineHint)) if (hasAttribute(Attribute::InlineHint))
Result += "inlinehint "; return "inlinehint";
if (hasAttribute(Attribute::AlwaysInline)) if (hasAttribute(Attribute::AlwaysInline))
Result += "alwaysinline "; return "alwaysinline";
if (hasAttribute(Attribute::StackProtect)) if (hasAttribute(Attribute::StackProtect))
Result += "ssp "; return "ssp";
if (hasAttribute(Attribute::StackProtectReq)) if (hasAttribute(Attribute::StackProtectReq))
Result += "sspreq "; return "sspreq";
if (hasAttribute(Attribute::StackProtectStrong)) if (hasAttribute(Attribute::StackProtectStrong))
Result += "sspstrong "; return "sspstrong";
if (hasAttribute(Attribute::NoRedZone)) if (hasAttribute(Attribute::NoRedZone))
Result += "noredzone "; return "noredzone";
if (hasAttribute(Attribute::NoImplicitFloat)) if (hasAttribute(Attribute::NoImplicitFloat))
Result += "noimplicitfloat "; return "noimplicitfloat";
if (hasAttribute(Attribute::Naked)) if (hasAttribute(Attribute::Naked))
Result += "naked "; return "naked";
if (hasAttribute(Attribute::NonLazyBind)) if (hasAttribute(Attribute::NonLazyBind))
Result += "nonlazybind "; return "nonlazybind";
if (hasAttribute(Attribute::AddressSafety)) if (hasAttribute(Attribute::AddressSafety))
Result += "address_safety "; return "address_safety";
if (hasAttribute(Attribute::MinSize)) if (hasAttribute(Attribute::MinSize))
Result += "minsize "; return "minsize";
if (hasAttribute(Attribute::StackAlignment)) { if (hasAttribute(Attribute::StackAlignment)) {
std::string Result;
Result += "alignstack("; Result += "alignstack(";
Result += utostr(getStackAlignment()); Result += utostr(getStackAlignment());
Result += ")"; Result += ")";
return Result;
} }
if (hasAttribute(Attribute::Alignment)) { if (hasAttribute(Attribute::Alignment)) {
std::string Result;
Result += "align "; Result += "align ";
Result += utostr(getAlignment()); Result += utostr(getAlignment());
Result += ""; Result += "";
return Result;
} }
if (hasAttribute(Attribute::NoDuplicate)) if (hasAttribute(Attribute::NoDuplicate))
Result += "noduplicate "; return "noduplicate";
// Trim the trailing space.
assert(!Result.empty() && "Unknown attribute!"); llvm_unreachable("Unknown attribute");
Result.erase(Result.end()-1);
return Result;
} }
bool Attribute::operator==(AttrKind K) const { bool Attribute::operator==(AttrKind K) const {
@ -354,6 +355,40 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
return PA; return PA;
} }
bool AttributeSetNode::hasAttribute(Attribute::AttrKind Kind) const {
for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(),
E = AttrList.end(); I != E; ++I)
if (I->hasAttribute(Kind))
return true;
return false;
}
unsigned AttributeSetNode::getAlignment() const {
for (SmallVectorImpl<Attribute>::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<Attribute>::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() const {
std::string Str = "";
for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(),
E = AttrList.end(); I != E; ++I) {
if (I != AttrList.begin()) Str += " ";
Str += I->getAsString();
}
return Str;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// AttributeSetImpl Definition // AttributeSetImpl Definition
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -597,7 +632,7 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx,
AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const { AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const {
return pImpl && hasAttributes(Idx) ? return pImpl && hasAttributes(Idx) ?
AttributeSet::get(pImpl->getContext(), AttributeSet::get(pImpl->getContext(),
ArrayRef<std::pair<unsigned, Attribute> >( ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
std::make_pair(Idx, getAttributes(Idx)))) : std::make_pair(Idx, getAttributes(Idx)))) :
AttributeSet(); AttributeSet();
} }
@ -605,7 +640,7 @@ AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const {
AttributeSet AttributeSet::getRetAttributes() const { AttributeSet AttributeSet::getRetAttributes() const {
return pImpl && hasAttributes(ReturnIndex) ? return pImpl && hasAttributes(ReturnIndex) ?
AttributeSet::get(pImpl->getContext(), AttributeSet::get(pImpl->getContext(),
ArrayRef<std::pair<unsigned, Attribute> >( ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
std::make_pair(ReturnIndex, std::make_pair(ReturnIndex,
getAttributes(ReturnIndex)))) : getAttributes(ReturnIndex)))) :
AttributeSet(); AttributeSet();
@ -614,18 +649,20 @@ AttributeSet AttributeSet::getRetAttributes() const {
AttributeSet AttributeSet::getFnAttributes() const { AttributeSet AttributeSet::getFnAttributes() const {
return pImpl && hasAttributes(FunctionIndex) ? return pImpl && hasAttributes(FunctionIndex) ?
AttributeSet::get(pImpl->getContext(), AttributeSet::get(pImpl->getContext(),
ArrayRef<std::pair<unsigned, Attribute> >( ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
std::make_pair(FunctionIndex, std::make_pair(FunctionIndex,
getAttributes(FunctionIndex)))) : getAttributes(FunctionIndex)))) :
AttributeSet(); AttributeSet();
} }
bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{ 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::hasAttributes(unsigned Index) const { 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 /// \brief Return true if the specified attribute is set for at least one
@ -642,36 +679,31 @@ bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const {
return false; return false;
} }
unsigned AttributeSet::getParamAlignment(unsigned Idx) const { unsigned AttributeSet::getParamAlignment(unsigned Index) const {
return getAttributes(Idx).getAlignment(); AttributeSetNode *ASN = getAttributes(Index);
return ASN ? ASN->getAlignment() : 0;
} }
unsigned AttributeSet::getStackAlignment(unsigned Index) const { 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 { std::string AttributeSet::getAsString(unsigned Index) const {
return getAttributes(Index).getAsString(); AttributeSetNode *ASN = getAttributes(Index);
return ASN ? ASN->getAsString() : std::string("");
} }
/// \brief The attributes for the specified index are returned. /// \brief The attributes for the specified index are returned.
/// AttributeSetNode *AttributeSet::getAttributes(unsigned Idx) const {
/// FIXME: This shouldn't return 'Attribute'. if (!pImpl) return 0;
Attribute AttributeSet::getAttributes(unsigned Idx) const {
if (pImpl == 0) return Attribute();
// Loop through to find the attribute we want. // Loop through to find the attribute node we want.
for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) { for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I)
if (pImpl->getSlotIndex(I) != Idx) continue; if (pImpl->getSlotIndex(I) == Idx)
return pImpl->getSlotNode(I);
AttrBuilder B; return 0;
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 Attribute();
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -948,9 +980,8 @@ void AttributeFuncs::decodeLLVMAttributesForBitcode(LLVMContext &C,
assert((!Alignment || isPowerOf2_32(Alignment)) && assert((!Alignment || isPowerOf2_32(Alignment)) &&
"Alignment must be a power of two."); "Alignment must be a power of two.");
B.addRawValue(EncodedAttrs & 0xffff);
if (Alignment) if (Alignment)
B.addAlignmentAttr(Alignment); B.addAlignmentAttr(Alignment);
B.addRawValue((EncodedAttrs & (0xffffULL << 32)) >> 11); B.addRawValue(((EncodedAttrs & (0xffffULL << 32)) >> 11) |
(EncodedAttrs & 0xffff));
} }

View File

@ -3,7 +3,7 @@
; Atomic load/store to local doesn't affect whether a function is ; Atomic load/store to local doesn't affect whether a function is
; readnone/readonly. ; readnone/readonly.
define i32 @test1(i32 %x) uwtable ssp { define i32 @test1(i32 %x) uwtable ssp {
; CHECK: define i32 @test1(i32 %x) uwtable readnone ssp { ; CHECK: define i32 @test1(i32 %x) readnone ssp uwtable {
entry: entry:
%x.addr = alloca i32, align 4 %x.addr = alloca i32, align 4
store atomic i32 %x, i32* %x.addr seq_cst, align 4 store atomic i32 %x, i32* %x.addr seq_cst, align 4
@ -13,7 +13,7 @@ entry:
; A function with an Acquire load is not readonly. ; A function with an Acquire load is not readonly.
define i32 @test2(i32* %x) uwtable ssp { define i32 @test2(i32* %x) uwtable ssp {
; CHECK: define i32 @test2(i32* nocapture %x) uwtable ssp { ; CHECK: define i32 @test2(i32* nocapture %x) ssp uwtable {
entry: entry:
%r = load atomic i32* %x seq_cst, align 4 %r = load atomic i32* %x seq_cst, align 4
ret i32 %r ret i32 %r

View File

@ -39,35 +39,35 @@ entry:
define void @inline_req_req() nounwind uwtable sspreq { define void @inline_req_req() nounwind uwtable sspreq {
entry: entry:
; CHECK: @inline_req_req() nounwind uwtable sspreq ; CHECK: @inline_req_req() nounwind sspreq uwtable
call void @fun_sspreq() call void @fun_sspreq()
ret void ret void
} }
define void @inline_req_strong() nounwind uwtable sspstrong { define void @inline_req_strong() nounwind uwtable sspstrong {
entry: entry:
; CHECK: @inline_req_strong() nounwind uwtable sspreq ; CHECK: @inline_req_strong() nounwind sspreq uwtable
call void @fun_sspreq() call void @fun_sspreq()
ret void ret void
} }
define void @inline_req_ssp() nounwind uwtable ssp { define void @inline_req_ssp() nounwind uwtable ssp {
entry: entry:
; CHECK: @inline_req_ssp() nounwind uwtable sspreq ; CHECK: @inline_req_ssp() nounwind sspreq uwtable
call void @fun_sspreq() call void @fun_sspreq()
ret void ret void
} }
define void @inline_req_nossp() nounwind uwtable { define void @inline_req_nossp() nounwind uwtable {
entry: entry:
; CHECK: @inline_req_nossp() nounwind uwtable sspreq ; CHECK: @inline_req_nossp() nounwind sspreq uwtable
call void @fun_sspreq() call void @fun_sspreq()
ret void ret void
} }
define void @inline_strong_req() nounwind uwtable sspreq { define void @inline_strong_req() nounwind uwtable sspreq {
entry: entry:
; CHECK: @inline_strong_req() nounwind uwtable sspreq ; CHECK: @inline_strong_req() nounwind sspreq uwtable
call void @fun_sspstrong() call void @fun_sspstrong()
ret void ret void
} }
@ -96,7 +96,7 @@ entry:
define void @inline_ssp_req() nounwind uwtable sspreq { define void @inline_ssp_req() nounwind uwtable sspreq {
entry: entry:
; CHECK: @inline_ssp_req() nounwind uwtable sspreq ; CHECK: @inline_ssp_req() nounwind sspreq uwtable
call void @fun_ssp() call void @fun_ssp()
ret void ret void
} }
@ -111,21 +111,21 @@ entry:
define void @inline_ssp_ssp() nounwind uwtable ssp { define void @inline_ssp_ssp() nounwind uwtable ssp {
entry: entry:
; CHECK: @inline_ssp_ssp() nounwind uwtable ssp ; CHECK: @inline_ssp_ssp() nounwind ssp uwtable
call void @fun_ssp() call void @fun_ssp()
ret void ret void
} }
define void @inline_ssp_nossp() nounwind uwtable { define void @inline_ssp_nossp() nounwind uwtable {
entry: entry:
; CHECK: @inline_ssp_nossp() nounwind uwtable ssp ; CHECK: @inline_ssp_nossp() nounwind ssp uwtable
call void @fun_ssp() call void @fun_ssp()
ret void ret void
} }
define void @inline_nossp_req() nounwind uwtable sspreq { define void @inline_nossp_req() nounwind uwtable sspreq {
entry: entry:
; CHECK: @inline_nossp_req() nounwind uwtable sspreq ; CHECK: @inline_nossp_req() nounwind sspreq uwtable
call void @fun_nossp() call void @fun_nossp()
ret void ret void
} }
@ -140,7 +140,7 @@ entry:
define void @inline_nossp_ssp() nounwind uwtable ssp { define void @inline_nossp_ssp() nounwind uwtable ssp {
entry: entry:
; CHECK: @inline_nossp_ssp() nounwind uwtable ssp ; CHECK: @inline_nossp_ssp() nounwind ssp uwtable
call void @fun_nossp() call void @fun_nossp()
ret void ret void
} }