diff options
Diffstat (limited to 'contrib/llvm/lib/IR/Attributes.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/Attributes.cpp | 192 |
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; } |