aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/IR/Attributes.cpp')
-rw-r--r--contrib/llvm/lib/IR/Attributes.cpp300
1 files changed, 214 insertions, 86 deletions
diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp
index 6c01bb645629..d774c1ae9dfb 100644
--- a/contrib/llvm/lib/IR/Attributes.cpp
+++ b/contrib/llvm/lib/IR/Attributes.cpp
@@ -32,6 +32,35 @@ using namespace llvm;
// Attribute Construction Methods
//===----------------------------------------------------------------------===//
+// allocsize has two integer arguments, but because they're both 32 bits, we can
+// pack them into one 64-bit value, at the cost of making said value
+// nonsensical.
+//
+// In order to do this, we need to reserve one value of the second (optional)
+// allocsize argument to signify "not present."
+LLVM_CONSTEXPR static unsigned AllocSizeNumElemsNotPresent = -1;
+
+static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg) {
+ assert((!NumElemsArg.hasValue() ||
+ *NumElemsArg != AllocSizeNumElemsNotPresent) &&
+ "Attempting to pack a reserved value");
+
+ return uint64_t(ElemSizeArg) << 32 |
+ NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent);
+}
+
+static std::pair<unsigned, Optional<unsigned>>
+unpackAllocSizeArgs(uint64_t Num) {
+ unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
+ unsigned ElemSizeArg = Num >> 32;
+
+ Optional<unsigned> NumElemsArg;
+ if (NumElems != AllocSizeNumElemsNotPresent)
+ NumElemsArg = NumElems;
+ return std::make_pair(ElemSizeArg, NumElemsArg);
+}
+
Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
uint64_t Val) {
LLVMContextImpl *pImpl = Context.pImpl;
@@ -101,6 +130,14 @@ Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
return get(Context, DereferenceableOrNull, Bytes);
}
+Attribute
+Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg) {
+ assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
+ "Invalid allocsize arguments -- given allocsize(0, 0)");
+ return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
+}
+
//===----------------------------------------------------------------------===//
// Attribute Accessor Methods
//===----------------------------------------------------------------------===//
@@ -154,22 +191,18 @@ bool Attribute::hasAttribute(StringRef Kind) const {
return pImpl && pImpl->hasAttribute(Kind);
}
-/// This returns the alignment field of an attribute as a byte alignment value.
unsigned Attribute::getAlignment() const {
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 {
assert(hasAttribute(Attribute::StackAlignment) &&
"Trying to get alignment from non-alignment attribute!");
return pImpl->getValueAsInt();
}
-/// This returns the number of dereferenceable bytes.
uint64_t Attribute::getDereferenceableBytes() const {
assert(hasAttribute(Attribute::Dereferenceable) &&
"Trying to get dereferenceable bytes from "
@@ -184,6 +217,12 @@ uint64_t Attribute::getDereferenceableOrNullBytes() const {
return pImpl->getValueAsInt();
}
+std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
+ assert(hasAttribute(Attribute::AllocSize) &&
+ "Trying to get allocsize args from non-allocsize attribute");
+ return unpackAllocSizeArgs(pImpl->getValueAsInt());
+}
+
std::string Attribute::getAsString(bool InAttrGrp) const {
if (!pImpl) return "";
@@ -199,6 +238,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "byval";
if (hasAttribute(Attribute::Convergent))
return "convergent";
+ if (hasAttribute(Attribute::SwiftError))
+ return "swifterror";
+ if (hasAttribute(Attribute::SwiftSelf))
+ return "swiftself";
if (hasAttribute(Attribute::InaccessibleMemOnly))
return "inaccessiblememonly";
if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
@@ -249,6 +292,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "readnone";
if (hasAttribute(Attribute::ReadOnly))
return "readonly";
+ if (hasAttribute(Attribute::WriteOnly))
+ return "writeonly";
if (hasAttribute(Attribute::Returned))
return "returned";
if (hasAttribute(Attribute::ReturnsTwice))
@@ -312,6 +357,21 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
if (hasAttribute(Attribute::DereferenceableOrNull))
return AttrWithBytesToString("dereferenceable_or_null");
+ if (hasAttribute(Attribute::AllocSize)) {
+ unsigned ElemSize;
+ Optional<unsigned> NumElems;
+ std::tie(ElemSize, NumElems) = getAllocSizeArgs();
+
+ std::string Result = "allocsize(";
+ Result += utostr(ElemSize);
+ if (NumElems.hasValue()) {
+ Result += ',';
+ Result += utostr(*NumElems);
+ }
+ Result += ')';
+ return Result;
+ }
+
// Convert target-dependent attributes to strings of the form:
//
// "kind"
@@ -389,7 +449,11 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {
if (isIntAttribute()) {
if (AI.isEnumAttribute()) return false;
- if (AI.isIntAttribute()) return getValueAsInt() < AI.getValueAsInt();
+ if (AI.isIntAttribute()) {
+ if (getKindAsEnum() == AI.getKindAsEnum())
+ return getValueAsInt() < AI.getValueAsInt();
+ return getKindAsEnum() < AI.getKindAsEnum();
+ }
if (AI.isStringAttribute()) return true;
}
@@ -452,6 +516,9 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::NoRecurse: return 1ULL << 48;
case Attribute::InaccessibleMemOnly: return 1ULL << 49;
case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50;
+ case Attribute::SwiftSelf: return 1ULL << 51;
+ case Attribute::SwiftError: return 1ULL << 52;
+ case Attribute::WriteOnly: return 1ULL << 53;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
@@ -462,6 +529,9 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::ArgMemOnly:
llvm_unreachable("argmemonly attribute not supported in raw format");
break;
+ case Attribute::AllocSize:
+ llvm_unreachable("allocsize not supported in raw format");
+ break;
}
llvm_unreachable("Unsupported attribute type");
}
@@ -480,7 +550,7 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
FoldingSetNodeID ID;
SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
- array_pod_sort(SortedAttrs.begin(), SortedAttrs.end());
+ std::sort(SortedAttrs.begin(), SortedAttrs.end());
for (Attribute Attr : SortedAttrs)
Attr.Profile(ID);
@@ -502,62 +572,65 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
return PA;
}
-bool AttributeSetNode::hasAttribute(Attribute::AttrKind Kind) const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Kind))
- return true;
- return false;
-}
-
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Kind))
+ for (Attribute I : *this)
+ if (I.hasAttribute(Kind))
return true;
return false;
}
Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Kind))
- return *I;
+ if (hasAttribute(Kind)) {
+ for (Attribute I : *this)
+ if (I.hasAttribute(Kind))
+ return I;
+ }
return Attribute();
}
Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Kind))
- return *I;
+ for (Attribute I : *this)
+ if (I.hasAttribute(Kind))
+ return I;
return Attribute();
}
unsigned AttributeSetNode::getAlignment() const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Attribute::Alignment))
- return I->getAlignment();
+ for (Attribute I : *this)
+ if (I.hasAttribute(Attribute::Alignment))
+ return I.getAlignment();
return 0;
}
unsigned AttributeSetNode::getStackAlignment() const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Attribute::StackAlignment))
- return I->getStackAlignment();
+ for (Attribute I : *this)
+ if (I.hasAttribute(Attribute::StackAlignment))
+ return I.getStackAlignment();
return 0;
}
uint64_t AttributeSetNode::getDereferenceableBytes() const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Attribute::Dereferenceable))
- return I->getDereferenceableBytes();
+ for (Attribute I : *this)
+ if (I.hasAttribute(Attribute::Dereferenceable))
+ return I.getDereferenceableBytes();
return 0;
}
uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
- for (iterator I = begin(), E = end(); I != E; ++I)
- if (I->hasAttribute(Attribute::DereferenceableOrNull))
- return I->getDereferenceableOrNullBytes();
+ for (Attribute I : *this)
+ if (I.hasAttribute(Attribute::DereferenceableOrNull))
+ return I.getDereferenceableOrNullBytes();
return 0;
}
+std::pair<unsigned, Optional<unsigned>>
+AttributeSetNode::getAllocSizeArgs() const {
+ for (Attribute I : *this)
+ if (I.hasAttribute(Attribute::AllocSize))
+ return I.getAllocSizeArgs();
+ return std::make_pair(0, 0);
+}
+
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
std::string Str;
for (iterator I = begin(), E = end(); I != E; ++I) {
@@ -573,7 +646,7 @@ std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
//===----------------------------------------------------------------------===//
uint64_t AttributeSetImpl::Raw(unsigned Index) const {
- for (unsigned I = 0, E = getNumAttributes(); I != E; ++I) {
+ for (unsigned I = 0, E = getNumSlots(); I != E; ++I) {
if (getSlotIndex(I) != Index) continue;
const AttributeSetNode *ASN = getSlotNode(I);
uint64_t Mask = 0;
@@ -593,6 +666,8 @@ uint64_t AttributeSetImpl::Raw(unsigned Index) const {
Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26;
else if (Kind == Attribute::Dereferenceable)
llvm_unreachable("dereferenceable not supported in bit mask");
+ else if (Kind == Attribute::AllocSize)
+ llvm_unreachable("allocsize not supported in bit mask");
else
Mask |= AttributeImpl::getAttrMask(Kind);
}
@@ -603,7 +678,7 @@ uint64_t AttributeSetImpl::Raw(unsigned Index) const {
return 0;
}
-void AttributeSetImpl::dump() const {
+LLVM_DUMP_METHOD void AttributeSetImpl::dump() const {
AttributeSet(const_cast<AttributeSetImpl *>(this)).dump();
}
@@ -708,6 +783,11 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
Attr = Attribute::getWithDereferenceableOrNullBytes(
C, B.getDereferenceableOrNullBytes());
break;
+ case Attribute::AllocSize: {
+ auto A = B.getAllocSizeArgs();
+ Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
+ break;
+ }
default:
Attr = Attribute::get(C, Kind);
}
@@ -715,7 +795,7 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
}
// Add target-dependent (string) attributes.
- for (const AttrBuilder::td_type &TDA : B.td_attrs())
+ for (const auto &TDA : B.td_attrs())
Attrs.push_back(
std::make_pair(Index, Attribute::get(C, TDA.first, TDA.second)));
@@ -723,9 +803,17 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
}
AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
- ArrayRef<Attribute::AttrKind> Kind) {
+ ArrayRef<Attribute::AttrKind> Kinds) {
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
- for (Attribute::AttrKind K : Kind)
+ for (Attribute::AttrKind K : Kinds)
+ Attrs.push_back(std::make_pair(Index, Attribute::get(C, K)));
+ return get(C, Attrs);
+}
+
+AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
+ ArrayRef<StringRef> Kinds) {
+ SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
+ for (StringRef K : Kinds)
Attrs.push_back(std::make_pair(Index, Attribute::get(C, K)));
return get(C, Attrs);
}
@@ -737,7 +825,7 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) {
SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrNodeVec;
AttributeSetImpl *A0 = Attrs[0].pImpl;
if (A0)
- AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumAttributes()));
+ AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumSlots()));
// Copy all attributes from Attrs into AttrNodeVec while keeping AttrNodeVec
// ordered by index. Because we know that each list in Attrs is ordered by
// index we only need to merge each successive list in rather than doing a
@@ -748,7 +836,7 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) {
SmallVector<std::pair<unsigned, AttributeSetNode *>, 8>::iterator
ANVI = AttrNodeVec.begin(), ANVE;
for (const IndexAttrPair *AI = AS->getNode(0),
- *AE = AS->getNode(AS->getNumAttributes());
+ *AE = AS->getNode(AS->getNumSlots());
AI != AE; ++AI) {
ANVE = AttrNodeVec.end();
while (ANVI != ANVE && ANVI->first <= AI->first)
@@ -761,16 +849,9 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) {
}
AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Attr) const {
- 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));
+ Attribute::AttrKind Kind) const {
+ if (hasAttribute(Index, Kind)) return *this;
+ return addAttributes(C, Index, AttributeSet::get(C, Index, Kind));
}
AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
@@ -783,7 +864,7 @@ AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
AttributeSet AttributeSet::addAttribute(LLVMContext &C,
ArrayRef<unsigned> Indices,
Attribute A) const {
- unsigned I = 0, E = pImpl ? pImpl->getNumAttributes() : 0;
+ unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0;
auto IdxI = Indices.begin(), IdxE = Indices.end();
SmallVector<AttributeSet, 4> AttrSet;
@@ -826,7 +907,7 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
// Add the attribute slots before the one we're trying to add.
SmallVector<AttributeSet, 4> AttrSet;
- uint64_t NumAttrs = pImpl->getNumAttributes();
+ uint64_t NumAttrs = pImpl->getNumSlots();
AttributeSet AS;
uint64_t LastIndex = 0;
for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
@@ -842,7 +923,7 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
// AttributeSet there.
AttrBuilder B(AS, Index);
- for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I)
+ for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I)
if (Attrs.getSlotIndex(I) == Index) {
for (AttributeSetImpl::iterator II = Attrs.pImpl->begin(I),
IE = Attrs.pImpl->end(I); II != IE; ++II)
@@ -860,9 +941,15 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
}
AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Attr) const {
- if (!hasAttribute(Index, Attr)) return *this;
- return removeAttributes(C, Index, AttributeSet::get(C, Index, Attr));
+ Attribute::AttrKind Kind) const {
+ if (!hasAttribute(Index, Kind)) return *this;
+ return removeAttributes(C, Index, AttributeSet::get(C, Index, Kind));
+}
+
+AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index,
+ StringRef Kind) const {
+ if (!hasAttribute(Index, Kind)) return *this;
+ return removeAttributes(C, Index, AttributeSet::get(C, Index, Kind));
}
AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
@@ -877,7 +964,7 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
// Add the attribute slots before the one we're trying to add.
SmallVector<AttributeSet, 4> AttrSet;
- uint64_t NumAttrs = pImpl->getNumAttributes();
+ uint64_t NumAttrs = pImpl->getNumSlots();
AttributeSet AS;
uint64_t LastIndex = 0;
for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
@@ -893,7 +980,7 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
// AttributeSet there.
AttrBuilder B(AS, Index);
- for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I)
+ for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I)
if (Attrs.getSlotIndex(I) == Index) {
B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Index);
break;
@@ -918,7 +1005,7 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
// Add the attribute slots before the one we're trying to add.
SmallVector<AttributeSet, 4> AttrSet;
- uint64_t NumAttrs = pImpl->getNumAttributes();
+ uint64_t NumAttrs = pImpl->getNumSlots();
AttributeSet AS;
uint64_t LastIndex = 0;
for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
@@ -959,6 +1046,15 @@ AttributeSet AttributeSet::addDereferenceableOrNullAttr(LLVMContext &C,
return addAttributes(C, Index, AttributeSet::get(C, Index, B));
}
+AttributeSet
+AttributeSet::addAllocSizeAttr(LLVMContext &C, unsigned Index,
+ unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg) {
+ llvm::AttrBuilder B;
+ B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
+ return addAttributes(C, Index, AttributeSet::get(C, Index, B));
+}
+
//===----------------------------------------------------------------------===//
// AttributeSet Accessor Methods
//===----------------------------------------------------------------------===//
@@ -1008,16 +1104,21 @@ bool AttributeSet::hasAttributes(unsigned Index) const {
return ASN && ASN->hasAttributes();
}
-/// \brief Return true if the specified attribute is set for at least one
-/// parameter or for the return value.
-bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const {
+bool AttributeSet::hasFnAttribute(Attribute::AttrKind Kind) const {
+ return pImpl && pImpl->hasFnAttribute(Kind);
+}
+
+bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr,
+ unsigned *Index) const {
if (!pImpl) return false;
- for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I)
+ for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I)
for (AttributeSetImpl::iterator II = pImpl->begin(I),
IE = pImpl->end(I); II != IE; ++II)
- if (II->hasAttribute(Attr))
+ if (II->hasAttribute(Attr)) {
+ if (Index) *Index = pImpl->getSlotIndex(I);
return true;
+ }
return false;
}
@@ -1054,18 +1155,22 @@ uint64_t AttributeSet::getDereferenceableOrNullBytes(unsigned Index) const {
return ASN ? ASN->getDereferenceableOrNullBytes() : 0;
}
-std::string AttributeSet::getAsString(unsigned Index,
- bool InAttrGrp) const {
+std::pair<unsigned, Optional<unsigned>>
+AttributeSet::getAllocSizeArgs(unsigned Index) const {
+ AttributeSetNode *ASN = getAttributes(Index);
+ return ASN ? ASN->getAllocSizeArgs() : std::make_pair(0, 0);
+}
+
+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.
AttributeSetNode *AttributeSet::getAttributes(unsigned Index) const {
if (!pImpl) return nullptr;
// 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->getNumSlots(); I != E; ++I)
if (pImpl->getSlotIndex(I) == Index)
return pImpl->getSlotNode(I);
@@ -1088,21 +1193,18 @@ AttributeSet::iterator AttributeSet::end(unsigned Slot) const {
// AttributeSet Introspection Methods
//===----------------------------------------------------------------------===//
-/// \brief Return the number of slots used in this attribute list. This is the
-/// number of arguments that have an attribute set on them (including the
-/// function itself).
unsigned AttributeSet::getNumSlots() const {
- return pImpl ? pImpl->getNumAttributes() : 0;
+ return pImpl ? pImpl->getNumSlots() : 0;
}
unsigned AttributeSet::getSlotIndex(unsigned Slot) const {
- assert(pImpl && Slot < pImpl->getNumAttributes() &&
+ assert(pImpl && Slot < pImpl->getNumSlots() &&
"Slot # out of range!");
return pImpl->getSlotIndex(Slot);
}
AttributeSet AttributeSet::getSlotAttributes(unsigned Slot) const {
- assert(pImpl && Slot < pImpl->getNumAttributes() &&
+ assert(pImpl && Slot < pImpl->getNumSlots() &&
"Slot # out of range!");
return pImpl->getSlotAttributes(Slot);
}
@@ -1112,7 +1214,7 @@ uint64_t AttributeSet::Raw(unsigned Index) const {
return pImpl ? pImpl->Raw(Index) : 0;
}
-void AttributeSet::dump() const {
+LLVM_DUMP_METHOD void AttributeSet::dump() const {
dbgs() << "PAL[\n";
for (unsigned i = 0, e = getNumSlots(); i < e; ++i) {
@@ -1134,11 +1236,11 @@ void AttributeSet::dump() const {
AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
: Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0) {
+ DerefOrNullBytes(0), AllocSizeArgs(0) {
AttributeSetImpl *pImpl = AS.pImpl;
if (!pImpl) return;
- for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) {
+ for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) {
if (pImpl->getSlotIndex(I) != Index) continue;
for (AttributeSetImpl::iterator II = pImpl->begin(I),
@@ -1153,12 +1255,13 @@ void AttrBuilder::clear() {
Attrs.reset();
TargetDepAttrs.clear();
Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
+ AllocSizeArgs = 0;
}
AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
- Val != Attribute::Dereferenceable &&
+ Val != Attribute::Dereferenceable && Val != Attribute::AllocSize &&
"Adding integer attribute without adding a value!");
Attrs[Val] = true;
return *this;
@@ -1181,6 +1284,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
DerefBytes = Attr.getDereferenceableBytes();
else if (Kind == Attribute::DereferenceableOrNull)
DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
+ else if (Kind == Attribute::AllocSize)
+ AllocSizeArgs = Attr.getValueAsInt();
return *this;
}
@@ -1201,6 +1306,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
DerefBytes = 0;
else if (Val == Attribute::DereferenceableOrNull)
DerefOrNullBytes = 0;
+ else if (Val == Attribute::AllocSize)
+ AllocSizeArgs = 0;
return *this;
}
@@ -1235,6 +1342,10 @@ AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
return *this;
}
+std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
+ return unpackAllocSizeArgs(AllocSizeArgs);
+}
+
AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
if (Align == 0) return *this;
@@ -1275,6 +1386,22 @@ AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
return *this;
}
+AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
+ const Optional<unsigned> &NumElems) {
+ return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
+}
+
+AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
+ // (0, 0) is our "not present" value, so we need to check for it here.
+ assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
+
+ Attrs[Attribute::AllocSize] = true;
+ // Reuse existing machinery to store this as a single 64-bit integer so we can
+ // save a few bytes over using a pair<unsigned, Optional<unsigned>>.
+ AllocSizeArgs = RawArgs;
+ return *this;
+}
+
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
// FIXME: What if both have alignments, but they don't match?!
if (!Alignment)
@@ -1289,6 +1416,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
if (!DerefOrNullBytes)
DerefOrNullBytes = B.DerefOrNullBytes;
+ if (!AllocSizeArgs)
+ AllocSizeArgs = B.AllocSizeArgs;
+
Attrs |= B.Attrs;
for (auto I : B.td_attrs())
@@ -1311,6 +1441,9 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
if (B.DerefOrNullBytes)
DerefOrNullBytes = 0;
+ if (B.AllocSizeArgs)
+ AllocSizeArgs = 0;
+
Attrs &= ~B.Attrs;
for (auto I : B.td_attrs())
@@ -1389,7 +1522,8 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
I = Attribute::AttrKind(I + 1)) {
if (I == Attribute::Dereferenceable ||
I == Attribute::DereferenceableOrNull ||
- I == Attribute::ArgMemOnly)
+ I == Attribute::ArgMemOnly ||
+ I == Attribute::AllocSize)
continue;
if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
Attrs[I] = true;
@@ -1478,20 +1612,14 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
AttributeSet::FunctionIndex,
B);
- if (Callee.hasFnAttribute(Attribute::SafeStack)) {
- Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller.addFnAttr(Attribute::SafeStack);
- } else if (Callee.hasFnAttribute(Attribute::StackProtectReq) &&
- !Caller.hasFnAttribute(Attribute::SafeStack)) {
+ if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
Caller.addFnAttr(Attribute::StackProtectReq);
} else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
- !Caller.hasFnAttribute(Attribute::SafeStack) &&
!Caller.hasFnAttribute(Attribute::StackProtectReq)) {
Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
Caller.addFnAttr(Attribute::StackProtectStrong);
} else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
- !Caller.hasFnAttribute(Attribute::SafeStack) &&
!Caller.hasFnAttribute(Attribute::StackProtectReq) &&
!Caller.hasFnAttribute(Attribute::StackProtectStrong))
Caller.addFnAttr(Attribute::StackProtect);