aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/IR/Attributes.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r--llvm/lib/IR/Attributes.cpp246
1 files changed, 162 insertions, 84 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 6d9f94b5eefd..8c989c464551 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -17,7 +17,6 @@
#include "LLVMContextImpl.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -29,12 +28,14 @@
#include "llvm/IR/Type.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ModRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
+#include <optional>
#include <string>
#include <tuple>
#include <utility>
@@ -54,7 +55,7 @@ using namespace llvm;
static const unsigned AllocSizeNumElemsNotPresent = -1;
static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
- const Optional<unsigned> &NumElemsArg) {
+ const std::optional<unsigned> &NumElemsArg) {
assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
"Attempting to pack a reserved value");
@@ -62,42 +63,44 @@ static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
}
-static std::pair<unsigned, Optional<unsigned>>
+static std::pair<unsigned, std::optional<unsigned>>
unpackAllocSizeArgs(uint64_t Num) {
unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
unsigned ElemSizeArg = Num >> 32;
- Optional<unsigned> NumElemsArg;
+ std::optional<unsigned> NumElemsArg;
if (NumElems != AllocSizeNumElemsNotPresent)
NumElemsArg = NumElems;
return std::make_pair(ElemSizeArg, NumElemsArg);
}
static uint64_t packVScaleRangeArgs(unsigned MinValue,
- Optional<unsigned> MaxValue) {
+ std::optional<unsigned> MaxValue) {
return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
}
-static std::pair<unsigned, Optional<unsigned>>
+static std::pair<unsigned, std::optional<unsigned>>
unpackVScaleRangeArgs(uint64_t Value) {
unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
unsigned MinValue = Value >> 32;
return std::make_pair(MinValue,
- MaxValue > 0 ? MaxValue : Optional<unsigned>());
+ MaxValue > 0 ? MaxValue : std::optional<unsigned>());
}
Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
uint64_t Val) {
- if (Val)
- assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
- else
- assert(Attribute::isEnumAttrKind(Kind) && "Not an enum attribute");
+ bool IsIntAttr = Attribute::isIntAttrKind(Kind);
+ assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
+ "Not an enum or int attribute");
LLVMContextImpl *pImpl = Context.pImpl;
FoldingSetNodeID ID;
ID.AddInteger(Kind);
- if (Val) ID.AddInteger(Val);
+ if (IsIntAttr)
+ ID.AddInteger(Val);
+ else
+ assert(Val == 0 && "Value must be zero for enum attributes");
void *InsertPoint;
AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
@@ -105,7 +108,7 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
if (!PA) {
// If we didn't find any existing attributes of the same shape then create a
// new one and insert it.
- if (!Val)
+ if (!IsIntAttr)
PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
else
PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
@@ -208,9 +211,14 @@ Attribute Attribute::getWithUWTableKind(LLVMContext &Context,
return get(Context, UWTable, uint64_t(Kind));
}
+Attribute Attribute::getWithMemoryEffects(LLVMContext &Context,
+ MemoryEffects ME) {
+ return get(Context, Memory, ME.toIntValue());
+}
+
Attribute
Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
- const Optional<unsigned> &NumElemsArg) {
+ const std::optional<unsigned> &NumElemsArg) {
assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
"Invalid allocsize arguments -- given allocsize(0, 0)");
return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
@@ -351,7 +359,8 @@ uint64_t Attribute::getDereferenceableOrNullBytes() const {
return pImpl->getValueAsInt();
}
-std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
+std::pair<unsigned, std::optional<unsigned>>
+Attribute::getAllocSizeArgs() const {
assert(hasAttribute(Attribute::AllocSize) &&
"Trying to get allocsize args from non-allocsize attribute");
return unpackAllocSizeArgs(pImpl->getValueAsInt());
@@ -363,7 +372,7 @@ unsigned Attribute::getVScaleRangeMin() const {
return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
}
-Optional<unsigned> Attribute::getVScaleRangeMax() const {
+std::optional<unsigned> Attribute::getVScaleRangeMax() const {
assert(hasAttribute(Attribute::VScaleRange) &&
"Trying to get vscale args from non-vscale attribute");
return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
@@ -381,6 +390,26 @@ AllocFnKind Attribute::getAllocKind() const {
return AllocFnKind(pImpl->getValueAsInt());
}
+MemoryEffects Attribute::getMemoryEffects() const {
+ assert(hasAttribute(Attribute::Memory) &&
+ "Can only call getMemoryEffects() on memory attribute");
+ return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
+}
+
+static const char *getModRefStr(ModRefInfo MR) {
+ switch (MR) {
+ case ModRefInfo::NoModRef:
+ return "none";
+ case ModRefInfo::Ref:
+ return "read";
+ case ModRefInfo::Mod:
+ return "write";
+ case ModRefInfo::ModRef:
+ return "readwrite";
+ }
+ llvm_unreachable("Invalid ModRefInfo");
+}
+
std::string Attribute::getAsString(bool InAttrGrp) const {
if (!pImpl) return {};
@@ -424,7 +453,7 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
if (hasAttribute(Attribute::AllocSize)) {
unsigned ElemSize;
- Optional<unsigned> NumElems;
+ std::optional<unsigned> NumElems;
std::tie(ElemSize, NumElems) = getAllocSizeArgs();
return (NumElems
@@ -435,7 +464,7 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
if (hasAttribute(Attribute::VScaleRange)) {
unsigned MinValue = getVScaleRangeMin();
- Optional<unsigned> MaxValue = getVScaleRangeMax();
+ std::optional<unsigned> MaxValue = getVScaleRangeMax();
return ("vscale_range(" + Twine(MinValue) + "," +
Twine(MaxValue.value_or(0)) + ")")
.str();
@@ -472,6 +501,48 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
.str();
}
+ if (hasAttribute(Attribute::Memory)) {
+ std::string Result;
+ raw_string_ostream OS(Result);
+ bool First = true;
+ OS << "memory(";
+
+ MemoryEffects ME = getMemoryEffects();
+
+ // Print access kind for "other" as the default access kind. This way it
+ // will apply to any new location kinds that get split out of "other".
+ ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
+ if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
+ First = false;
+ OS << getModRefStr(OtherMR);
+ }
+
+ for (auto Loc : MemoryEffects::locations()) {
+ ModRefInfo MR = ME.getModRef(Loc);
+ if (MR == OtherMR)
+ continue;
+
+ if (!First)
+ OS << ", ";
+ First = false;
+
+ switch (Loc) {
+ case MemoryEffects::ArgMem:
+ OS << "argmem: ";
+ break;
+ case MemoryEffects::InaccessibleMem:
+ OS << "inaccessiblemem: ";
+ break;
+ case MemoryEffects::Other:
+ llvm_unreachable("This is represented as the default access kind");
+ }
+ OS << getModRefStr(MR);
+ }
+ OS << ")";
+ OS.flush();
+ return Result;
+ }
+
// Convert target-dependent attributes to strings of the form:
//
// "kind"
@@ -530,8 +601,7 @@ enum AttributeProperty {
static bool hasAttributeProperty(Attribute::AttrKind Kind,
AttributeProperty Prop) {
unsigned Index = Kind - 1;
- assert(Index < sizeof(AttrPropTable) / sizeof(AttrPropTable[0]) &&
- "Invalid attribute kind");
+ assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
return AttrPropTable[Index] & Prop;
}
@@ -704,11 +774,11 @@ Attribute AttributeSet::getAttribute(StringRef Kind) const {
}
MaybeAlign AttributeSet::getAlignment() const {
- return SetNode ? SetNode->getAlignment() : None;
+ return SetNode ? SetNode->getAlignment() : std::nullopt;
}
MaybeAlign AttributeSet::getStackAlignment() const {
- return SetNode ? SetNode->getStackAlignment() : None;
+ return SetNode ? SetNode->getStackAlignment() : std::nullopt;
}
uint64_t AttributeSet::getDereferenceableBytes() const {
@@ -743,17 +813,19 @@ Type *AttributeSet::getElementType() const {
return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
}
-std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
- return SetNode ? SetNode->getAllocSizeArgs()
- : std::pair<unsigned, Optional<unsigned>>(0, 0);
+std::optional<std::pair<unsigned, std::optional<unsigned>>>
+AttributeSet::getAllocSizeArgs() const {
+ if (SetNode)
+ return SetNode->getAllocSizeArgs();
+ return std::nullopt;
}
unsigned AttributeSet::getVScaleRangeMin() const {
return SetNode ? SetNode->getVScaleRangeMin() : 1;
}
-Optional<unsigned> AttributeSet::getVScaleRangeMax() const {
- return SetNode ? SetNode->getVScaleRangeMax() : None;
+std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
+ return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
}
UWTableKind AttributeSet::getUWTableKind() const {
@@ -764,6 +836,10 @@ AllocFnKind AttributeSet::getAllocKind() const {
return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
}
+MemoryEffects AttributeSet::getMemoryEffects() const {
+ return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
+}
+
std::string AttributeSet::getAsString(bool InAttrGrp) const {
return SetNode ? SetNode->getAsString(InAttrGrp) : "";
}
@@ -854,11 +930,11 @@ bool AttributeSetNode::hasAttribute(StringRef Kind) const {
return StringAttrs.count(Kind);
}
-Optional<Attribute>
+std::optional<Attribute>
AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
// Do a quick presence check.
if (!hasAttribute(Kind))
- return None;
+ return std::nullopt;
// Attributes in a set are sorted by enum value, followed by string
// attributes. Binary search the one we want.
@@ -884,13 +960,13 @@ Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
MaybeAlign AttributeSetNode::getAlignment() const {
if (auto A = findEnumAttribute(Attribute::Alignment))
return A->getAlignment();
- return None;
+ return std::nullopt;
}
MaybeAlign AttributeSetNode::getStackAlignment() const {
if (auto A = findEnumAttribute(Attribute::StackAlignment))
return A->getStackAlignment();
- return None;
+ return std::nullopt;
}
Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
@@ -911,11 +987,11 @@ uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
return 0;
}
-std::pair<unsigned, Optional<unsigned>>
+std::optional<std::pair<unsigned, std::optional<unsigned>>>
AttributeSetNode::getAllocSizeArgs() const {
if (auto A = findEnumAttribute(Attribute::AllocSize))
return A->getAllocSizeArgs();
- return std::make_pair(0, 0);
+ return std::nullopt;
}
unsigned AttributeSetNode::getVScaleRangeMin() const {
@@ -924,10 +1000,10 @@ unsigned AttributeSetNode::getVScaleRangeMin() const {
return 1;
}
-Optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
+std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
if (auto A = findEnumAttribute(Attribute::VScaleRange))
return A->getVScaleRangeMax();
- return None;
+ return std::nullopt;
}
UWTableKind AttributeSetNode::getUWTableKind() const {
@@ -942,6 +1018,12 @@ AllocFnKind AttributeSetNode::getAllocKind() const {
return AllocFnKind::Unknown;
}
+MemoryEffects AttributeSetNode::getMemoryEffects() const {
+ if (auto A = findEnumAttribute(Attribute::Memory))
+ return A->getMemoryEffects();
+ return MemoryEffects::unknown();
+}
+
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
std::string Str;
for (iterator I = begin(), E = end(); I != E; ++I) {
@@ -982,7 +1064,7 @@ AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
}
void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
- Profile(ID, makeArrayRef(begin(), end()));
+ Profile(ID, ArrayRef(begin(), end()));
}
void AttributeListImpl::Profile(FoldingSetNodeID &ID,
@@ -1219,9 +1301,9 @@ AttributeList AttributeList::get(LLVMContext &C,
AttributeList
AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const {
- if (hasAttributeAtIndex(Index, Kind))
- return *this;
AttributeSet Attrs = getAttributes(Index);
+ if (Attrs.hasAttribute(Kind))
+ return *this;
// TODO: Insert at correct position and avoid sort.
SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
NewAttrs.push_back(Attribute::get(C, Kind));
@@ -1251,6 +1333,12 @@ AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
if (Index >= AttrSets.size())
AttrSets.resize(Index + 1);
AttrSets[Index] = Attrs;
+
+ // Remove trailing empty attribute sets.
+ while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
+ AttrSets.pop_back();
+ if (AttrSets.empty())
+ return {};
return AttributeList::getImpl(C, AttrSets);
}
@@ -1291,31 +1379,21 @@ AttributeList AttributeList::addParamAttribute(LLVMContext &C,
AttributeList
AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const {
- if (!hasAttributeAtIndex(Index, Kind))
+ AttributeSet Attrs = getAttributes(Index);
+ AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
+ if (Attrs == NewAttrs)
return *this;
-
- Index = attrIdxToArrayIdx(Index);
- SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
- assert(Index < AttrSets.size());
-
- AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
-
- return getImpl(C, AttrSets);
+ return setAttributesAtIndex(C, Index, NewAttrs);
}
AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
unsigned Index,
StringRef Kind) const {
- if (!hasAttributeAtIndex(Index, Kind))
+ AttributeSet Attrs = getAttributes(Index);
+ AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
+ if (Attrs == NewAttrs)
return *this;
-
- Index = attrIdxToArrayIdx(Index);
- SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
- assert(Index < AttrSets.size());
-
- AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
-
- return getImpl(C, AttrSets);
+ return setAttributesAtIndex(C, Index, NewAttrs);
}
AttributeList AttributeList::removeAttributesAtIndex(
@@ -1333,12 +1411,9 @@ AttributeList::removeAttributesAtIndex(LLVMContext &C,
unsigned WithoutIndex) const {
if (!pImpl)
return {};
- WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
- if (WithoutIndex >= getNumAttrSets())
+ if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
return *this;
- SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
- AttrSets[WithoutIndex] = AttributeSet();
- return getImpl(C, AttrSets);
+ return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
}
AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
@@ -1364,10 +1439,9 @@ AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
return addParamAttributes(C, Index, B);
}
-AttributeList
-AttributeList::addAllocSizeParamAttr(LLVMContext &C, unsigned Index,
- unsigned ElemSizeArg,
- const Optional<unsigned> &NumElemsArg) {
+AttributeList AttributeList::addAllocSizeParamAttr(
+ LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
+ const std::optional<unsigned> &NumElemsArg) {
AttrBuilder B(C);
B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
return addParamAttributes(C, Index, B);
@@ -1494,6 +1568,10 @@ AllocFnKind AttributeList::getAllocKind() const {
return getFnAttrs().getAllocKind();
}
+MemoryEffects AttributeList::getMemoryEffects() const {
+ return getFnAttrs().getMemoryEffects();
+}
+
std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
return getAttributes(Index).getAsString(InAttrGrp);
}
@@ -1638,10 +1716,13 @@ AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
return *this;
}
-uint64_t AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
+std::optional<uint64_t>
+AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
Attribute A = getAttribute(Kind);
- return A.isValid() ? A.getValueAsInt() : 0;
+ if (A.isValid())
+ return A.getValueAsInt();
+ return std::nullopt;
}
AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
@@ -1649,16 +1730,12 @@ AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
return addAttribute(Attribute::get(Ctx, Kind, Value));
}
-std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
- return unpackAllocSizeArgs(getRawIntAttr(Attribute::AllocSize));
-}
-
-unsigned AttrBuilder::getVScaleRangeMin() const {
- return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)).first;
-}
-
-Optional<unsigned> AttrBuilder::getVScaleRangeMax() const {
- return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)).second;
+std::optional<std::pair<unsigned, std::optional<unsigned>>>
+AttrBuilder::getAllocSizeArgs() const {
+ Attribute A = getAttribute(Attribute::AllocSize);
+ if (A.isValid())
+ return A.getAllocSizeArgs();
+ return std::nullopt;
}
AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
@@ -1691,8 +1768,9 @@ AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
}
-AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
- const Optional<unsigned> &NumElems) {
+AttrBuilder &
+AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
+ const std::optional<unsigned> &NumElems) {
return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
}
@@ -1703,7 +1781,7 @@ AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
}
AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
- Optional<unsigned> MaxValue) {
+ std::optional<unsigned> MaxValue) {
return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
}
@@ -1721,6 +1799,10 @@ AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
}
+AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
+ return addRawIntAttr(Attribute::Memory, ME.toIntValue());
+}
+
AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
}
@@ -1795,10 +1877,6 @@ bool AttrBuilder::contains(StringRef A) const {
return getAttribute(A).isValid();
}
-bool AttrBuilder::hasAlignmentAttr() const {
- return getRawIntAttr(Attribute::Alignment) != 0;
-}
-
bool AttrBuilder::operator==(const AttrBuilder &B) const {
return Attrs == B.Attrs;
}