Better support for attribute wrapper classes when getting def name

Unless we explicitly name a template instantiation in .td file, its def
name will be "anonymous_<number>". We typically give base-level Attr
template instantiation a name by writing `def AnAttr : Attr<...>`. But
when `AnAttr` is further wrapped in classes like OptionalAttr, the name
is lost unless explicitly def'ed again. These implicit-named template
instantiation is fairly common when writing op definitions. Those wrapper
classes are just essentially attaching more information to the attribute.
Without a proper way to trace back to the original attribute def name
can cause problems for consumers wanting to handle attributes according
to their types.

Previously we handled OptionalAttr and DefaultValuedAttr specifically,
but Confined was not supported. And they can compose together to have
Confined<OptionalAttr<...>, [...]>. So this CL moves the baseAttr field
to main Attr class (like isOptional) and set it only on the innermost
wrapper class.

PiperOrigin-RevId: 258341646
This commit is contained in:
Lei Zhang 2019-07-16 04:33:54 -07:00 committed by Mehdi Amini
parent e78ea03b24
commit 765b77cc70
3 changed files with 38 additions and 16 deletions

View File

@ -518,6 +518,17 @@ class Attr<Pred condition, string descr = ""> :
// convertFromStorage method to handle the case where the attribute is
// not present.
bit isOptional = 0;
// What is the base-level Attr instantiation that this Attr is built upon.
// Unset means this is a base-level Attr.
//
// This field is used by attribute wrapper classes (DefaultValuedAttr,
// OptionalAttr, etc.) to retrive the base-level attribute definition.
// This can be used for getting its name; otherwise, we will see
// "anonymous_<number>" as the attribute def name because of template
// instantiation.
// TOOD(b/132458159): deduplicate the fields in attribute wrapper classes.
Attr baseAttr = ?;
}
//===----------------------------------------------------------------------===//
@ -535,9 +546,7 @@ class DefaultValuedAttr<Attr attr, string val> :
let constBuilderCall = attr.constBuilderCall;
let defaultValue = val;
// Remember `attr`'s def name.
// TOOD(b/132458159): consider embedding Attr as a field.
string baseAttr = !cast<string>(attr);
let baseAttr = attr;
}
// Decorates an attribute as optional. The return type of the generated
@ -551,9 +560,7 @@ class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.description> {
attr.convertFromStorage # ") : (llvm::None)";
let isOptional = 1;
// Remember `attr`'s def name.
// TOOD(b/132458159): consider embedding Attr as a field.
string baseAttr = !cast<string>(attr);
let baseAttr = attr;
}
//===----------------------------------------------------------------------===//
@ -891,6 +898,8 @@ class Confined<Attr attr, list<AttrConstraint> constraints> : Attr<
let constBuilderCall = attr.constBuilderCall;
let defaultValue = attr.defaultValue;
let isOptional = attr.isOptional;
let baseAttr = attr;
}
// An AttrConstraint that holds if all attr constraints specified in

View File

@ -52,14 +52,6 @@ public:
explicit Attribute(const llvm::Record *record);
explicit Attribute(const llvm::DefInit *init);
// Returns true if this attribute is a derived attribute (i.e., a subclass
// of `DerivedAttr`).
bool isDerivedAttr() const;
// Returns true if this attribute is a type attribute (i.e., a subclass
// of `TypeAttrBase`).
bool isTypeAttr() const;
// Returns true if this attribute has storage type set.
bool hasStorageType() const;
@ -84,6 +76,10 @@ public:
// the constant value.
StringRef getConstBuilderTemplate() const;
// Returns the base-level attribute that this attribute constraint is
// built upon.
Attribute getBaseAttr() const;
// Returns whether this attribute has a default value's initializer.
bool hasDefaultValueInitializer() const;
// Returns the default value's initializer for this attribute.
@ -92,6 +88,14 @@ public:
// Returns whether this attribute is optional.
bool isOptional() const;
// Returns true if this attribute is a derived attribute (i.e., a subclass
// of `DerivedAttr`).
bool isDerivedAttr() const;
// Returns true if this attribute is a type attribute (i.e., a subclass
// of `TypeAttrBase`).
bool isTypeAttr() const;
// Returns this attribute's TableGen def name. If this is an `OptionalAttr`
// or `DefaultValuedAttr` without explicit name, returns the base attribute's
// name.

View File

@ -96,6 +96,14 @@ StringRef tblgen::Attribute::getConstBuilderTemplate() const {
return getValueAsString(init);
}
tblgen::Attribute tblgen::Attribute::getBaseAttr() const {
if (const auto *defInit =
llvm::dyn_cast<llvm::DefInit>(def->getValueInit("baseAttr"))) {
return Attribute(defInit).getBaseAttr();
}
return *this;
}
bool tblgen::Attribute::hasDefaultValueInitializer() const {
const auto *init = def->getValueInit("defaultValue");
return !getValueAsString(init).empty();
@ -111,8 +119,9 @@ bool tblgen::Attribute::isOptional() const {
}
StringRef tblgen::Attribute::getAttrDefName() const {
if (def->isAnonymous() && (isOptional() || hasDefaultValueInitializer()))
return getValueAsString(def->getValueInit("baseAttr"));
if (def->isAnonymous()) {
return getBaseAttr().def->getName();
}
return def->getName();
}