@@ -1498,22 +1498,17 @@ optionality, default values, etc.:
14981498* ` AllAttrOf ` : adapts an attribute with
14991499 [ multiple constraints] ( #combining-constraints ) .
15001500
1501- ### Enum attributes
1501+ ## Enum definition
15021502
1503- Some attributes can only take values from a predefined enum, e.g., the
1504- comparison kind of a comparison op. To define such attributes, ODS provides
1505- several mechanisms: ` IntEnumAttr ` , and ` BitEnumAttr ` .
1503+ MLIR is capabable of generating C++ enums, both those that represent a set
1504+ of values drawn from a list or that can hold a combination of flags
1505+ using the ` IntEnum ` and ` BitEnum ` classes, respectively .
15061506
1507- * ` IntEnumAttr ` : each enum case is an integer, the attribute is stored as a
1508- [ ` IntegerAttr ` ] [ IntegerAttr ] in the op.
1509- * ` BitEnumAttr ` : each enum case is a either the empty case, a single bit,
1510- or a group of single bits, and the attribute is stored as a
1511- [ ` IntegerAttr ` ] [ IntegerAttr ] in the op.
1512-
1513- All these ` *EnumAttr ` attributes require fully specifying all of the allowed
1514- cases via their corresponding ` *EnumAttrCase ` . With this, ODS is able to
1507+ All these ` IntEnum ` and ` BitEnum ` classes require fully specifying all of the allowed
1508+ cases via a ` EnumCase ` or ` BitEnumCase ` subclass, respectively. With this, ODS is able to
15151509generate additional verification to only accept allowed cases. To facilitate the
1516- interaction between ` *EnumAttr ` s and their C++ consumers, the
1510+ interaction between tablegen enums and the attributes or properties that wrap them and
1511+ to make them easier to use in C++, the
15171512[ ` EnumsGen ` ] [ EnumsGen ] TableGen backend can generate a few common utilities: a
15181513C++ enum class, ` llvm::DenseMapInfo ` for the enum class, conversion functions
15191514from/to strings. This is controlled via the ` -gen-enum-decls ` and
@@ -1522,10 +1517,10 @@ from/to strings. This is controlled via the `-gen-enum-decls` and
15221517For example, given the following ` EnumAttr ` :
15231518
15241519``` tablegen
1525- def Case15: I32EnumAttrCase <"Case15", 15>;
1526- def Case20: I32EnumAttrCase <"Case20", 20>;
1520+ def Case15: I32EnumCase <"Case15", 15>;
1521+ def Case20: I32EnumCase <"Case20", 20>;
15271522
1528- def MyIntEnum: I32EnumAttr <"MyIntEnum", "An example int enum",
1523+ def MyIntEnum: I32Enum <"MyIntEnum", "An example int enum",
15291524 [Case15, Case20]> {
15301525 let cppNamespace = "Outer::Inner";
15311526 let stringToSymbolFnName = "ConvertToEnum";
@@ -1611,14 +1606,17 @@ std::optional<MyIntEnum> symbolizeMyIntEnum(uint32_t value) {
16111606Similarly for the following ` BitEnumAttr ` definition:
16121607
16131608``` tablegen
1614- def None: I32BitEnumAttrCaseNone<"None">;
1615- def Bit0: I32BitEnumAttrCaseBit<"Bit0", 0, "tagged">;
1616- def Bit1: I32BitEnumAttrCaseBit<"Bit1", 1>;
1617- def Bit2: I32BitEnumAttrCaseBit<"Bit2", 2>;
1618- def Bit3: I32BitEnumAttrCaseBit<"Bit3", 3>;
1619-
1620- def MyBitEnum: BitEnumAttr<"MyBitEnum", "An example bit enum",
1621- [None, Bit0, Bit1, Bit2, Bit3]>;
1609+ def None: I32BitEnumCaseNone<"None">;
1610+ def Bit0: I32BitEnumCaseBit<"Bit0", 0, "tagged">;
1611+ def Bit1: I32BitEnumCaseBit<"Bit1", 1>;
1612+ def Bit2: I32BitEnumCaseBit<"Bit2", 2>;
1613+ def Bit3: I32BitEnumCaseBit<"Bit3", 3>;
1614+
1615+ def MyBitEnum: I32BitEnum<"MyBitEnum", "An example bit enum",
1616+ [None, Bit0, Bit1, Bit2, Bit3]> {
1617+ // Note: this is the default value, and is listed for illustrative purposes.
1618+ let separator = "|";
1619+ }
16221620```
16231621
16241622We can have:
@@ -1738,6 +1736,26 @@ std::optional<MyBitEnum> symbolizeMyBitEnum(uint32_t value) {
17381736}
17391737```
17401738
1739+ ### Wrapping enums in attributes
1740+
1741+ There are several mechanisms for creating an ` Attribute ` whose values are
1742+ taken from a ` *Enum ` .
1743+
1744+ The most common of these is to use the ` EnumAttr ` class, which takes
1745+ an ` EnumInfo ` (either a ` IntEnum ` or ` BitEnum ` ) as a parameter and constructs
1746+ an attribute that holds one argument - value of the enum. This attribute
1747+ is defined within a dialect and can have its assembly format customized to,
1748+ for example, print angle brackets around the enum value or assign a mnemonic.
1749+
1750+ An older form involves using the ` *IntEnumAttr ` and ` *BitEnumATtr ` classes
1751+ and their corresponding ` *EnumAttrCase ` classes (which can be used
1752+ anywhere a ` *EnumCase ` is needed). These classes store their values
1753+ as a ` SignlessIntegerAttr ` of their bitwidth, imposing the constraint on it
1754+ that it has a value within the valid range of the enum. If their
1755+ ` genSpecializedAttr ` parameter is set, they will also generate a
1756+ wrapper attribute instead of using a bare signless integer attribute
1757+ for storage.
1758+
17411759## Debugging Tips
17421760
17431761### Run ` mlir-tblgen ` to see the generated content
0 commit comments