Skip to content

Commit 8ea0711

Browse files
ZenithalHourlyRatesivan-shani
authored andcommitted
[MLIR][Doc] Add documentation for OpAsmAttr/TypeInterface (llvm#140244)
After the introduction of OpAsmAttr/TypeInterface in llvm#121187 llvm#124721, the documentation for them could be updated along side the doc for OpAsmDialectInterface. llvm#127993 changed the trailing digit behavior for alias name generation.
1 parent c6c9c60 commit 8ea0711

File tree

1 file changed

+52
-14
lines changed

1 file changed

+52
-14
lines changed

mlir/docs/DefiningDialects/Assembly.md

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,42 @@
44

55
## Generating Aliases
66

7-
To reduce verbosity in the resulting assembly, `AsmPrinter` can generate aliases for frequently used types and attributes.
7+
`AsmPrinter` can generate aliases for frequently used types and attributes when not printing them in generic form. For example, `!my_dialect.type<a=3,b=4,c=5,d=tuple,e=another_type>` and `#my_dialect.attr<a=3>` can be aliased to `!my_dialect_type` and `#my_dialect_attr`.
88

9-
For example, `!my_dialect.type<a=3,b=4,c=5,d=tuple,e=another_type>` and `#my_dialect.attr<a=3>` can be aliased to `!my_dialect_type` and `#my_dialect_attr`, simplifying further references.
9+
There are mainly two ways to hook into the `AsmPrinter`. One is the attribute/type interface and the other is the dialect interface.
1010

11-
To enable this, the owning dialect of these types/attributes can define an interface to hook into the `AsmPrinter`. This is effective only when the assembly is not printed in generic form.
11+
The attribute/type interface is the first hook to check. If no such hook is found, or the hook returns `OverridableAlias` (see definition below), then dialect interfaces are involved.
12+
13+
The dialect interface for one specific dialect could generate alias for all types/attributes, even when it does not "own" them. The `AsmPrinter` checks all dialect interfaces based on their order of registration. For example, the default alias `map` for `builtin` attribute `AffineMapAttr` could be overriden by the dialect interface for `my_dialect` as custom dialect is often registered after the `builtin` dialect.
1214

1315
```cpp
14-
// OpAsmDialectInterface is defined in
15-
// https://github.com/llvm/llvm-project/blob/91ab10e8d6c256d841da1a1a1b47c334e08d95b9/mlir/include/mlir/IR/OpImplementation.h#L1738
16+
/// Holds the result of `OpAsm{Dialect,Attr,Type}Interface::getAlias` hook call.
17+
enum class OpAsmAliasResult {
18+
/// The object (type or attribute) is not supported by the hook
19+
/// and an alias was not provided.
20+
NoAlias,
21+
/// An alias was provided, but it might be overriden by other hook.
22+
OverridableAlias,
23+
/// An alias was provided and it should be used
24+
/// (no other hooks will be checked).
25+
FinalAlias
26+
};
27+
```
28+
29+
If multiple types/attributes have the same alias from `getAlias` hooks, a number is appended to the alias to avoid conflicts.
30+
31+
### `OpAsmDialectInterface`
32+
33+
```cpp
34+
#include "mlir/IR/OpImplementation.h"
35+
1636
struct MyDialectOpAsmDialectInterface : public OpAsmDialectInterface {
1737
public:
1838
using OpAsmDialectInterface::OpAsmDialectInterface;
1939
2040
AliasResult getAlias(Type type, raw_ostream& os) const override {
2141
if (mlir::isa<MyType>(type)) {
2242
os << "my_dialect_type";
23-
// Could return OverridableAlias when
24-
// allowing other dialect to override the alias.
25-
//
26-
// Other dialects are allowed to provide alias for
27-
// type/attribute not owned by them
28-
// but the final result would depend on the registration order
29-
// of these dialects in the MLIRContext
3043
return AliasResult::FinalAlias;
3144
}
3245
return AliasResult::NoAlias;
@@ -47,8 +60,31 @@ void MyDialect::initialize() {
4760
}
4861
```
4962

50-
* If `getAlias` provides an alias with a trailing digit, `AsmPrinter` appends an underscore to avoid conflicts with autogenerated IDs.
51-
* If multiple types/attributes have the same alias from `getAlias`, a number is appended to the alias to avoid conflicts.
63+
### `OpAsmAttrInterface` and `OpAsmTypeInterface`
64+
65+
The easiest way to use these interfaces is toggling `genMnemonicAlias` in the tablegen file of the attribute/alias. It directly uses the mnemonic as alias. See [Defining Dialect Attributes and Types](/docs/DefiningDialects/AttributesAndTypes) for details.
66+
67+
If a more custom behavior is wanted, the following modification to the attribute/type should be made
68+
69+
1. Add `OpAsmAttrInterface` or `OpAsmTypeInterface` into its trait list.
70+
2. Implement the `getAlias` method, either in tablegen or its cpp file.
71+
72+
```tablegen
73+
include "mlir/IR/OpAsmInterface.td"
74+
75+
// Add OpAsmAttrInterface trait
76+
def MyAttr : MyDialect_Attr<"MyAttr",
77+
[ OpAsmAttrInterface ] > {
78+
79+
// This method could be put in the cpp file.
80+
let extraClassDeclaration = [{
81+
::mlir::OpAsmAliasResult getAlias(::llvm::raw_ostream &os) const {
82+
os << "alias_name";
83+
return ::mlir::OpAsmAliasResult::OverridableAlias;
84+
}
85+
}];
86+
}
87+
```
5288

5389
## Suggesting SSA/Block Names
5490

@@ -98,6 +134,8 @@ Similarly, an `Operation` can suggest the name for its block arguments using `ge
98134
For custom block names, `OpAsmOpInterface` has a method `getAsmBlockNames` so that
99135
the operation can suggest a custom prefix instead of a generic `^bb0`.
100136
137+
Alternatively, `OpAsmTypeInterface` provides a `getAsmName` method for scenarios where the name could be inferred from its type.
138+
101139
## Defining Default Dialect
102140
103141
An `Operation` can indicate that the nested region in it has a default dialect prefix, and the operations in the region could elide the dialect prefix.

0 commit comments

Comments
 (0)