diff options
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r-- | llvm/lib/IR/Attributes.cpp | 623 |
1 files changed, 310 insertions, 313 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index c4629decc6d9..5cd1bafccc47 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -78,8 +78,24 @@ unpackAllocSizeArgs(uint64_t Num) { return std::make_pair(ElemSizeArg, NumElemsArg); } +static uint64_t packVScaleRangeArgs(unsigned MinValue, unsigned MaxValue) { + return uint64_t(MinValue) << 32 | MaxValue; +} + +static std::pair<unsigned, unsigned> unpackVScaleRangeArgs(uint64_t Value) { + unsigned MaxValue = Value & std::numeric_limits<unsigned>::max(); + unsigned MinValue = Value >> 32; + + return std::make_pair(MinValue, MaxValue); +} + 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"); + LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; ID.AddInteger(Kind); @@ -127,6 +143,7 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, Type *Ty) { + assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute"); LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; ID.AddInteger(Kind); @@ -184,6 +201,10 @@ Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) { return get(Context, Preallocated, Ty); } +Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) { + return get(Context, InAlloca, Ty); +} + Attribute Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const Optional<unsigned> &NumElemsArg) { @@ -192,6 +213,12 @@ Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg)); } +Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context, + unsigned MinValue, + unsigned MaxValue) { + return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue)); +} + Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) { return StringSwitch<Attribute::AttrKind>(AttrName) #define GET_ATTR_NAMES @@ -215,14 +242,6 @@ StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) { } } -bool Attribute::doesAttrKindHaveArgument(Attribute::AttrKind AttrKind) { - return AttrKind == Attribute::Alignment || - AttrKind == Attribute::StackAlignment || - AttrKind == Attribute::Dereferenceable || - AttrKind == Attribute::AllocSize || - AttrKind == Attribute::DereferenceableOrNull; -} - bool Attribute::isExistingAttribute(StringRef Name) { return StringSwitch<bool>(Name) #define GET_ATTR_NAMES @@ -265,6 +284,13 @@ uint64_t Attribute::getValueAsInt() const { return pImpl->getValueAsInt(); } +bool Attribute::getValueAsBool() const { + if (!pImpl) return false; + assert(isStringAttribute() && + "Expected the attribute to be a string attribute!"); + return pImpl->getValueAsBool(); +} + StringRef Attribute::getKindAsString() const { if (!pImpl) return {}; assert(isStringAttribute() && @@ -328,157 +354,22 @@ std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const { return unpackAllocSizeArgs(pImpl->getValueAsInt()); } +std::pair<unsigned, unsigned> Attribute::getVScaleRangeArgs() const { + assert(hasAttribute(Attribute::VScaleRange) && + "Trying to get vscale args from non-vscale attribute"); + return unpackVScaleRangeArgs(pImpl->getValueAsInt()); +} + std::string Attribute::getAsString(bool InAttrGrp) const { if (!pImpl) return {}; - if (hasAttribute(Attribute::SanitizeAddress)) - return "sanitize_address"; - if (hasAttribute(Attribute::SanitizeHWAddress)) - return "sanitize_hwaddress"; - if (hasAttribute(Attribute::SanitizeMemTag)) - return "sanitize_memtag"; - if (hasAttribute(Attribute::AlwaysInline)) - return "alwaysinline"; - if (hasAttribute(Attribute::ArgMemOnly)) - return "argmemonly"; - if (hasAttribute(Attribute::Builtin)) - return "builtin"; - if (hasAttribute(Attribute::Convergent)) - return "convergent"; - if (hasAttribute(Attribute::SwiftError)) - return "swifterror"; - if (hasAttribute(Attribute::SwiftSelf)) - return "swiftself"; - if (hasAttribute(Attribute::InaccessibleMemOnly)) - return "inaccessiblememonly"; - if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) - return "inaccessiblemem_or_argmemonly"; - 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)) - return "naked"; - if (hasAttribute(Attribute::Nest)) - return "nest"; - if (hasAttribute(Attribute::NoAlias)) - return "noalias"; - if (hasAttribute(Attribute::NoBuiltin)) - return "nobuiltin"; - if (hasAttribute(Attribute::NoCallback)) - return "nocallback"; - if (hasAttribute(Attribute::NoCapture)) - return "nocapture"; - if (hasAttribute(Attribute::NoDuplicate)) - return "noduplicate"; - if (hasAttribute(Attribute::NoFree)) - return "nofree"; - if (hasAttribute(Attribute::NoImplicitFloat)) - return "noimplicitfloat"; - if (hasAttribute(Attribute::NoInline)) - return "noinline"; - if (hasAttribute(Attribute::NonLazyBind)) - return "nonlazybind"; - if (hasAttribute(Attribute::NoMerge)) - return "nomerge"; - if (hasAttribute(Attribute::NonNull)) - return "nonnull"; - if (hasAttribute(Attribute::NoRedZone)) - return "noredzone"; - if (hasAttribute(Attribute::NoReturn)) - return "noreturn"; - if (hasAttribute(Attribute::NoSync)) - return "nosync"; - if (hasAttribute(Attribute::NullPointerIsValid)) - return "null_pointer_is_valid"; - if (hasAttribute(Attribute::WillReturn)) - return "willreturn"; - if (hasAttribute(Attribute::NoCfCheck)) - return "nocf_check"; - if (hasAttribute(Attribute::NoRecurse)) - return "norecurse"; - if (hasAttribute(Attribute::NoProfile)) - return "noprofile"; - if (hasAttribute(Attribute::NoUnwind)) - return "nounwind"; - if (hasAttribute(Attribute::OptForFuzzing)) - return "optforfuzzing"; - if (hasAttribute(Attribute::OptimizeNone)) - return "optnone"; - if (hasAttribute(Attribute::OptimizeForSize)) - return "optsize"; - if (hasAttribute(Attribute::ReadNone)) - return "readnone"; - if (hasAttribute(Attribute::ReadOnly)) - return "readonly"; - if (hasAttribute(Attribute::WriteOnly)) - return "writeonly"; - if (hasAttribute(Attribute::Returned)) - return "returned"; - if (hasAttribute(Attribute::ReturnsTwice)) - return "returns_twice"; - if (hasAttribute(Attribute::SExt)) - return "signext"; - if (hasAttribute(Attribute::SpeculativeLoadHardening)) - return "speculative_load_hardening"; - if (hasAttribute(Attribute::Speculatable)) - return "speculatable"; - if (hasAttribute(Attribute::StackProtect)) - return "ssp"; - if (hasAttribute(Attribute::StackProtectReq)) - return "sspreq"; - if (hasAttribute(Attribute::StackProtectStrong)) - return "sspstrong"; - if (hasAttribute(Attribute::SafeStack)) - return "safestack"; - if (hasAttribute(Attribute::ShadowCallStack)) - return "shadowcallstack"; - if (hasAttribute(Attribute::StrictFP)) - return "strictfp"; - if (hasAttribute(Attribute::SanitizeThread)) - return "sanitize_thread"; - if (hasAttribute(Attribute::SanitizeMemory)) - return "sanitize_memory"; - if (hasAttribute(Attribute::UWTable)) - return "uwtable"; - if (hasAttribute(Attribute::ZExt)) - return "zeroext"; - if (hasAttribute(Attribute::Cold)) - return "cold"; - if (hasAttribute(Attribute::Hot)) - return "hot"; - if (hasAttribute(Attribute::ImmArg)) - return "immarg"; - if (hasAttribute(Attribute::NoUndef)) - return "noundef"; - if (hasAttribute(Attribute::MustProgress)) - return "mustprogress"; - - const bool IsByVal = hasAttribute(Attribute::ByVal); - if (IsByVal || hasAttribute(Attribute::StructRet)) { - std::string Result; - Result += IsByVal ? "byval" : "sret"; - if (Type *Ty = getValueAsType()) { - raw_string_ostream OS(Result); - Result += '('; - Ty->print(OS, false, true); - OS.flush(); - Result += ')'; - } - return Result; - } + if (isEnumAttribute()) + return getNameFromAttrKind(getKindAsEnum()).str(); - const bool IsByRef = hasAttribute(Attribute::ByRef); - if (IsByRef || hasAttribute(Attribute::Preallocated)) { - std::string Result = IsByRef ? "byref" : "preallocated"; - raw_string_ostream OS(Result); + if (isTypeAttribute()) { + std::string Result = getNameFromAttrKind(getKindAsEnum()).str(); Result += '('; + raw_string_ostream OS(Result); getValueAsType()->print(OS, false, true); OS.flush(); Result += ')'; @@ -536,6 +427,18 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return Result; } + if (hasAttribute(Attribute::VScaleRange)) { + unsigned MinValue, MaxValue; + std::tie(MinValue, MaxValue) = getVScaleRangeArgs(); + + std::string Result = "vscale_range("; + Result += utostr(MinValue); + Result += ','; + Result += utostr(MaxValue); + Result += ')'; + return Result; + } + // Convert target-dependent attributes to strings of the form: // // "kind" @@ -563,6 +466,14 @@ std::string Attribute::getAsString(bool InAttrGrp) const { llvm_unreachable("Unknown attribute"); } +bool Attribute::hasParentContext(LLVMContext &C) const { + assert(isValid() && "invalid Attribute doesn't refer to any context"); + FoldingSetNodeID ID; + pImpl->Profile(ID); + void *Unused; + return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl; +} + bool Attribute::operator<(Attribute A) const { if (!pImpl && !A.pImpl) return false; if (!pImpl) return true; @@ -574,6 +485,35 @@ void Attribute::Profile(FoldingSetNodeID &ID) const { ID.AddPointer(pImpl); } +enum AttributeProperty { + FnAttr = (1 << 0), + ParamAttr = (1 << 1), + RetAttr = (1 << 2), +}; + +#define GET_ATTR_PROP_TABLE +#include "llvm/IR/Attributes.inc" + +static bool hasAttributeProperty(Attribute::AttrKind Kind, + AttributeProperty Prop) { + unsigned Index = Kind - 1; + assert(Index < sizeof(AttrPropTable) / sizeof(AttrPropTable[0]) && + "Invalid attribute kind"); + return AttrPropTable[Index] & Prop; +} + +bool Attribute::canUseAsFnAttr(AttrKind Kind) { + return hasAttributeProperty(Kind, AttributeProperty::FnAttr); +} + +bool Attribute::canUseAsParamAttr(AttrKind Kind) { + return hasAttributeProperty(Kind, AttributeProperty::ParamAttr); +} + +bool Attribute::canUseAsRetAttr(AttrKind Kind) { + return hasAttributeProperty(Kind, AttributeProperty::RetAttr); +} + //===----------------------------------------------------------------------===// // AttributeImpl Definition //===----------------------------------------------------------------------===// @@ -598,6 +538,11 @@ uint64_t AttributeImpl::getValueAsInt() const { return static_cast<const IntAttributeImpl *>(this)->getValue(); } +bool AttributeImpl::getValueAsBool() const { + assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true"); + return getValueAsString() == "true"; +} + StringRef AttributeImpl::getKindAsString() const { assert(isStringAttribute()); return static_cast<const StringAttributeImpl *>(this)->getStringKind(); @@ -616,41 +561,23 @@ Type *AttributeImpl::getValueAsType() const { bool AttributeImpl::operator<(const AttributeImpl &AI) const { if (this == &AI) return false; + // This sorts the attributes with Attribute::AttrKinds coming first (sorted // relative to their enum value) and then strings. - if (isEnumAttribute()) { - if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); - if (AI.isIntAttribute()) return true; - if (AI.isStringAttribute()) return true; - if (AI.isTypeAttribute()) return true; - } - - if (isTypeAttribute()) { - if (AI.isEnumAttribute()) return false; - if (AI.isTypeAttribute()) { - assert(getKindAsEnum() != AI.getKindAsEnum() && - "Comparison of types would be unstable"); - return getKindAsEnum() < AI.getKindAsEnum(); - } - if (AI.isIntAttribute()) return true; - if (AI.isStringAttribute()) return true; - } - - if (isIntAttribute()) { - if (AI.isEnumAttribute()) return false; - if (AI.isTypeAttribute()) return false; - if (AI.isIntAttribute()) { - if (getKindAsEnum() == AI.getKindAsEnum()) - return getValueAsInt() < AI.getValueAsInt(); + if (!isStringAttribute()) { + if (AI.isStringAttribute()) + return true; + if (getKindAsEnum() != AI.getKindAsEnum()) return getKindAsEnum() < AI.getKindAsEnum(); - } - if (AI.isStringAttribute()) return true; + assert(!AI.isEnumAttribute() && "Non-unique attribute"); + assert(!AI.isTypeAttribute() && "Comparison of types would be unstable"); + // TODO: Is this actually needed? + assert(AI.isIntAttribute() && "Only possibility left"); + return getValueAsInt() < AI.getValueAsInt(); } - assert(isStringAttribute()); - if (AI.isEnumAttribute()) return false; - if (AI.isTypeAttribute()) return false; - if (AI.isIntAttribute()) return false; + if (!AI.isStringAttribute()) + return false; if (getKindAsString() == AI.getKindAsString()) return getValueAsString() < AI.getValueAsString(); return getKindAsString() < AI.getKindAsString(); @@ -715,8 +642,12 @@ AttributeSet AttributeSet::removeAttribute(LLVMContext &C, } AttributeSet AttributeSet::removeAttributes(LLVMContext &C, - const AttrBuilder &Attrs) const { + const AttrBuilder &Attrs) const { AttrBuilder B(*this); + // If there is nothing to remove, directly return the original set. + if (!B.overlaps(Attrs)) + return *this; + B.remove(Attrs); return get(C, B); } @@ -758,19 +689,27 @@ uint64_t AttributeSet::getDereferenceableOrNullBytes() const { } Type *AttributeSet::getByRefType() const { - return SetNode ? SetNode->getByRefType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr; } Type *AttributeSet::getByValType() const { - return SetNode ? SetNode->getByValType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr; } Type *AttributeSet::getStructRetType() const { - return SetNode ? SetNode->getStructRetType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr; } Type *AttributeSet::getPreallocatedType() const { - return SetNode ? SetNode->getPreallocatedType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr; +} + +Type *AttributeSet::getInAllocaType() const { + return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr; +} + +Type *AttributeSet::getElementType() const { + return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr; } std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const { @@ -778,10 +717,23 @@ std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const { : std::pair<unsigned, Optional<unsigned>>(0, 0); } +std::pair<unsigned, unsigned> AttributeSet::getVScaleRangeArgs() const { + return SetNode ? SetNode->getVScaleRangeArgs() + : std::pair<unsigned, unsigned>(0, 0); +} + std::string AttributeSet::getAsString(bool InAttrGrp) const { return SetNode ? SetNode->getAsString(InAttrGrp) : ""; } +bool AttributeSet::hasParentContext(LLVMContext &C) const { + assert(hasAttributes() && "empty AttributeSet doesn't refer to any context"); + FoldingSetNodeID ID; + SetNode->Profile(ID); + void *Unused; + return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode; +} + AttributeSet::iterator AttributeSet::begin() const { return SetNode ? SetNode->begin() : nullptr; } @@ -860,20 +812,13 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { if (!B.contains(Kind)) continue; + if (Attribute::isTypeAttrKind(Kind)) { + Attrs.push_back(Attribute::get(C, Kind, B.getTypeAttr(Kind))); + continue; + } + Attribute Attr; switch (Kind) { - case Attribute::ByVal: - Attr = Attribute::getWithByValType(C, B.getByValType()); - break; - case Attribute::StructRet: - Attr = Attribute::getWithStructRetType(C, B.getStructRetType()); - break; - case Attribute::ByRef: - Attr = Attribute::getWithByRefType(C, B.getByRefType()); - break; - case Attribute::Preallocated: - Attr = Attribute::getWithPreallocatedType(C, B.getPreallocatedType()); - break; case Attribute::Alignment: assert(B.getAlignment() && "Alignment must be set"); Attr = Attribute::getWithAlignment(C, *B.getAlignment()); @@ -895,6 +840,11 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second); break; } + case Attribute::VScaleRange: { + auto A = B.getVScaleRangeArgs(); + Attr = Attribute::getWithVScaleRangeArgs(C, A.first, A.second); + break; + } default: Attr = Attribute::get(C, Kind); } @@ -951,26 +901,8 @@ MaybeAlign AttributeSetNode::getStackAlignment() const { return None; } -Type *AttributeSetNode::getByValType() const { - if (auto A = findEnumAttribute(Attribute::ByVal)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getStructRetType() const { - if (auto A = findEnumAttribute(Attribute::StructRet)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getByRefType() const { - if (auto A = findEnumAttribute(Attribute::ByRef)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getPreallocatedType() const { - if (auto A = findEnumAttribute(Attribute::Preallocated)) +Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const { + if (auto A = findEnumAttribute(Kind)) return A->getValueAsType(); return nullptr; } @@ -994,6 +926,12 @@ AttributeSetNode::getAllocSizeArgs() const { return std::make_pair(0, 0); } +std::pair<unsigned, unsigned> AttributeSetNode::getVScaleRangeArgs() const { + if (auto A = findEnumAttribute(Attribute::VScaleRange)) + return A->getVScaleRangeArgs(); + return std::make_pair(0, 0); +} + std::string AttributeSetNode::getAsString(bool InAttrGrp) const { std::string Str; for (iterator I = begin(), E = end(); I != E; ++I) { @@ -1377,17 +1315,12 @@ AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &AttrsToRemove) const { - if (!pImpl) - return {}; - - Index = attrIdxToArrayIdx(Index); - SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); - if (Index >= AttrSets.size()) - AttrSets.resize(Index + 1); - - AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove); - - return getImpl(C, AttrSets); + AttributeSet Attrs = getAttributes(Index); + AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove); + // If nothing was removed, return the original list. + if (Attrs == NewAttrs) + return *this; + return setAttributes(C, Index, NewAttrs); } AttributeList AttributeList::removeAttributes(LLVMContext &C, @@ -1427,6 +1360,14 @@ AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index, return addAttributes(C, Index, B); } +AttributeList AttributeList::addVScaleRangeAttr(LLVMContext &C, unsigned Index, + unsigned MinValue, + unsigned MaxValue) { + AttrBuilder B; + B.addVScaleRangeAttr(MinValue, MaxValue); + return addAttributes(C, Index, B); +} + //===----------------------------------------------------------------------===// // AttributeList Accessor Methods //===----------------------------------------------------------------------===// @@ -1491,6 +1432,10 @@ MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const { return getAttributes(ArgNo + FirstArgIndex).getAlignment(); } +MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const { + return getAttributes(ArgNo + FirstArgIndex).getStackAlignment(); +} + Type *AttributeList::getParamByValType(unsigned Index) const { return getAttributes(Index+FirstArgIndex).getByValType(); } @@ -1507,6 +1452,14 @@ Type *AttributeList::getParamPreallocatedType(unsigned Index) const { return getAttributes(Index + FirstArgIndex).getPreallocatedType(); } +Type *AttributeList::getParamInAllocaType(unsigned Index) const { + return getAttributes(Index + FirstArgIndex).getInAllocaType(); +} + +Type *AttributeList::getParamElementType(unsigned Index) const { + return getAttributes(Index + FirstArgIndex).getElementType(); +} + MaybeAlign AttributeList::getStackAlignment(unsigned Index) const { return getAttributes(Index).getStackAlignment(); } @@ -1524,6 +1477,11 @@ AttributeList::getAllocSizeArgs(unsigned Index) const { return getAttributes(Index).getAllocSizeArgs(); } +std::pair<unsigned, unsigned> +AttributeList::getVScaleRangeArgs(unsigned Index) const { + return getAttributes(Index).getVScaleRangeArgs(); +} + std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const { return getAttributes(Index).getAsString(InAttrGrp); } @@ -1535,6 +1493,14 @@ AttributeSet AttributeList::getAttributes(unsigned Index) const { return pImpl->begin()[Index]; } +bool AttributeList::hasParentContext(LLVMContext &C) const { + assert(!isEmpty() && "an empty attribute list has no parent context"); + FoldingSetNodeID ID; + pImpl->Profile(ID); + void *Unused; + return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl; +} + AttributeList::iterator AttributeList::begin() const { return pImpl ? pImpl->begin() : nullptr; } @@ -1551,17 +1517,31 @@ unsigned AttributeList::getNumAttrSets() const { return pImpl ? pImpl->NumAttrSets : 0; } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void AttributeList::dump() const { - dbgs() << "PAL[\n"; +void AttributeList::print(raw_ostream &O) const { + O << "AttributeList[\n"; for (unsigned i = index_begin(), e = index_end(); i != e; ++i) { - if (getAttributes(i).hasAttributes()) - dbgs() << " { " << i << " => " << getAsString(i) << " }\n"; + if (!getAttributes(i).hasAttributes()) + continue; + O << " { "; + switch (i) { + case AttrIndex::ReturnIndex: + O << "return"; + break; + case AttrIndex::FunctionIndex: + O << "function"; + break; + default: + O << "arg(" << i - AttrIndex::FirstArgIndex << ")"; + } + O << " => " << getAsString(i) << " }\n"; } - dbgs() << "]\n"; + O << "]\n"; } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); } #endif //===----------------------------------------------------------------------===// @@ -1587,10 +1567,15 @@ void AttrBuilder::clear() { StackAlignment.reset(); DerefBytes = DerefOrNullBytes = 0; AllocSizeArgs = 0; - ByValType = nullptr; - StructRetType = nullptr; - ByRefType = nullptr; - PreallocatedType = nullptr; + VScaleRangeArgs = 0; + TypeAttrs = {}; +} + +Optional<unsigned> +AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const { + if (Attribute::isTypeAttrKind(Kind)) + return Kind - Attribute::FirstTypeAttr; + return None; } AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { @@ -1602,29 +1587,26 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { Attribute::AttrKind Kind = Attr.getKindAsEnum(); Attrs[Kind] = true; - if (Kind == Attribute::Alignment) + if (Optional<unsigned> TypeIndex = kindToTypeIndex(Kind)) + TypeAttrs[*TypeIndex] = Attr.getValueAsType(); + else if (Kind == Attribute::Alignment) Alignment = Attr.getAlignment(); else if (Kind == Attribute::StackAlignment) StackAlignment = Attr.getStackAlignment(); - else if (Kind == Attribute::ByVal) - ByValType = Attr.getValueAsType(); - else if (Kind == Attribute::StructRet) - StructRetType = Attr.getValueAsType(); - else if (Kind == Attribute::ByRef) - ByRefType = Attr.getValueAsType(); - else if (Kind == Attribute::Preallocated) - PreallocatedType = Attr.getValueAsType(); else if (Kind == Attribute::Dereferenceable) DerefBytes = Attr.getDereferenceableBytes(); else if (Kind == Attribute::DereferenceableOrNull) DerefOrNullBytes = Attr.getDereferenceableOrNullBytes(); else if (Kind == Attribute::AllocSize) AllocSizeArgs = Attr.getValueAsInt(); + else if (Kind == Attribute::VScaleRange) + VScaleRangeArgs = Attr.getValueAsInt(); + return *this; } AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) { - TargetDepAttrs[std::string(A)] = std::string(V); + TargetDepAttrs[A] = V; return *this; } @@ -1632,24 +1614,20 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); Attrs[Val] = false; - if (Val == Attribute::Alignment) + if (Optional<unsigned> TypeIndex = kindToTypeIndex(Val)) + TypeAttrs[*TypeIndex] = nullptr; + else if (Val == Attribute::Alignment) Alignment.reset(); else if (Val == Attribute::StackAlignment) StackAlignment.reset(); - else if (Val == Attribute::ByVal) - ByValType = nullptr; - else if (Val == Attribute::StructRet) - StructRetType = nullptr; - else if (Val == Attribute::ByRef) - ByRefType = nullptr; - else if (Val == Attribute::Preallocated) - PreallocatedType = nullptr; else if (Val == Attribute::Dereferenceable) DerefBytes = 0; else if (Val == Attribute::DereferenceableOrNull) DerefOrNullBytes = 0; else if (Val == Attribute::AllocSize) AllocSizeArgs = 0; + else if (Val == Attribute::VScaleRange) + VScaleRangeArgs = 0; return *this; } @@ -1670,6 +1648,10 @@ std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const { return unpackAllocSizeArgs(AllocSizeArgs); } +std::pair<unsigned, unsigned> AttrBuilder::getVScaleRangeArgs() const { + return unpackVScaleRangeArgs(VScaleRangeArgs); +} + AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) { if (!Align) return *this; @@ -1726,28 +1708,55 @@ AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) { return *this; } -AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) { - Attrs[Attribute::ByVal] = true; - ByValType = Ty; +AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue, + unsigned MaxValue) { + return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue)); +} + +AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) { + // (0, 0) is not present hence ignore this case + if (RawArgs == 0) + return *this; + + Attrs[Attribute::VScaleRange] = true; + // Reuse existing machinery to store this as a single 64-bit integer so we can + // save a few bytes over using a pair<unsigned, unsigned>. + VScaleRangeArgs = RawArgs; return *this; } -AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) { - Attrs[Attribute::StructRet] = true; - StructRetType = Ty; +Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const { + Optional<unsigned> TypeIndex = kindToTypeIndex(Kind); + assert(TypeIndex && "Not a type attribute"); + return TypeAttrs[*TypeIndex]; +} + +AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) { + Optional<unsigned> TypeIndex = kindToTypeIndex(Kind); + assert(TypeIndex && "Not a type attribute"); + Attrs[Kind] = true; + TypeAttrs[*TypeIndex] = Ty; return *this; } +AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) { + return addTypeAttr(Attribute::ByVal, Ty); +} + +AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) { + return addTypeAttr(Attribute::StructRet, Ty); +} + AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) { - Attrs[Attribute::ByRef] = true; - ByRefType = Ty; - return *this; + return addTypeAttr(Attribute::ByRef, Ty); } AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) { - Attrs[Attribute::Preallocated] = true; - PreallocatedType = Ty; - return *this; + return addTypeAttr(Attribute::Preallocated, Ty); +} + +AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) { + return addTypeAttr(Attribute::InAlloca, Ty); } AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { @@ -1767,17 +1776,12 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { if (!AllocSizeArgs) AllocSizeArgs = B.AllocSizeArgs; - if (!ByValType) - ByValType = B.ByValType; - - if (!StructRetType) - StructRetType = B.StructRetType; - - if (!ByRefType) - ByRefType = B.ByRefType; + if (!VScaleRangeArgs) + VScaleRangeArgs = B.VScaleRangeArgs; - if (!PreallocatedType) - PreallocatedType = B.PreallocatedType; + for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) + if (!TypeAttrs[Index]) + TypeAttrs[Index] = B.TypeAttrs[Index]; Attrs |= B.Attrs; @@ -1804,17 +1808,12 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { if (B.AllocSizeArgs) AllocSizeArgs = 0; - if (B.ByValType) - ByValType = nullptr; - - if (B.StructRetType) - StructRetType = nullptr; - - if (B.ByRefType) - ByRefType = nullptr; + if (B.VScaleRangeArgs) + VScaleRangeArgs = 0; - if (B.PreallocatedType) - PreallocatedType = nullptr; + for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) + if (B.TypeAttrs[Index]) + TypeAttrs[Index] = nullptr; Attrs &= ~B.Attrs; @@ -1869,15 +1868,13 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const { if (Attrs != B.Attrs) return false; - for (td_const_iterator I = TargetDepAttrs.begin(), - E = TargetDepAttrs.end(); I != E; ++I) - if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end()) + for (const auto &TDA : TargetDepAttrs) + if (B.TargetDepAttrs.find(TDA.first) == B.TargetDepAttrs.end()) return false; return Alignment == B.Alignment && StackAlignment == B.StackAlignment && - DerefBytes == B.DerefBytes && ByValType == B.ByValType && - StructRetType == B.StructRetType && ByRefType == B.ByRefType && - PreallocatedType == B.PreallocatedType; + DerefBytes == B.DerefBytes && TypeAttrs == B.TypeAttrs && + VScaleRangeArgs == B.VScaleRangeArgs; } //===----------------------------------------------------------------------===// @@ -1899,16 +1896,18 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { .addAttribute(Attribute::NoAlias) .addAttribute(Attribute::NoCapture) .addAttribute(Attribute::NonNull) + .addAttribute(Attribute::ReadNone) + .addAttribute(Attribute::ReadOnly) + .addAttribute(Attribute::SwiftError) .addAlignmentAttr(1) // the int here is ignored .addDereferenceableAttr(1) // the int here is ignored .addDereferenceableOrNullAttr(1) // the int here is ignored - .addAttribute(Attribute::ReadNone) - .addAttribute(Attribute::ReadOnly) - .addAttribute(Attribute::InAlloca) .addPreallocatedAttr(Ty) + .addInAllocaAttr(Ty) .addByValAttr(Ty) .addStructRetAttr(Ty) - .addByRefAttr(Ty); + .addByRefAttr(Ty) + .addTypeAttr(Attribute::ElementType, Ty); // Some attributes can apply to all "values" but there are no `void` values. if (Ty->isVoidTy()) @@ -1917,6 +1916,14 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { return Incompatible; } +AttrBuilder AttributeFuncs::getUBImplyingAttributes() { + AttrBuilder B; + B.addAttribute(Attribute::NoUndef); + B.addDereferenceableAttr(1); + B.addDereferenceableOrNullAttr(1); + return B; +} + template<typename AttrClass> static bool isEqual(const Function &Caller, const Function &Callee) { return Caller.getFnAttribute(AttrClass::getKind()) == @@ -1950,16 +1957,6 @@ static void setOR(Function &Caller, const Function &Callee) { /// If the inlined function had a higher stack protection level than the /// calling function, then bump up the caller's stack protection level. static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { -#ifndef NDEBUG - if (!Callee.hasFnAttribute(Attribute::AlwaysInline)) { - assert(!(!Callee.hasStackProtectorFnAttr() && - Caller.hasStackProtectorFnAttr()) && - "stack protected caller but callee requested no stack protector"); - assert(!(!Caller.hasStackProtectorFnAttr() && - Callee.hasStackProtectorFnAttr()) && - "stack protected callee but caller requested no stack protector"); - } -#endif // If upgrading the SSP attribute, clear out the old SSP Attributes first. // Having multiple SSP attributes doesn't actually hurt, but it adds useless // clutter to the IR. |