diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -71,14 +71,19 @@ enum AttrKind { // IR-Level Attributes None, ///< No attributes have been set - #define GET_ATTR_NAMES - #define ATTRIBUTE_ENUM(ENUM_NAME, OTHER) ENUM_NAME, + #define GET_ATTR_ENUM #include "llvm/IR/Attributes.inc" EndAttrKinds, ///< Sentinal value useful for loops EmptyKey, ///< Use as Empty key for DenseMap of AttrKind TombstoneKey, ///< Use as Tombstone key for DenseMap of AttrKind }; + static const unsigned NumTypeAttrKinds = LastTypeAttr - FirstTypeAttr + 1; + + static bool isTypeAttrKind(AttrKind Kind) { + return Kind >= FirstTypeAttr && Kind <= LastTypeAttr; + } + private: AttributeImpl *pImpl = nullptr; @@ -802,16 +807,6 @@ /// value, however, is not. So this can be used as a quick way to test for /// equality, presence of attributes, etc. class AttrBuilder { - // Indices into the TypeAttrs array. - enum : unsigned { - ByValTypeIndex = 0, - StructRetTypeIndex = 1, - ByRefTypeIndex = 2, - PreallocatedTypeIndex = 3, - InAllocaTypeIndex = 4, - NumTypeIndices = 5, - }; - std::bitset Attrs; std::map, SmallString<32>, std::less<>> TargetDepAttrs; MaybeAlign Alignment; @@ -820,7 +815,7 @@ uint64_t DerefOrNullBytes = 0; uint64_t AllocSizeArgs = 0; uint64_t VScaleRangeArgs = 0; - std::array TypeAttrs = {}; + std::array TypeAttrs = {}; Optional kindToTypeIndex(Attribute::AttrKind Kind) const; @@ -905,20 +900,25 @@ /// dereferenceable_or_null attribute exists (zero is returned otherwise). uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// Retrieve type for the given type attribute. + Type *getTypeAttr(Attribute::AttrKind Kind) const; + /// Retrieve the byval type. - Type *getByValType() const { return TypeAttrs[ByValTypeIndex]; } + Type *getByValType() const { return getTypeAttr(Attribute::ByVal); } /// Retrieve the sret type. - Type *getStructRetType() const { return TypeAttrs[StructRetTypeIndex]; } + Type *getStructRetType() const { return getTypeAttr(Attribute::StructRet); } /// Retrieve the byref type. - Type *getByRefType() const { return TypeAttrs[ByRefTypeIndex]; } + Type *getByRefType() const { return getTypeAttr(Attribute::ByRef); } /// Retrieve the preallocated type. - Type *getPreallocatedType() const { return TypeAttrs[PreallocatedTypeIndex]; } + Type *getPreallocatedType() const { + return getTypeAttr(Attribute::Preallocated); + } /// Retrieve the inalloca type. - Type *getInAllocaType() const { return TypeAttrs[InAllocaTypeIndex]; } + Type *getInAllocaType() const { return getTypeAttr(Attribute::InAlloca); } /// Retrieve the allocsize args, if the allocsize attribute exists. If it /// doesn't exist, pair(0, 0) is returned. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1642,17 +1642,10 @@ Attribute::AttrKind Kind; if (Error Err = parseAttrKind(Record[++i], &Kind)) return Err; - if (Kind == Attribute::ByVal) { - B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr); - } else if (Kind == Attribute::StructRet) { - B.addStructRetAttr(HasType ? getTypeByID(Record[++i]) : nullptr); - } else if (Kind == Attribute::ByRef) { - B.addByRefAttr(getTypeByID(Record[++i])); - } else if (Kind == Attribute::Preallocated) { - B.addPreallocatedAttr(getTypeByID(Record[++i])); - } else if (Kind == Attribute::InAlloca) { - B.addInAllocaAttr(HasType ? getTypeByID(Record[++i]) : nullptr); - } + if (!Attribute::isTypeAttrKind(Kind)) + return error("Not a type attribute"); + + B.addTypeAttr(Kind, HasType ? getTypeByID(Record[++i]) : nullptr); } } diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -138,6 +138,7 @@ 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); @@ -800,23 +801,13 @@ 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::InAlloca: - Attr = Attribute::getWithInAllocaType(C, B.getInAllocaType()); - break; case Attribute::Alignment: assert(B.getAlignment() && "Alignment must be set"); Attr = Attribute::getWithAlignment(C, *B.getAlignment()); @@ -1602,20 +1593,9 @@ Optional AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const { - switch (Kind) { - case Attribute::ByVal: - return ByValTypeIndex; - case Attribute::ByRef: - return ByRefTypeIndex; - case Attribute::InAlloca: - return InAllocaTypeIndex; - case Attribute::Preallocated: - return PreallocatedTypeIndex; - case Attribute::StructRet: - return StructRetTypeIndex; - default: - return None; - } + if (Attribute::isTypeAttrKind(Kind)) + return Kind - Attribute::FirstTypeAttr; + return None; } AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { @@ -1765,6 +1745,12 @@ return *this; } +Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const { + Optional TypeIndex = kindToTypeIndex(Kind); + assert(TypeIndex && "Not a type attribute"); + return TypeAttrs[*TypeIndex]; +} + AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) { Optional TypeIndex = kindToTypeIndex(Kind); assert(TypeIndex && "Not a type attribute"); @@ -1813,7 +1799,7 @@ if (!VScaleRangeArgs) VScaleRangeArgs = B.VScaleRangeArgs; - for (unsigned Index = 0; Index < NumTypeIndices; ++Index) + for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) if (!TypeAttrs[Index]) TypeAttrs[Index] = B.TypeAttrs[Index]; @@ -1845,7 +1831,7 @@ if (B.VScaleRangeArgs) VScaleRangeArgs = 0; - for (unsigned Index = 0; Index < NumTypeIndices; ++Index) + for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) if (B.TypeAttrs[Index]) TypeAttrs[Index] = nullptr; diff --git a/llvm/utils/TableGen/Attributes.cpp b/llvm/utils/TableGen/Attributes.cpp --- a/llvm/utils/TableGen/Attributes.cpp +++ b/llvm/utils/TableGen/Attributes.cpp @@ -58,7 +58,20 @@ Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL"); OS << "#undef ATTRIBUTE_ALL\n"; - OS << "#endif\n"; + OS << "#endif\n\n"; + + OS << "#ifdef GET_ATTR_ENUM\n"; + OS << "#undef GET_ATTR_ENUM\n"; + unsigned Value = 1; // Leave zero for AttrKind::None. + for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) { + OS << "First" << KindName << " = " << Value << ",\n"; + for (auto A : Records.getAllDerivedDefinitions(KindName)) { + OS << A->getName() << " = " << Value << ",\n"; + Value++; + } + OS << "Last" << KindName << " = " << (Value - 1) << ",\n"; + } + OS << "#endif\n\n"; } void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {