/// Enum attribute.
class EnumAttr<string S> : Attr<S>;
+/// Int attribute.
+class IntAttr<string S> : Attr<S>;
+
/// StringBool attribute.
class StrBoolAttr<string S> : Attr<S>;
+/// Type attribute.
+class TypeAttr<string S> : Attr<S>;
+
/// Target-independent enum attributes.
/// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias.
/// 0 means unaligned (different from align(1)).
-def Alignment : EnumAttr<"align">;
+def Alignment : IntAttr<"align">;
/// The result of the function is guaranteed to point to a number of bytes that
/// we can determine if we know the value of the function's arguments.
-def AllocSize : EnumAttr<"allocsize">;
+def AllocSize : IntAttr<"allocsize">;
/// inline=always.
def AlwaysInline : EnumAttr<"alwaysinline">;
def Builtin : EnumAttr<"builtin">;
/// Pass structure by value.
-def ByVal : EnumAttr<"byval">;
+def ByVal : TypeAttr<"byval">;
/// Marks function as being in a cold path.
def Cold : EnumAttr<"cold">;
def Convergent : EnumAttr<"convergent">;
/// Pointer is known to be dereferenceable.
-def Dereferenceable : EnumAttr<"dereferenceable">;
+def Dereferenceable : IntAttr<"dereferenceable">;
/// Pointer is either null or dereferenceable.
-def DereferenceableOrNull : EnumAttr<"dereferenceable_or_null">;
+def DereferenceableOrNull : IntAttr<"dereferenceable_or_null">;
/// Function may only access memory that is inaccessible from IR.
def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly">;
/// Alignment of stack for function (3 bits) stored as log2 of alignment with
/// +1 bias 0 means unaligned (different from alignstack=(1)).
-def StackAlignment : EnumAttr<"alignstack">;
+def StackAlignment : IntAttr<"alignstack">;
/// Function can be speculated.
def Speculatable : EnumAttr<"speculatable">;
AttributeSetNode(ArrayRef<Attribute> Attrs);
+ static AttributeSetNode *getSorted(LLVMContext &C,
+ ArrayRef<Attribute> SortedAttrs);
+
public:
// AttributesSetNode is uniqued, these should not be available.
AttributeSetNode(const AttributeSetNode &) = delete;
AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
ArrayRef<Attribute> Attrs) {
- if (Attrs.empty())
+ SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
+ llvm::sort(SortedAttrs);
+ return getSorted(C, SortedAttrs);
+}
+
+AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
+ ArrayRef<Attribute> SortedAttrs) {
+ if (SortedAttrs.empty())
return nullptr;
- // Otherwise, build a key to look up the existing attributes.
+ // Build a key to look up the existing attributes.
LLVMContextImpl *pImpl = C.pImpl;
FoldingSetNodeID ID;
- SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
- llvm::sort(SortedAttrs);
-
+ assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
for (const auto &Attr : SortedAttrs)
Attr.Profile(ID);
for (const auto &TDA : B.td_attrs())
Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
- return get(C, Attrs);
+ return getSorted(C, Attrs);
}
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n";
OS << "#endif\n\n";
- auto Emiter = [&](StringRef KindName, StringRef MacroName) {
- std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(KindName);
-
+ auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) {
OS << "#ifndef " << MacroName << "\n";
- OS << "#define " << MacroName << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, "
- "SECOND)\n";
+ OS << "#define " << MacroName
+ << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n";
OS << "#endif\n\n";
-
- for (auto A : Attrs) {
- OS << "" << MacroName << "(" << A->getName() << ","
- << A->getValueAsString("AttrString") << ")\n";
+ for (StringRef KindName : KindNames) {
+ for (auto A : Records.getAllDerivedDefinitions(KindName)) {
+ OS << MacroName << "(" << A->getName() << ","
+ << A->getValueAsString("AttrString") << ")\n";
+ }
}
OS << "#undef " << MacroName << "\n\n";
};
- Emiter("EnumAttr", "ATTRIBUTE_ENUM");
- Emiter("StrBoolAttr", "ATTRIBUTE_STRBOOL");
+ // Emit attribute enums in the same order llvm::Attribute::operator< expects.
+ Emit({"EnumAttr", "TypeAttr", "IntAttr"}, "ATTRIBUTE_ENUM");
+ Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
OS << "#undef ATTRIBUTE_ALL\n";
OS << "#endif\n";