[Attributes] Make type attribute handling more generic (NFCI)

Followup to D105658 to make AttrBuilder automatically work with
new type attributes. TableGen is tweaked to emit First/LastTypeAttr
markers, based on which we can handle type attributes
programmatically.

Differential Revision: https://reviews.llvm.org/D105763
This commit is contained in:
Nikita Popov 2021-07-10 18:36:00 +02:00
parent 6ebbf755b6
commit 5d1464cbfe
4 changed files with 53 additions and 61 deletions

View File

@ -71,14 +71,19 @@ public:
enum AttrKind { enum AttrKind {
// IR-Level Attributes // IR-Level Attributes
None, ///< No attributes have been set None, ///< No attributes have been set
#define GET_ATTR_NAMES #define GET_ATTR_ENUM
#define ATTRIBUTE_ENUM(ENUM_NAME, OTHER) ENUM_NAME,
#include "llvm/IR/Attributes.inc" #include "llvm/IR/Attributes.inc"
EndAttrKinds, ///< Sentinal value useful for loops EndAttrKinds, ///< Sentinal value useful for loops
EmptyKey, ///< Use as Empty key for DenseMap of AttrKind EmptyKey, ///< Use as Empty key for DenseMap of AttrKind
TombstoneKey, ///< Use as Tombstone 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: private:
AttributeImpl *pImpl = nullptr; AttributeImpl *pImpl = nullptr;
@ -802,16 +807,6 @@ template <> struct DenseMapInfo<AttributeList> {
/// value, however, is not. So this can be used as a quick way to test for /// value, however, is not. So this can be used as a quick way to test for
/// equality, presence of attributes, etc. /// equality, presence of attributes, etc.
class AttrBuilder { class AttrBuilder {
// Indices into the TypeAttrs array.
enum : unsigned {
ByValTypeIndex = 0,
StructRetTypeIndex = 1,
ByRefTypeIndex = 2,
PreallocatedTypeIndex = 3,
InAllocaTypeIndex = 4,
NumTypeIndices = 5,
};
std::bitset<Attribute::EndAttrKinds> Attrs; std::bitset<Attribute::EndAttrKinds> Attrs;
std::map<SmallString<32>, SmallString<32>, std::less<>> TargetDepAttrs; std::map<SmallString<32>, SmallString<32>, std::less<>> TargetDepAttrs;
MaybeAlign Alignment; MaybeAlign Alignment;
@ -820,7 +815,7 @@ class AttrBuilder {
uint64_t DerefOrNullBytes = 0; uint64_t DerefOrNullBytes = 0;
uint64_t AllocSizeArgs = 0; uint64_t AllocSizeArgs = 0;
uint64_t VScaleRangeArgs = 0; uint64_t VScaleRangeArgs = 0;
std::array<Type *, NumTypeIndices> TypeAttrs = {}; std::array<Type *, Attribute::NumTypeAttrKinds> TypeAttrs = {};
Optional<unsigned> kindToTypeIndex(Attribute::AttrKind Kind) const; Optional<unsigned> kindToTypeIndex(Attribute::AttrKind Kind) const;
@ -905,20 +900,25 @@ public:
/// dereferenceable_or_null attribute exists (zero is returned otherwise). /// dereferenceable_or_null attribute exists (zero is returned otherwise).
uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
/// Retrieve type for the given type attribute.
Type *getTypeAttr(Attribute::AttrKind Kind) const;
/// Retrieve the byval type. /// Retrieve the byval type.
Type *getByValType() const { return TypeAttrs[ByValTypeIndex]; } Type *getByValType() const { return getTypeAttr(Attribute::ByVal); }
/// Retrieve the sret type. /// Retrieve the sret type.
Type *getStructRetType() const { return TypeAttrs[StructRetTypeIndex]; } Type *getStructRetType() const { return getTypeAttr(Attribute::StructRet); }
/// Retrieve the byref type. /// Retrieve the byref type.
Type *getByRefType() const { return TypeAttrs[ByRefTypeIndex]; } Type *getByRefType() const { return getTypeAttr(Attribute::ByRef); }
/// Retrieve the preallocated type. /// Retrieve the preallocated type.
Type *getPreallocatedType() const { return TypeAttrs[PreallocatedTypeIndex]; } Type *getPreallocatedType() const {
return getTypeAttr(Attribute::Preallocated);
}
/// Retrieve the inalloca type. /// 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 /// Retrieve the allocsize args, if the allocsize attribute exists. If it
/// doesn't exist, pair(0, 0) is returned. /// doesn't exist, pair(0, 0) is returned.

View File

@ -1642,17 +1642,10 @@ Error BitcodeReader::parseAttributeGroupBlock() {
Attribute::AttrKind Kind; Attribute::AttrKind Kind;
if (Error Err = parseAttrKind(Record[++i], &Kind)) if (Error Err = parseAttrKind(Record[++i], &Kind))
return Err; return Err;
if (Kind == Attribute::ByVal) { if (!Attribute::isTypeAttrKind(Kind))
B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr); return error("Not a type attribute");
} else if (Kind == Attribute::StructRet) {
B.addStructRetAttr(HasType ? getTypeByID(Record[++i]) : nullptr); B.addTypeAttr(Kind, 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);
}
} }
} }

View File

@ -138,6 +138,7 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
Type *Ty) { Type *Ty) {
assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
LLVMContextImpl *pImpl = Context.pImpl; LLVMContextImpl *pImpl = Context.pImpl;
FoldingSetNodeID ID; FoldingSetNodeID ID;
ID.AddInteger(Kind); ID.AddInteger(Kind);
@ -800,23 +801,13 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
if (!B.contains(Kind)) if (!B.contains(Kind))
continue; continue;
if (Attribute::isTypeAttrKind(Kind)) {
Attrs.push_back(Attribute::get(C, Kind, B.getTypeAttr(Kind)));
continue;
}
Attribute Attr; Attribute Attr;
switch (Kind) { 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: case Attribute::Alignment:
assert(B.getAlignment() && "Alignment must be set"); assert(B.getAlignment() && "Alignment must be set");
Attr = Attribute::getWithAlignment(C, *B.getAlignment()); Attr = Attribute::getWithAlignment(C, *B.getAlignment());
@ -1602,20 +1593,9 @@ void AttrBuilder::clear() {
Optional<unsigned> Optional<unsigned>
AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const { AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const {
switch (Kind) { if (Attribute::isTypeAttrKind(Kind))
case Attribute::ByVal: return Kind - Attribute::FirstTypeAttr;
return ByValTypeIndex; return None;
case Attribute::ByRef:
return ByRefTypeIndex;
case Attribute::InAlloca:
return InAllocaTypeIndex;
case Attribute::Preallocated:
return PreallocatedTypeIndex;
case Attribute::StructRet:
return StructRetTypeIndex;
default:
return None;
}
} }
AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
@ -1765,6 +1745,12 @@ AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
return *this; return *this;
} }
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) { AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
Optional<unsigned> TypeIndex = kindToTypeIndex(Kind); Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
assert(TypeIndex && "Not a type attribute"); assert(TypeIndex && "Not a type attribute");
@ -1813,7 +1799,7 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
if (!VScaleRangeArgs) if (!VScaleRangeArgs)
VScaleRangeArgs = B.VScaleRangeArgs; VScaleRangeArgs = B.VScaleRangeArgs;
for (unsigned Index = 0; Index < NumTypeIndices; ++Index) for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
if (!TypeAttrs[Index]) if (!TypeAttrs[Index])
TypeAttrs[Index] = B.TypeAttrs[Index]; TypeAttrs[Index] = B.TypeAttrs[Index];
@ -1845,7 +1831,7 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
if (B.VScaleRangeArgs) if (B.VScaleRangeArgs)
VScaleRangeArgs = 0; VScaleRangeArgs = 0;
for (unsigned Index = 0; Index < NumTypeIndices; ++Index) for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
if (B.TypeAttrs[Index]) if (B.TypeAttrs[Index])
TypeAttrs[Index] = nullptr; TypeAttrs[Index] = nullptr;

View File

@ -58,7 +58,20 @@ void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL"); Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
OS << "#undef ATTRIBUTE_ALL\n"; 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) { void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {