1
1
# Defining Dialect Attributes and Types
2
2
3
3
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.
7
7
8
8
See [ MLIR specification] ( ../LangRef.md ) for more information about MLIR, the
9
9
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.
24
24
So before defining the derived ` Type ` , it's important to know which of the two
25
25
classes of ` Type ` we are defining:
26
26
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 ) .
29
30
30
- Other types are _ parametric _ , and contain additional information that
31
+ Other types are * parametric * , and contain additional information that
31
32
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.
39
40
40
41
#### Singleton types
41
42
@@ -389,12 +390,12 @@ Attributes and types defined in ODS with a mnemonic can define an
389
390
`assemblyFormat` to declaratively describe custom parsers and printers. The
390
391
assembly format consists of literals, variables, and directives.
391
392
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.
398
399
399
400
```tablegen
400
401
// An example type with an assembly format.
@@ -412,24 +413,24 @@ def MyType : TypeDef<My_Dialect, "MyType"> {
412
413
}
413
414
```
414
415
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:
417
418
418
419
``` mlir
419
420
!my_dialect.my_type<42, map = affine_map<(i, j) -> (j, i)>
420
421
```
421
422
422
423
### Parameter Parsing and Printing
423
424
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.
426
427
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 ` .
433
434
434
435
Printing and parsing behaviour can be added to additional C++ types by
435
436
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"> {
470
471
}
471
472
```
472
473
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:
475
476
476
477
```mlir
477
478
!my_dialect.my_type<42 * 24>
@@ -480,10 +481,42 @@ will look as follows in the IR:
480
481
#### Non-POD Parameters
481
482
482
483
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.
487
520
488
521
### Assembly Format Directives
489
522
@@ -497,9 +530,9 @@ Attribute and type assembly formats have the following directives:
497
530
498
531
#### ` params ` Directive
499
532
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:
503
536
504
537
``` tablegen
505
538
def MyPairType : TypeDef<My_Dialect, "MyPairType"> {
@@ -547,12 +580,16 @@ In the IR, the types will appear as:
547
580
!my_dialect.outer_qual<pair : !mydialect.pair<42, 24>>
548
581
```
549
582
583
+ If optional parameters are present, they are not printed in the parameter list
584
+ if they are not present.
585
+
550
586
#### ` struct ` Directive
551
587
552
588
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:
556
593
557
594
``` tablegen
558
595
def MyStructType : TypeDef<My_Dialect, "MyStructType"> {
0 commit comments