11# Defining Dialect Attributes and Types
22
33This 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
88See [ MLIR specification] ( ../LangRef.md ) for more information about MLIR, the
99structure of the IR, operations, etc.
@@ -24,18 +24,19 @@ defining a new `Type` it isn't always necessary to define a new storage class.
2424So before defining the derived ` Type ` , it's important to know which of the two
2525classes 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
3132differentiates 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
390391assembly 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
434435Printing and parsing behaviour can be added to additional C++ types by
435436overloading 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
482483Parameters 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
505538def 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
552588The ` 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
558595def MyStructType : TypeDef<My_Dialect, "MyStructType"> {
0 commit comments