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
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index 1aa733e..1578789 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -180,7 +180,7 @@
/// \brief The attributes for the specified index are returned. Attributes
/// 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.
static AttributeSet get(LLVMContext &C,
diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h
index 34754e8..91f5005 100644
--- a/lib/IR/AttributeImpl.h
+++ b/lib/IR/AttributeImpl.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/IR/Attributes.h"
+#include <string>
namespace llvm {
@@ -92,6 +93,13 @@
public:
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>::const_iterator const_iterator;
@@ -152,6 +160,12 @@
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::const_iterator const_iterator;
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index 8250330..ab29766 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -99,77 +99,78 @@
}
std::string Attribute::getAsString() const {
- std::string Result;
if (hasAttribute(Attribute::ZExt))
- Result += "zeroext ";
+ return "zeroext";
if (hasAttribute(Attribute::SExt))
- Result += "signext ";
+ return "signext";
if (hasAttribute(Attribute::NoReturn))
- Result += "noreturn ";
+ return "noreturn";
if (hasAttribute(Attribute::NoUnwind))
- Result += "nounwind ";
+ return "nounwind";
if (hasAttribute(Attribute::UWTable))
- Result += "uwtable ";
+ return "uwtable";
if (hasAttribute(Attribute::ReturnsTwice))
- Result += "returns_twice ";
+ return "returns_twice";
if (hasAttribute(Attribute::InReg))
- Result += "inreg ";
+ return "inreg";
if (hasAttribute(Attribute::NoAlias))
- Result += "noalias ";
+ return "noalias";
if (hasAttribute(Attribute::NoCapture))
- Result += "nocapture ";
+ return "nocapture";
if (hasAttribute(Attribute::StructRet))
- Result += "sret ";
+ return "sret";
if (hasAttribute(Attribute::ByVal))
- Result += "byval ";
+ return "byval";
if (hasAttribute(Attribute::Nest))
- Result += "nest ";
+ return "nest";
if (hasAttribute(Attribute::ReadNone))
- Result += "readnone ";
+ return "readnone";
if (hasAttribute(Attribute::ReadOnly))
- Result += "readonly ";
+ return "readonly";
if (hasAttribute(Attribute::OptimizeForSize))
- Result += "optsize ";
+ return "optsize";
if (hasAttribute(Attribute::NoInline))
- Result += "noinline ";
+ return "noinline";
if (hasAttribute(Attribute::InlineHint))
- Result += "inlinehint ";
+ return "inlinehint";
if (hasAttribute(Attribute::AlwaysInline))
- Result += "alwaysinline ";
+ return "alwaysinline";
if (hasAttribute(Attribute::StackProtect))
- Result += "ssp ";
+ return "ssp";
if (hasAttribute(Attribute::StackProtectReq))
- Result += "sspreq ";
+ return "sspreq";
if (hasAttribute(Attribute::StackProtectStrong))
- Result += "sspstrong ";
+ return "sspstrong";
if (hasAttribute(Attribute::NoRedZone))
- Result += "noredzone ";
+ return "noredzone";
if (hasAttribute(Attribute::NoImplicitFloat))
- Result += "noimplicitfloat ";
+ return "noimplicitfloat";
if (hasAttribute(Attribute::Naked))
- Result += "naked ";
+ return "naked";
if (hasAttribute(Attribute::NonLazyBind))
- Result += "nonlazybind ";
+ return "nonlazybind";
if (hasAttribute(Attribute::AddressSafety))
- Result += "address_safety ";
+ return "address_safety";
if (hasAttribute(Attribute::MinSize))
- Result += "minsize ";
+ return "minsize";
if (hasAttribute(Attribute::StackAlignment)) {
+ std::string Result;
Result += "alignstack(";
Result += utostr(getStackAlignment());
- Result += ") ";
+ Result += ")";
+ return Result;
}
if (hasAttribute(Attribute::Alignment)) {
+ std::string Result;
Result += "align ";
Result += utostr(getAlignment());
- Result += " ";
+ Result += "";
+ return Result;
}
if (hasAttribute(Attribute::NoDuplicate))
- Result += "noduplicate ";
- // Trim the trailing space.
- assert(!Result.empty() && "Unknown attribute!");
- Result.erase(Result.end()-1);
- return Result;
+ return "noduplicate";
+
+ llvm_unreachable("Unknown attribute");
}
bool Attribute::operator==(AttrKind K) const {
@@ -354,6 +355,40 @@
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
//===----------------------------------------------------------------------===//
@@ -597,7 +632,7 @@
AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const {
return pImpl && hasAttributes(Idx) ?
AttributeSet::get(pImpl->getContext(),
- ArrayRef<std::pair<unsigned, Attribute> >(
+ ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
std::make_pair(Idx, getAttributes(Idx)))) :
AttributeSet();
}
@@ -605,7 +640,7 @@
AttributeSet AttributeSet::getRetAttributes() const {
return pImpl && hasAttributes(ReturnIndex) ?
AttributeSet::get(pImpl->getContext(),
- ArrayRef<std::pair<unsigned, Attribute> >(
+ ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
std::make_pair(ReturnIndex,
getAttributes(ReturnIndex)))) :
AttributeSet();
@@ -614,18 +649,20 @@
AttributeSet AttributeSet::getFnAttributes() const {
return pImpl && hasAttributes(FunctionIndex) ?
AttributeSet::get(pImpl->getContext(),
- ArrayRef<std::pair<unsigned, Attribute> >(
+ ArrayRef<std::pair<unsigned, AttributeSetNode*> >(
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::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
@@ -642,36 +679,31 @@
return false;
}
-unsigned AttributeSet::getParamAlignment(unsigned Idx) const {
- return getAttributes(Idx).getAlignment();
+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();
+ AttributeSetNode *ASN = getAttributes(Index);
+ return ASN ? ASN->getAsString() : 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 Idx) 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) == Idx)
+ 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 Attribute();
+ return 0;
}
//===----------------------------------------------------------------------===//
@@ -948,9 +980,8 @@
assert((!Alignment || isPowerOf2_32(Alignment)) &&
"Alignment must be a power of two.");
- B.addRawValue(EncodedAttrs & 0xffff);
if (Alignment)
B.addAlignmentAttr(Alignment);
- B.addRawValue((EncodedAttrs & (0xffffULL << 32)) >> 11);
+ B.addRawValue(((EncodedAttrs & (0xffffULL << 32)) >> 11) |
+ (EncodedAttrs & 0xffff));
}
-
diff --git a/test/Transforms/FunctionAttrs/atomic.ll b/test/Transforms/FunctionAttrs/atomic.ll
index 7c2bff7..df916e2 100644
--- a/test/Transforms/FunctionAttrs/atomic.ll
+++ b/test/Transforms/FunctionAttrs/atomic.ll
@@ -3,7 +3,7 @@
; Atomic load/store to local doesn't affect whether a function is
; readnone/readonly.
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:
%x.addr = alloca i32, align 4
store atomic i32 %x, i32* %x.addr seq_cst, align 4
@@ -13,7 +13,7 @@
; A function with an Acquire load is not readonly.
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:
%r = load atomic i32* %x seq_cst, align 4
ret i32 %r
diff --git a/test/Transforms/Inline/inline_ssp.ll b/test/Transforms/Inline/inline_ssp.ll
index d9996b3..ff0d5ce 100644
--- a/test/Transforms/Inline/inline_ssp.ll
+++ b/test/Transforms/Inline/inline_ssp.ll
@@ -39,35 +39,35 @@
define void @inline_req_req() nounwind uwtable sspreq {
entry:
-; CHECK: @inline_req_req() nounwind uwtable sspreq
+; CHECK: @inline_req_req() nounwind sspreq uwtable
call void @fun_sspreq()
ret void
}
define void @inline_req_strong() nounwind uwtable sspstrong {
entry:
-; CHECK: @inline_req_strong() nounwind uwtable sspreq
+; CHECK: @inline_req_strong() nounwind sspreq uwtable
call void @fun_sspreq()
ret void
}
define void @inline_req_ssp() nounwind uwtable ssp {
entry:
-; CHECK: @inline_req_ssp() nounwind uwtable sspreq
+; CHECK: @inline_req_ssp() nounwind sspreq uwtable
call void @fun_sspreq()
ret void
}
define void @inline_req_nossp() nounwind uwtable {
entry:
-; CHECK: @inline_req_nossp() nounwind uwtable sspreq
+; CHECK: @inline_req_nossp() nounwind sspreq uwtable
call void @fun_sspreq()
ret void
}
define void @inline_strong_req() nounwind uwtable sspreq {
entry:
-; CHECK: @inline_strong_req() nounwind uwtable sspreq
+; CHECK: @inline_strong_req() nounwind sspreq uwtable
call void @fun_sspstrong()
ret void
}
@@ -96,7 +96,7 @@
define void @inline_ssp_req() nounwind uwtable sspreq {
entry:
-; CHECK: @inline_ssp_req() nounwind uwtable sspreq
+; CHECK: @inline_ssp_req() nounwind sspreq uwtable
call void @fun_ssp()
ret void
}
@@ -111,21 +111,21 @@
define void @inline_ssp_ssp() nounwind uwtable ssp {
entry:
-; CHECK: @inline_ssp_ssp() nounwind uwtable ssp
+; CHECK: @inline_ssp_ssp() nounwind ssp uwtable
call void @fun_ssp()
ret void
}
define void @inline_ssp_nossp() nounwind uwtable {
entry:
-; CHECK: @inline_ssp_nossp() nounwind uwtable ssp
+; CHECK: @inline_ssp_nossp() nounwind ssp uwtable
call void @fun_ssp()
ret void
}
define void @inline_nossp_req() nounwind uwtable sspreq {
entry:
-; CHECK: @inline_nossp_req() nounwind uwtable sspreq
+; CHECK: @inline_nossp_req() nounwind sspreq uwtable
call void @fun_nossp()
ret void
}
@@ -140,7 +140,7 @@
define void @inline_nossp_ssp() nounwind uwtable ssp {
entry:
-; CHECK: @inline_nossp_ssp() nounwind uwtable ssp
+; CHECK: @inline_nossp_ssp() nounwind ssp uwtable
call void @fun_nossp()
ret void
}