summaryrefslogtreecommitdiffstats
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.cpp192
1 files changed, 164 insertions, 28 deletions
diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp
index 04545ea..fef05c8 100644
--- a/contrib/llvm/lib/IR/Attributes.cpp
+++ b/contrib/llvm/lib/IR/Attributes.cpp
@@ -94,6 +94,12 @@ Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
return get(Context, Dereferenceable, Bytes);
}
+Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
+ uint64_t Bytes) {
+ assert(Bytes && "Bytes must be non-zero.");
+ return get(Context, DereferenceableOrNull, Bytes);
+}
+
//===----------------------------------------------------------------------===//
// Attribute Accessor Methods
//===----------------------------------------------------------------------===//
@@ -170,6 +176,13 @@ uint64_t Attribute::getDereferenceableBytes() const {
return pImpl->getValueAsInt();
}
+uint64_t Attribute::getDereferenceableOrNullBytes() const {
+ assert(hasAttribute(Attribute::DereferenceableOrNull) &&
+ "Trying to get dereferenceable bytes from "
+ "non-dereferenceable attribute!");
+ return pImpl->getValueAsInt();
+}
+
std::string Attribute::getAsString(bool InAttrGrp) const {
if (!pImpl) return "";
@@ -181,6 +194,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "builtin";
if (hasAttribute(Attribute::ByVal))
return "byval";
+ if (hasAttribute(Attribute::Convergent))
+ return "convergent";
if (hasAttribute(Attribute::InAlloca))
return "inalloca";
if (hasAttribute(Attribute::InlineHint))
@@ -263,9 +278,9 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return Result;
}
- if (hasAttribute(Attribute::StackAlignment)) {
+ auto AttrWithBytesToString = [&](const char *Name) {
std::string Result;
- Result += "alignstack";
+ Result += Name;
if (InAttrGrp) {
Result += "=";
Result += utostr(getValueAsInt());
@@ -275,21 +290,16 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
Result += ")";
}
return Result;
- }
+ };
- if (hasAttribute(Attribute::Dereferenceable)) {
- std::string Result;
- Result += "dereferenceable";
- if (InAttrGrp) {
- Result += "=";
- Result += utostr(getValueAsInt());
- } else {
- Result += "(";
- Result += utostr(getValueAsInt());
- Result += ")";
- }
- return Result;
- }
+ if (hasAttribute(Attribute::StackAlignment))
+ return AttrWithBytesToString("alignstack");
+
+ if (hasAttribute(Attribute::Dereferenceable))
+ return AttrWithBytesToString("dereferenceable");
+
+ if (hasAttribute(Attribute::DereferenceableOrNull))
+ return AttrWithBytesToString("dereferenceable_or_null");
// Convert target-dependent attributes to strings of the form:
//
@@ -298,12 +308,12 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
//
if (isStringAttribute()) {
std::string Result;
- Result += '\"' + getKindAsString().str() + '"';
+ Result += (Twine('"') + getKindAsString() + Twine('"')).str();
StringRef Val = pImpl->getValueAsString();
if (Val.empty()) return Result;
- Result += "=\"" + Val.str() + '"';
+ Result += ("=\"" + Val + Twine('"')).str();
return Result;
}
@@ -426,8 +436,14 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::InAlloca: return 1ULL << 43;
case Attribute::NonNull: return 1ULL << 44;
case Attribute::JumpTable: return 1ULL << 45;
+ case Attribute::Convergent: return 1ULL << 46;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
+ break;
+ case Attribute::DereferenceableOrNull:
+ llvm_unreachable("dereferenceable_or_null attribute not supported in raw "
+ "format");
+ break;
}
llvm_unreachable("Unsupported attribute type");
}
@@ -519,6 +535,13 @@ uint64_t AttributeSetNode::getDereferenceableBytes() const {
return 0;
}
+uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (I->hasAttribute(Attribute::DereferenceableOrNull))
+ return I->getDereferenceableOrNullBytes();
+ return 0;
+}
+
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
std::string Str;
for (iterator I = begin(), E = end(); I != E; ++I) {
@@ -663,6 +686,10 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
Attrs.push_back(std::make_pair(Index,
Attribute::getWithDereferenceableBytes(C,
B.getDereferenceableBytes())));
+ else if (Kind == Attribute::DereferenceableOrNull)
+ Attrs.push_back(
+ std::make_pair(Index, Attribute::getWithDereferenceableOrNullBytes(
+ C, B.getDereferenceableOrNullBytes())));
else
Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind)));
}
@@ -795,12 +822,10 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
if (!pImpl) return AttributeSet();
if (!Attrs.pImpl) return *this;
-#ifndef NDEBUG
// FIXME it is not obvious how this should work for alignment.
// For now, say we can't pass in alignment, which no current use does.
assert(!Attrs.hasAttribute(Index, Attribute::Alignment) &&
"Attempt to change alignment!");
-#endif
// Add the attribute slots before the one we're trying to add.
SmallVector<AttributeSet, 4> AttrSet;
@@ -835,6 +860,57 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
return get(C, AttrSet);
}
+AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &Attrs) const {
+ if (!pImpl) return AttributeSet();
+
+ // FIXME it is not obvious how this should work for alignment.
+ // For now, say we can't pass in alignment, which no current use does.
+ assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!");
+
+ // Add the attribute slots before the one we're trying to add.
+ SmallVector<AttributeSet, 4> AttrSet;
+ uint64_t NumAttrs = pImpl->getNumAttributes();
+ AttributeSet AS;
+ uint64_t LastIndex = 0;
+ for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
+ if (getSlotIndex(I) >= Index) {
+ if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
+ break;
+ }
+ LastIndex = I + 1;
+ AttrSet.push_back(getSlotAttributes(I));
+ }
+
+ // Now remove the attribute from the correct slot. There may already be an
+ // AttributeSet there.
+ AttrBuilder B(AS, Index);
+ B.remove(Attrs);
+
+ AttrSet.push_back(AttributeSet::get(C, Index, B));
+
+ // Add the remaining attribute slots.
+ for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
+ AttrSet.push_back(getSlotAttributes(I));
+
+ return get(C, AttrSet);
+}
+
+AttributeSet AttributeSet::addDereferenceableAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const {
+ llvm::AttrBuilder B;
+ B.addDereferenceableAttr(Bytes);
+ return addAttributes(C, Index, AttributeSet::get(C, Index, B));
+}
+
+AttributeSet AttributeSet::addDereferenceableOrNullAttr(LLVMContext &C,
+ unsigned Index,
+ uint64_t Bytes) const {
+ llvm::AttrBuilder B;
+ B.addDereferenceableOrNullAttr(Bytes);
+ return addAttributes(C, Index, AttributeSet::get(C, Index, B));
+}
+
//===----------------------------------------------------------------------===//
// AttributeSet Accessor Methods
//===----------------------------------------------------------------------===//
@@ -925,6 +1001,11 @@ uint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const {
return ASN ? ASN->getDereferenceableBytes() : 0;
}
+uint64_t AttributeSet::getDereferenceableOrNullBytes(unsigned Index) const {
+ AttributeSetNode *ASN = getAttributes(Index);
+ return ASN ? ASN->getDereferenceableOrNullBytes() : 0;
+}
+
std::string AttributeSet::getAsString(unsigned Index,
bool InAttrGrp) const {
AttributeSetNode *ASN = getAttributes(Index);
@@ -1004,7 +1085,8 @@ void AttributeSet::dump() const {
//===----------------------------------------------------------------------===//
AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
+ DerefOrNullBytes(0) {
AttributeSetImpl *pImpl = AS.pImpl;
if (!pImpl) return;
@@ -1021,7 +1103,7 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
void AttrBuilder::clear() {
Attrs.reset();
- Alignment = StackAlignment = DerefBytes = 0;
+ Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
}
AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
@@ -1048,6 +1130,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
StackAlignment = Attr.getStackAlignment();
else if (Kind == Attribute::Dereferenceable)
DerefBytes = Attr.getDereferenceableBytes();
+ else if (Kind == Attribute::DereferenceableOrNull)
+ DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
return *this;
}
@@ -1066,6 +1150,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
StackAlignment = 0;
else if (Val == Attribute::Dereferenceable)
DerefBytes = 0;
+ else if (Val == Attribute::DereferenceableOrNull)
+ DerefOrNullBytes = 0;
return *this;
}
@@ -1092,6 +1178,8 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
StackAlignment = 0;
else if (Kind == Attribute::Dereferenceable)
DerefBytes = 0;
+ else if (Kind == Attribute::DereferenceableOrNull)
+ DerefOrNullBytes = 0;
} else {
assert(Attr.isStringAttribute() && "Invalid attribute type!");
std::map<std::string, std::string>::iterator
@@ -1142,6 +1230,15 @@ AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
return *this;
}
+AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
+ if (Bytes == 0)
+ return *this;
+
+ Attrs[Attribute::DereferenceableOrNull] = true;
+ DerefOrNullBytes = Bytes;
+ return *this;
+}
+
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
// FIXME: What if both have alignments, but they don't match?!
if (!Alignment)
@@ -1153,15 +1250,52 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
if (!DerefBytes)
DerefBytes = B.DerefBytes;
+ if (!DerefOrNullBytes)
+ DerefOrNullBytes = B.DerefOrNullBytes;
+
Attrs |= B.Attrs;
- for (td_const_iterator I = B.TargetDepAttrs.begin(),
- E = B.TargetDepAttrs.end(); I != E; ++I)
- TargetDepAttrs[I->first] = I->second;
+ for (auto I : B.td_attrs())
+ TargetDepAttrs[I.first] = I.second;
+
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
+ // FIXME: What if both have alignments, but they don't match?!
+ if (B.Alignment)
+ Alignment = 0;
+
+ if (B.StackAlignment)
+ StackAlignment = 0;
+
+ if (B.DerefBytes)
+ DerefBytes = 0;
+
+ if (B.DerefOrNullBytes)
+ DerefOrNullBytes = 0;
+
+ Attrs &= ~B.Attrs;
+
+ for (auto I : B.td_attrs())
+ TargetDepAttrs.erase(I.first);
return *this;
}
+bool AttrBuilder::overlaps(const AttrBuilder &B) const {
+ // First check if any of the target independent attributes overlap.
+ if ((Attrs & B.Attrs).any())
+ return true;
+
+ // Then check if any target dependent ones do.
+ for (auto I : td_attrs())
+ if (B.contains(I.first))
+ return true;
+
+ return false;
+}
+
bool AttrBuilder::contains(StringRef A) const {
return TargetDepAttrs.find(A) != TargetDepAttrs.end();
}
@@ -1218,7 +1352,8 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
I = Attribute::AttrKind(I + 1)) {
- if (I == Attribute::Dereferenceable)
+ if (I == Attribute::Dereferenceable ||
+ I == Attribute::DereferenceableOrNull)
continue;
if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
Attrs[I] = true;
@@ -1238,7 +1373,7 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
//===----------------------------------------------------------------------===//
/// \brief Which attributes cannot be applied to a type.
-AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {
+AttrBuilder AttributeFuncs::typeIncompatible(const Type *Ty) {
AttrBuilder Incompatible;
if (!Ty->isIntegerTy())
@@ -1254,10 +1389,11 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {
.addAttribute(Attribute::NoCapture)
.addAttribute(Attribute::NonNull)
.addDereferenceableAttr(1) // the int here is ignored
+ .addDereferenceableOrNullAttr(1) // the int here is ignored
.addAttribute(Attribute::ReadNone)
.addAttribute(Attribute::ReadOnly)
.addAttribute(Attribute::StructRet)
.addAttribute(Attribute::InAlloca);
- return AttributeSet::get(Ty->getContext(), Index, Incompatible);
+ return Incompatible;
}
OpenPOWER on IntegriCloud