summaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r--llvm/lib/IR/Attributes.cpp90
1 files changed, 87 insertions, 3 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 7a3c9a99ee4d..b2fdd218e5d4 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -25,6 +25,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/ConstantRange.h"
+#include "llvm/IR/ConstantRangeList.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Type.h"
@@ -191,6 +192,43 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
return Attribute(PA);
}
+Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
+ ArrayRef<ConstantRange> Val) {
+ assert(Attribute::isConstantRangeListAttrKind(Kind) &&
+ "Not a ConstantRangeList attribute");
+ LLVMContextImpl *pImpl = Context.pImpl;
+ FoldingSetNodeID ID;
+ ID.AddInteger(Kind);
+ ID.AddInteger(Val.size());
+ for (auto &CR : Val) {
+ CR.getLower().Profile(ID);
+ CR.getUpper().Profile(ID);
+ }
+
+ void *InsertPoint;
+ AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
+
+ if (!PA) {
+ // If we didn't find any existing attributes of the same shape then create a
+ // new one and insert it.
+ // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
+ // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
+ // allocation and record the allocated pointer in
+ // `ConstantRangeListAttributes`. LLVMContext destructor will call the
+ // destructor of the allocated pointer explicitly.
+ void *Mem = pImpl->Alloc.Allocate(
+ ConstantRangeListAttributeImpl::totalSizeToAlloc(Val),
+ alignof(ConstantRangeListAttributeImpl));
+ PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
+ pImpl->AttrsSet.InsertNode(PA, InsertPoint);
+ pImpl->ConstantRangeListAttributes.push_back(
+ reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
+ }
+
+ // Return the Attribute that we found or created.
+ return Attribute(PA);
+}
+
Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
return get(Context, Alignment, A.value());
@@ -317,10 +355,14 @@ bool Attribute::isConstantRangeAttribute() const {
return pImpl && pImpl->isConstantRangeAttribute();
}
+bool Attribute::isConstantRangeListAttribute() const {
+ return pImpl && pImpl->isConstantRangeListAttribute();
+}
+
Attribute::AttrKind Attribute::getKindAsEnum() const {
if (!pImpl) return None;
assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
- isConstantRangeAttribute()) &&
+ isConstantRangeAttribute() || isConstantRangeListAttribute()) &&
"Invalid attribute type to get the kind as an enum!");
return pImpl->getKindAsEnum();
}
@@ -366,6 +408,12 @@ const ConstantRange &Attribute::getValueAsConstantRange() const {
return pImpl->getValueAsConstantRange();
}
+ArrayRef<ConstantRange> Attribute::getValueAsConstantRangeList() const {
+ assert(isConstantRangeListAttribute() &&
+ "Invalid attribute type to get the value as a ConstantRangeList!");
+ return pImpl->getValueAsConstantRangeList();
+}
+
bool Attribute::hasAttribute(AttrKind Kind) const {
return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
}
@@ -450,6 +498,12 @@ const ConstantRange &Attribute::getRange() const {
return pImpl->getValueAsConstantRange();
}
+ArrayRef<ConstantRange> Attribute::getInitializes() const {
+ assert(hasAttribute(Attribute::Initializes) &&
+ "Trying to get initializes attr from non-ConstantRangeList attribute");
+ return pImpl->getValueAsConstantRangeList();
+}
+
static const char *getModRefStr(ModRefInfo MR) {
switch (MR) {
case ModRefInfo::NoModRef:
@@ -611,6 +665,17 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return Result;
}
+ if (hasAttribute(Attribute::Initializes)) {
+ std::string Result;
+ raw_string_ostream OS(Result);
+ ConstantRangeList CRL = getInitializes();
+ OS << "initializes(";
+ CRL.print(OS);
+ OS << ")";
+ OS.flush();
+ return Result;
+ }
+
// Convert target-dependent attributes to strings of the form:
//
// "kind"
@@ -701,7 +766,7 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const {
Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() ||
- isConstantRangeAttribute());
+ isConstantRangeAttribute() || isConstantRangeListAttribute());
return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
}
@@ -736,6 +801,12 @@ const ConstantRange &AttributeImpl::getValueAsConstantRange() const {
->getConstantRangeValue();
}
+ArrayRef<ConstantRange> AttributeImpl::getValueAsConstantRangeList() const {
+ assert(isConstantRangeListAttribute());
+ return static_cast<const ConstantRangeListAttributeImpl *>(this)
+ ->getConstantRangeListValue();
+}
+
bool AttributeImpl::operator<(const AttributeImpl &AI) const {
if (this == &AI)
return false;
@@ -750,6 +821,8 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {
assert(!AI.isEnumAttribute() && "Non-unique attribute");
assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
+ assert(!AI.isConstantRangeListAttribute() &&
+ "Unclear how to compare range list");
// TODO: Is this actually needed?
assert(AI.isIntAttribute() && "Only possibility left");
return getValueAsInt() < AI.getValueAsInt();
@@ -1954,6 +2027,16 @@ AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
return addConstantRangeAttr(Attribute::Range, CR);
}
+AttrBuilder &
+AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
+ ArrayRef<ConstantRange> Val) {
+ return addAttribute(Attribute::get(Ctx, Kind, Val));
+}
+
+AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
+ return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
+}
+
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
// TODO: Could make this O(n) as we're merging two sorted lists.
for (const auto &I : B.attrs())
@@ -2042,7 +2125,8 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
.addAttribute(Attribute::Dereferenceable)
.addAttribute(Attribute::DereferenceableOrNull)
.addAttribute(Attribute::Writable)
- .addAttribute(Attribute::DeadOnUnwind);
+ .addAttribute(Attribute::DeadOnUnwind)
+ .addAttribute(Attribute::Initializes);
if (ASK & ASK_UNSAFE_TO_DROP)
Incompatible.addAttribute(Attribute::Nest)
.addAttribute(Attribute::SwiftError)