diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/IR/Attributes.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r-- | llvm/lib/IR/Attributes.cpp | 246 |
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; } |