diff options
Diffstat (limited to 'contrib/llvm/lib/IR/Attributes.cpp')
| -rw-r--r-- | contrib/llvm/lib/IR/Attributes.cpp | 143 | 
1 files changed, 113 insertions, 30 deletions
diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp index 0f2b7a0ebb4f..04545ea919a4 100644 --- a/contrib/llvm/lib/IR/Attributes.cpp +++ b/contrib/llvm/lib/IR/Attributes.cpp @@ -16,6 +16,7 @@  #include "llvm/IR/Attributes.h"  #include "AttributeImpl.h"  #include "LLVMContextImpl.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/StringExtras.h"  #include "llvm/IR/Type.h"  #include "llvm/Support/Atomic.h" @@ -46,7 +47,7 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,      if (!Val)        PA = new EnumAttributeImpl(Kind);      else -      PA = new AlignAttributeImpl(Kind, Val); +      PA = new IntAttributeImpl(Kind, Val);      pImpl->AttrsSet.InsertNode(PA, InsertPoint);    } @@ -87,6 +88,12 @@ Attribute Attribute::getWithStackAlignment(LLVMContext &Context,    return get(Context, StackAlignment, Align);  } +Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context, +                                                uint64_t Bytes) { +  assert(Bytes && "Bytes must be non-zero."); +  return get(Context, Dereferenceable, Bytes); +} +  //===----------------------------------------------------------------------===//  // Attribute Accessor Methods  //===----------------------------------------------------------------------===// @@ -95,8 +102,8 @@ bool Attribute::isEnumAttribute() const {    return pImpl && pImpl->isEnumAttribute();  } -bool Attribute::isAlignAttribute() const { -  return pImpl && pImpl->isAlignAttribute(); +bool Attribute::isIntAttribute() const { +  return pImpl && pImpl->isIntAttribute();  }  bool Attribute::isStringAttribute() const { @@ -105,15 +112,15 @@ bool Attribute::isStringAttribute() const {  Attribute::AttrKind Attribute::getKindAsEnum() const {    if (!pImpl) return None; -  assert((isEnumAttribute() || isAlignAttribute()) && +  assert((isEnumAttribute() || isIntAttribute()) &&           "Invalid attribute type to get the kind as an enum!");    return pImpl ? pImpl->getKindAsEnum() : None;  }  uint64_t Attribute::getValueAsInt() const {    if (!pImpl) return 0; -  assert(isAlignAttribute() && -         "Expected the attribute to be an alignment attribute!"); +  assert(isIntAttribute() && +         "Expected the attribute to be an integer attribute!");    return pImpl ? pImpl->getValueAsInt() : 0;  } @@ -155,6 +162,14 @@ unsigned Attribute::getStackAlignment() const {    return pImpl->getValueAsInt();  } +/// This returns the number of dereferenceable bytes. +uint64_t Attribute::getDereferenceableBytes() const { +  assert(hasAttribute(Attribute::Dereferenceable) && +         "Trying to get dereferenceable bytes from " +         "non-dereferenceable attribute!"); +  return pImpl->getValueAsInt(); +} +  std::string Attribute::getAsString(bool InAttrGrp) const {    if (!pImpl) return ""; @@ -166,10 +181,14 @@ std::string Attribute::getAsString(bool InAttrGrp) const {      return "builtin";    if (hasAttribute(Attribute::ByVal))      return "byval"; +  if (hasAttribute(Attribute::InAlloca)) +    return "inalloca";    if (hasAttribute(Attribute::InlineHint))      return "inlinehint";    if (hasAttribute(Attribute::InReg))      return "inreg"; +  if (hasAttribute(Attribute::JumpTable)) +    return "jumptable";    if (hasAttribute(Attribute::MinSize))      return "minsize";    if (hasAttribute(Attribute::Naked)) @@ -190,6 +209,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {      return "noinline";    if (hasAttribute(Attribute::NonLazyBind))      return "nonlazybind"; +  if (hasAttribute(Attribute::NonNull)) +    return "nonnull";    if (hasAttribute(Attribute::NoRedZone))      return "noredzone";    if (hasAttribute(Attribute::NoReturn)) @@ -256,6 +277,20 @@ std::string Attribute::getAsString(bool InAttrGrp) const {      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; +  } +    // Convert target-dependent attributes to strings of the form:    //    //   "kind" @@ -286,10 +321,10 @@ bool Attribute::operator<(Attribute A) const {  // AttributeImpl Definition  //===----------------------------------------------------------------------===// -// Pin the vtabels to this file. +// Pin the vtables to this file.  AttributeImpl::~AttributeImpl() {}  void EnumAttributeImpl::anchor() {} -void AlignAttributeImpl::anchor() {} +void IntAttributeImpl::anchor() {}  void StringAttributeImpl::anchor() {}  bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { @@ -303,13 +338,13 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const {  }  Attribute::AttrKind AttributeImpl::getKindAsEnum() const { -  assert(isEnumAttribute() || isAlignAttribute()); +  assert(isEnumAttribute() || isIntAttribute());    return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();  }  uint64_t AttributeImpl::getValueAsInt() const { -  assert(isAlignAttribute()); -  return static_cast<const AlignAttributeImpl *>(this)->getAlignment(); +  assert(isIntAttribute()); +  return static_cast<const IntAttributeImpl *>(this)->getValue();  }  StringRef AttributeImpl::getKindAsString() const { @@ -327,18 +362,18 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {    // relative to their enum value) and then strings.    if (isEnumAttribute()) {      if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); -    if (AI.isAlignAttribute()) return true; +    if (AI.isIntAttribute()) return true;      if (AI.isStringAttribute()) return true;    } -  if (isAlignAttribute()) { +  if (isIntAttribute()) {      if (AI.isEnumAttribute()) return false; -    if (AI.isAlignAttribute()) return getValueAsInt() < AI.getValueAsInt(); +    if (AI.isIntAttribute()) return getValueAsInt() < AI.getValueAsInt();      if (AI.isStringAttribute()) return true;    }    if (AI.isEnumAttribute()) return false; -  if (AI.isAlignAttribute()) return false; +  if (AI.isIntAttribute()) return false;    if (getKindAsString() == AI.getKindAsString())      return getValueAsString() < AI.getValueAsString();    return getKindAsString() < AI.getKindAsString(); @@ -388,6 +423,11 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {    case Attribute::Cold:            return 1ULL << 40;    case Attribute::Builtin:         return 1ULL << 41;    case Attribute::OptimizeNone:    return 1ULL << 42; +  case Attribute::InAlloca:        return 1ULL << 43; +  case Attribute::NonNull:         return 1ULL << 44; +  case Attribute::JumpTable:       return 1ULL << 45; +  case Attribute::Dereferenceable: +    llvm_unreachable("dereferenceable attribute not supported in raw format");    }    llvm_unreachable("Unsupported attribute type");  } @@ -399,7 +439,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {  AttributeSetNode *AttributeSetNode::get(LLVMContext &C,                                          ArrayRef<Attribute> Attrs) {    if (Attrs.empty()) -    return 0; +    return nullptr;    // Otherwise, build a key to look up the existing attributes.    LLVMContextImpl *pImpl = C.pImpl; @@ -472,6 +512,13 @@ unsigned AttributeSetNode::getStackAlignment() const {    return 0;  } +uint64_t AttributeSetNode::getDereferenceableBytes() const { +  for (iterator I = begin(), E = end(); I != E; ++I) +    if (I->hasAttribute(Attribute::Dereferenceable)) +      return I->getDereferenceableBytes(); +  return 0; +} +  std::string AttributeSetNode::getAsString(bool InAttrGrp) const {    std::string Str;    for (iterator I = begin(), E = end(); I != E; ++I) { @@ -505,6 +552,8 @@ uint64_t AttributeSetImpl::Raw(unsigned Index) const {          Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16;        else if (Kind == Attribute::StackAlignment)          Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26; +      else if (Kind == Attribute::Dereferenceable) +        llvm_unreachable("dereferenceable not supported in bit mask");        else          Mask |= AttributeImpl::getAttrMask(Kind);      } @@ -592,7 +641,8 @@ AttributeSet AttributeSet::get(LLVMContext &C,    return getImpl(C, Attrs);  } -AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, AttrBuilder &B) { +AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, +                               const AttrBuilder &B) {    if (!B.hasAttributes())      return AttributeSet(); @@ -609,14 +659,18 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, AttrBuilder &B) {      else if (Kind == Attribute::StackAlignment)        Attrs.push_back(std::make_pair(Index, Attribute::                                getWithStackAlignment(C, B.getStackAlignment()))); +    else if (Kind == Attribute::Dereferenceable) +      Attrs.push_back(std::make_pair(Index, +                                     Attribute::getWithDereferenceableBytes(C, +                                       B.getDereferenceableBytes())));      else        Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind)));    }    // Add target-dependent (string) attributes. -  for (AttrBuilder::td_iterator I = B.td_begin(), E = B.td_end(); -       I != E; ++I) -    Attrs.push_back(std::make_pair(Index, Attribute::get(C, I->first,I->second))); +  for (const AttrBuilder::td_type &TDA : B.td_attrs()) +    Attrs.push_back( +        std::make_pair(Index, Attribute::get(C, TDA.first, TDA.second)));    return get(C, Attrs);  } @@ -833,7 +887,7 @@ bool AttributeSet::hasAttributes(unsigned Index) const {  /// \brief Return true if the specified attribute is set for at least one  /// parameter or for the return value.  bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { -  if (pImpl == 0) return false; +  if (!pImpl) return false;    for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I)      for (AttributeSetImpl::iterator II = pImpl->begin(I), @@ -866,6 +920,11 @@ unsigned AttributeSet::getStackAlignment(unsigned Index) const {    return ASN ? ASN->getStackAlignment() : 0;  } +uint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const { +  AttributeSetNode *ASN = getAttributes(Index); +  return ASN ? ASN->getDereferenceableBytes() : 0; +} +  std::string AttributeSet::getAsString(unsigned Index,                                        bool InAttrGrp) const {    AttributeSetNode *ASN = getAttributes(Index); @@ -874,14 +933,14 @@ std::string AttributeSet::getAsString(unsigned Index,  /// \brief The attributes for the specified index are returned.  AttributeSetNode *AttributeSet::getAttributes(unsigned Index) const { -  if (!pImpl) return 0; +  if (!pImpl) return nullptr;    // Loop through to find the attribute node we want.    for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I)      if (pImpl->getSlotIndex(I) == Index)        return pImpl->getSlotNode(I); -  return 0; +  return nullptr;  }  AttributeSet::iterator AttributeSet::begin(unsigned Slot) const { @@ -945,7 +1004,7 @@ void AttributeSet::dump() const {  //===----------------------------------------------------------------------===//  AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) -  : Attrs(0), Alignment(0), StackAlignment(0) { +  : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {    AttributeSetImpl *pImpl = AS.pImpl;    if (!pImpl) return; @@ -962,13 +1021,14 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)  void AttrBuilder::clear() {    Attrs.reset(); -  Alignment = StackAlignment = 0; +  Alignment = StackAlignment = DerefBytes = 0;  }  AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {    assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");    assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment && -         "Adding alignment attribute without adding alignment value!"); +         Val != Attribute::Dereferenceable && +         "Adding integer attribute without adding a value!");    Attrs[Val] = true;    return *this;  } @@ -986,6 +1046,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {      Alignment = Attr.getAlignment();    else if (Kind == Attribute::StackAlignment)      StackAlignment = Attr.getStackAlignment(); +  else if (Kind == Attribute::Dereferenceable) +    DerefBytes = Attr.getDereferenceableBytes();    return *this;  } @@ -1002,6 +1064,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {      Alignment = 0;    else if (Val == Attribute::StackAlignment)      StackAlignment = 0; +  else if (Val == Attribute::Dereferenceable) +    DerefBytes = 0;    return *this;  } @@ -1018,7 +1082,7 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {    for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {      Attribute Attr = *I; -    if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { +    if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {        Attribute::AttrKind Kind = I->getKindAsEnum();        Attrs[Kind] = false; @@ -1026,6 +1090,8 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {          Alignment = 0;        else if (Kind == Attribute::StackAlignment)          StackAlignment = 0; +      else if (Kind == Attribute::Dereferenceable) +        DerefBytes = 0;      } else {        assert(Attr.isStringAttribute() && "Invalid attribute type!");        std::map<std::string, std::string>::iterator @@ -1068,6 +1134,14 @@ AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {    return *this;  } +AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) { +  if (Bytes == 0) return *this; + +  Attrs[Attribute::Dereferenceable] = true; +  DerefBytes = Bytes; +  return *this; +} +  AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {    // FIXME: What if both have alignments, but they don't match?!    if (!Alignment) @@ -1076,6 +1150,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {    if (!StackAlignment)      StackAlignment = B.StackAlignment; +  if (!DerefBytes) +    DerefBytes = B.DerefBytes; +    Attrs |= B.Attrs;    for (td_const_iterator I = B.TargetDepAttrs.begin(), @@ -1106,7 +1183,7 @@ bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const {    for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot);         I != E; ++I) {      Attribute Attr = *I; -    if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { +    if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {        if (Attrs[I->getKindAsEnum()])          return true;      } else { @@ -1131,7 +1208,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {      if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())        return false; -  return Alignment == B.Alignment && StackAlignment == B.StackAlignment; +  return Alignment == B.Alignment && StackAlignment == B.StackAlignment && +         DerefBytes == B.DerefBytes;  }  AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { @@ -1140,6 +1218,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) +      continue;      if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {        Attrs[I] = true; @@ -1172,9 +1252,12 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {        .addAttribute(Attribute::Nest)        .addAttribute(Attribute::NoAlias)        .addAttribute(Attribute::NoCapture) +      .addAttribute(Attribute::NonNull) +      .addDereferenceableAttr(1) // the int here is ignored        .addAttribute(Attribute::ReadNone)        .addAttribute(Attribute::ReadOnly) -      .addAttribute(Attribute::StructRet); +      .addAttribute(Attribute::StructRet) +      .addAttribute(Attribute::InAlloca);    return AttributeSet::get(Ty->getContext(), Index, Incompatible);  }  | 
