Skip to content

Commit 0748639

Browse files
committed
[mlir][ods] Optional Attribute or Type Parameters
Implements optional attribute or type parameters, including support for such parameters in the assembly format `struct` directive. Also implements optional groups. Depends on D117971 Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D118208
1 parent 4a876b1 commit 0748639

File tree

13 files changed

+1128
-503
lines changed

13 files changed

+1128
-503
lines changed

mlir/docs/Tutorials/DefiningAttributesAndTypes.md

Lines changed: 78 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Defining Dialect Attributes and Types
22

33
This document is a quickstart to defining dialect specific extensions to the
4-
[attribute](../LangRef.md/#attributes) and [type](../LangRef.md/#type-system) systems in
5-
MLIR. The main part of this tutorial focuses on defining types, but the
6-
instructions are nearly identical for defining attributes.
4+
[attribute](../LangRef.md/#attributes) and [type](../LangRef.md/#type-system)
5+
systems in MLIR. The main part of this tutorial focuses on defining types, but
6+
the instructions are nearly identical for defining attributes.
77

88
See [MLIR specification](../LangRef.md) for more information about MLIR, the
99
structure of the IR, operations, etc.
@@ -24,18 +24,19 @@ defining a new `Type` it isn't always necessary to define a new storage class.
2424
So before defining the derived `Type`, it's important to know which of the two
2525
classes of `Type` we are defining:
2626

27-
Some types are _singleton_ in nature, meaning they have no parameters and only
28-
ever have one instance, like the [`index` type](../Dialects/Builtin.md/#indextype).
27+
Some types are *singleton* in nature, meaning they have no parameters and only
28+
ever have one instance, like the
29+
[`index` type](../Dialects/Builtin.md/#indextype).
2930

30-
Other types are _parametric_, and contain additional information that
31+
Other types are *parametric*, and contain additional information that
3132
differentiates different instances of the same `Type`. For example the
32-
[`integer` type](../Dialects/Builtin.md/#integertype) contains a bitwidth, with `i8` and
33-
`i16` representing different instances of
34-
[`integer` type](../Dialects/Builtin.md/#integertype). _Parametric_ may also contain a
35-
mutable component, which can be used, for example, to construct self-referring
36-
recursive types. The mutable component _cannot_ be used to differentiate
37-
instances of a type class, so usually such types contain other parametric
38-
components that serve to identify them.
33+
[`integer` type](../Dialects/Builtin.md/#integertype) contains a bitwidth, with
34+
`i8` and `i16` representing different instances of
35+
[`integer` type](../Dialects/Builtin.md/#integertype). *Parametric* may also
36+
contain a mutable component, which can be used, for example, to construct
37+
self-referring recursive types. The mutable component *cannot* be used to
38+
differentiate instances of a type class, so usually such types contain other
39+
parametric components that serve to identify them.
3940

4041
#### Singleton types
4142

@@ -389,12 +390,12 @@ Attributes and types defined in ODS with a mnemonic can define an
389390
`assemblyFormat` to declaratively describe custom parsers and printers. The
390391
assembly format consists of literals, variables, and directives.
391392
392-
* A literal is a keyword or valid punctuation enclosed in backticks, e.g.
393-
`` `keyword` `` or `` `<` ``.
394-
* A variable is a parameter name preceeded by a dollar sign, e.g. `$param0`,
395-
which captures one attribute or type parameter.
396-
* A directive is a keyword followed by an optional argument list that defines
397-
special parser and printer behaviour.
393+
* A literal is a keyword or valid punctuation enclosed in backticks, e.g. ``
394+
`keyword` `` or `` `<` ``.
395+
* A variable is a parameter name preceeded by a dollar sign, e.g. `$param0`,
396+
which captures one attribute or type parameter.
397+
* A directive is a keyword followed by an optional argument list that defines
398+
special parser and printer behaviour.
398399
399400
```tablegen
400401
// An example type with an assembly format.
@@ -412,24 +413,24 @@ def MyType : TypeDef<My_Dialect, "MyType"> {
412413
}
413414
```
414415

415-
The declarative assembly format for `MyType` results in the following format
416-
in the IR:
416+
The declarative assembly format for `MyType` results in the following format in
417+
the IR:
417418

418419
```mlir
419420
!my_dialect.my_type<42, map = affine_map<(i, j) -> (j, i)>
420421
```
421422

422423
### Parameter Parsing and Printing
423424

424-
For many basic parameter types, no additional work is needed to define how
425-
these parameters are parsed or printed.
425+
For many basic parameter types, no additional work is needed to define how these
426+
parameters are parsed or printed.
426427

427-
* The default printer for any parameter is `$_printer << $_self`,
428-
where `$_self` is the C++ value of the parameter and `$_printer` is an
429-
`AsmPrinter`.
430-
* The default parser for a parameter is
431-
`FieldParser<$cppClass>::parse($_parser)`, where `$cppClass` is the C++ type
432-
of the parameter and `$_parser` is an `AsmParser`.
428+
* The default printer for any parameter is `$_printer << $_self`, where
429+
`$_self` is the C++ value of the parameter and `$_printer` is an
430+
`AsmPrinter`.
431+
* The default parser for a parameter is
432+
`FieldParser<$cppClass>::parse($_parser)`, where `$cppClass` is the C++ type
433+
of the parameter and `$_parser` is an `AsmParser`.
433434

434435
Printing and parsing behaviour can be added to additional C++ types by
435436
overloading these functions or by defining a `parser` and `printer` in an ODS
@@ -470,8 +471,8 @@ def MyParameter : TypeParameter<"std::pair<int, int>", "pair of ints"> {
470471
}
471472
```
472473
473-
A type using this parameter with the assembly format `` `<` $myParam `>` ``
474-
will look as follows in the IR:
474+
A type using this parameter with the assembly format `` `<` $myParam `>` `` will
475+
look as follows in the IR:
475476
476477
```mlir
477478
!my_dialect.my_type<42 * 24>
@@ -480,10 +481,42 @@ will look as follows in the IR:
480481
#### Non-POD Parameters
481482

482483
Parameters that aren't plain-old-data (e.g. references) may need to define a
483-
`cppStorageType` to contain the data until it is copied into the allocator.
484-
For example, `StringRefParameter` uses `std::string` as its storage type,
485-
whereas `ArrayRefParameter` uses `SmallVector` as its storage type. The parsers
486-
for these parameters are expected to return `FailureOr<$cppStorageType>`.
484+
`cppStorageType` to contain the data until it is copied into the allocator. For
485+
example, `StringRefParameter` uses `std::string` as its storage type, whereas
486+
`ArrayRefParameter` uses `SmallVector` as its storage type. The parsers for
487+
these parameters are expected to return `FailureOr<$cppStorageType>`.
488+
489+
#### Optional Parameters
490+
491+
Optional parameters in the assembly format can be indicated by setting
492+
`isOptional`. The C++ type of an optional parameter is required to satisfy the
493+
following requirements:
494+
495+
* is default-constructible
496+
* is contextually convertible to `bool`
497+
* only the default-constructed value is `false`
498+
499+
The parameter parser should return the default-constructed value to indicate "no
500+
value present". The printer will guard on the presence of a value to print the
501+
parameter.
502+
503+
If a value was not parsed for an optional parameter, then the parameter will be
504+
set to its default-constructed C++ value. For example, `Optional<int>` will be
505+
set to `llvm::None` and `Attribute` will be set to `nullptr`.
506+
507+
Only optional parameters or directives that only capture optional parameters can
508+
be used in optional groups. An optional group is a set of elements optionally
509+
printed based on the presence of an anchor. Suppose parameter `a` is an
510+
`IntegerAttr`.
511+
512+
```
513+
( `(` $a^ `)` ) : (`x`)?
514+
```
515+
516+
In the above assembly format, if `a` is present (non-null), then it will be
517+
printed as `(5 : i32)`. If it is not present, it will be `x`. Directives that
518+
are used inside optional groups are allowed only if all captured parameters are
519+
also optional.
487520

488521
### Assembly Format Directives
489522

@@ -497,9 +530,9 @@ Attribute and type assembly formats have the following directives:
497530

498531
#### `params` Directive
499532

500-
This directive is used to refer to all parameters of an attribute or type.
501-
When used as a top-level directive, `params` generates a parser and printer for
502-
a comma-separated list of the parameters. For example:
533+
This directive is used to refer to all parameters of an attribute or type. When
534+
used as a top-level directive, `params` generates a parser and printer for a
535+
comma-separated list of the parameters. For example:
503536

504537
```tablegen
505538
def MyPairType : TypeDef<My_Dialect, "MyPairType"> {
@@ -547,12 +580,16 @@ In the IR, the types will appear as:
547580
!my_dialect.outer_qual<pair : !mydialect.pair<42, 24>>
548581
```
549582

583+
If optional parameters are present, they are not printed in the parameter list
584+
if they are not present.
585+
550586
#### `struct` Directive
551587

552588
The `struct` directive accepts a list of variables to capture and will generate
553-
a parser and printer for a comma-separated list of key-value pairs. The
554-
variables are printed in the order they are specified in the argument list **but
555-
can be parsed in any order**. For example:
589+
a parser and printer for a comma-separated list of key-value pairs. If an
590+
optional parameter is included in the `struct`, it can be elided. The variables
591+
are printed in the order they are specified in the argument list **but can be
592+
parsed in any order**. For example:
556593

557594
```tablegen
558595
def MyStructType : TypeDef<My_Dialect, "MyStructType"> {

mlir/include/mlir/IR/OpBase.td

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,15 +3130,19 @@ class AttrOrTypeParameter<string type, string desc, string accessorType = ""> {
31303130
string summary = desc;
31313131
// The format string for the asm syntax (documentation only).
31323132
string syntax = ?;
3133-
// The default parameter parser is `::mlir::parseField<T>($_parser)`, which
3134-
// returns `FailureOr<T>`. Overload `parseField` to support parsing for your
3135-
// type. Or you can provide a customer printer. For attributes, "$_type" will
3136-
// be replaced with the required attribute type.
3133+
// The default parameter parser is `::mlir::FieldParser<T>::parse($_parser)`,
3134+
// which returns `FailureOr<T>`. Specialize `FieldParser` to support parsing
3135+
// for your type. Or you can provide a customer printer. For attributes,
3136+
// "$_type" will be replaced with the required attribute type.
31373137
string parser = ?;
31383138
// The default parameter printer is `$_printer << $_self`. Overload the stream
31393139
// operator of `AsmPrinter` as necessary to print your type. Or you can
31403140
// provide a custom printer.
31413141
string printer = ?;
3142+
// Mark a parameter as optional. The C++ type of parameters marked as optional
3143+
// must be default constructible and be contextually convertible to `bool`.
3144+
// Any `Optional<T>` and any attribute type satisfies these requirements.
3145+
bit isOptional = 0;
31423146
}
31433147
class AttrParameter<string type, string desc, string accessorType = "">
31443148
: AttrOrTypeParameter<type, desc, accessorType>;
@@ -3183,6 +3187,12 @@ class ArrayRefOfSelfAllocationParameter<string arrayOf, string desc> :
31833187
}];
31843188
}
31853189

3190+
// An optional parameter.
3191+
class OptionalParameter<string type, string desc = ""> :
3192+
AttrOrTypeParameter<type, desc> {
3193+
let isOptional = 1;
3194+
}
3195+
31863196
// This is a special parameter used for AttrDefs that represents a `mlir::Type`
31873197
// that is also used as the value `Type` of the attribute. Only one parameter
31883198
// of the attribute may be of this type.

0 commit comments

Comments
 (0)