Skip to content

Commit 57a1e08

Browse files
committed
[mlir] Decouple enum generation from attributes, adding EnumInfo and EnumCase
This commit pulls apart the inherent attribute dependence of classes like EnumAttrInfo and EnumAttrCase, factoring them out into simpler EnumCase and EnumInfo variants. This allows specifying the cases of an enum without needing to make the cases, or the EnumInfo itself, a subclass of SignlessIntegerAttrBase. The existing classes are retained as subclasses of the new ones, both for backwards compatibility and to allow attribute-specific information. In addition, the new BitEnum class changes its default printer/parser behavior: cases when multiple keywords appear, like having both nuw and nsw in overflow flags, will no longer be quoted by the operator<<, and the FieldParser instance will now expect multiple keywords. All instances of BitEnumAttr retain the old behavior.
1 parent 64046e9 commit 57a1e08

File tree

14 files changed

+431
-158
lines changed

14 files changed

+431
-158
lines changed

mlir/docs/DefiningDialects/Operations.md

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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
15151509
generate 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
15181513
C++ enum class, `llvm::DenseMapInfo` for the enum class, conversion functions
15191514
from/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
15221517
For 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) {
16111606
Similarly 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

16241622
We 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

Comments
 (0)