aboutsummaryrefslogtreecommitdiff
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.cpp623
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.