forked from OSchip/llvm-project
[mlir][ODS] Rename several uses of 'description' to 'summary'
Right now constraint/predicate traits/etc. use their "description" field as a one line human readable string. This breaks the current convention, by which a "description" may be multi-line. This revision renames the "description" field in these cases to "summary" which matches what the string is actually used as. This also unbreaks the use of TypeDefs(and eventually AttrDefs) in conjunction with existing type constraint facilities like `Optional`. Differential Revision: https://reviews.llvm.org/D94133
This commit is contained in:
parent
4726bec8f2
commit
e0a93e4b65
|
@ -4,16 +4,17 @@ In addition to specializing the `mlir::Op` C++ template, MLIR also supports
|
|||
defining operations and data types in a table-driven manner. This is achieved
|
||||
via [TableGen][TableGen], which is both a generic language and its tooling to
|
||||
maintain records of domain-specific information. Facts regarding an operation
|
||||
are specified concisely into a TableGen record, which will be expanded into
|
||||
an equivalent `mlir::Op` C++ template specialization at compiler build time.
|
||||
are specified concisely into a TableGen record, which will be expanded into an
|
||||
equivalent `mlir::Op` C++ template specialization at compiler build time.
|
||||
|
||||
This manual explains in detail all the available mechanisms for defining
|
||||
operations in such a table-driven manner. It aims to be a specification instead
|
||||
of a tutorial. Please refer to [Quickstart tutorial to adding MLIR graph
|
||||
rewrite](Tutorials/QuickstartRewrites.md) for the latter.
|
||||
of a tutorial. Please refer to
|
||||
[Quickstart tutorial to adding MLIR graph rewrite](Tutorials/QuickstartRewrites.md)
|
||||
for the latter.
|
||||
|
||||
In addition to detailing each mechanism, this manual also tries to capture
|
||||
best practices. They are rendered as quoted bullet points.
|
||||
In addition to detailing each mechanism, this manual also tries to capture best
|
||||
practices. They are rendered as quoted bullet points.
|
||||
|
||||
## Motivation
|
||||
|
||||
|
@ -22,12 +23,12 @@ operations. This open and extensible ecosystem leads to the "stringly" type IR
|
|||
problem, e.g., repetitive string comparisons during optimization and analysis
|
||||
passes, unintuitive accessor methods (e.g., generic/error prone `getOperand(3)`
|
||||
vs self-documenting `getStride()`) with more generic return types, verbose and
|
||||
generic constructors without default arguments, verbose textual IR dump, and
|
||||
so on. Furthermore, operation verification is:
|
||||
generic constructors without default arguments, verbose textual IR dump, and so
|
||||
on. Furthermore, operation verification is:
|
||||
|
||||
1. best case: a central string-to-verification-function map,
|
||||
1. middle case: duplication of verification across the code base, or
|
||||
1. worst case: no verification functions.
|
||||
1. best case: a central string-to-verification-function map,
|
||||
1. middle case: duplication of verification across the code base, or
|
||||
1. worst case: no verification functions.
|
||||
|
||||
The fix is to support defining ops in a table-driven manner. Then for each
|
||||
dialect, we can have a central place that contains everything you need to know
|
||||
|
@ -40,17 +41,17 @@ building, verification, parsing, printing, analysis, and many more.
|
|||
Compared to the C++ template, this table-driven approach has several benefits
|
||||
including but not limited to:
|
||||
|
||||
* **Single source of truth**: We strive to encode all facts regarding an
|
||||
operation into the record, so that readers don't need to jump among code
|
||||
snippets to fully understand an operation.
|
||||
* **Removing boilerplate**: We can automatically generate
|
||||
operand/attribute/result getter methods, operation build methods, operation
|
||||
verify methods, and many more utilities from the record. This greatly reduces
|
||||
the boilerplate needed for defining a new op.
|
||||
* **Facilitating auto-generation**: The usage of these operation information
|
||||
records are by no means limited to op definition itself. We can use them to
|
||||
drive the auto-generation of many other components, like computation graph
|
||||
serialization.
|
||||
* **Single source of truth**: We strive to encode all facts regarding an
|
||||
operation into the record, so that readers don't need to jump among code
|
||||
snippets to fully understand an operation.
|
||||
* **Removing boilerplate**: We can automatically generate
|
||||
operand/attribute/result getter methods, operation build methods, operation
|
||||
verify methods, and many more utilities from the record. This greatly
|
||||
reduces the boilerplate needed for defining a new op.
|
||||
* **Facilitating auto-generation**: The usage of these operation information
|
||||
records are by no means limited to op definition itself. We can use them to
|
||||
drive the auto-generation of many other components, like computation graph
|
||||
serialization.
|
||||
|
||||
## TableGen Syntax
|
||||
|
||||
|
@ -128,8 +129,8 @@ window in `value`.
|
|||
}
|
||||
```
|
||||
|
||||
In the following we describe all the fields needed. Please see the definition
|
||||
of the `Op` class for the complete list of fields supported.
|
||||
In the following we describe all the fields needed. Please see the definition of
|
||||
the `Op` class for the complete list of fields supported.
|
||||
|
||||
### Operation name
|
||||
|
||||
|
@ -159,12 +160,12 @@ let description = [{
|
|||
|
||||
`description` should be written in Markdown syntax.
|
||||
|
||||
Placing the documentation at the beginning is recommended since
|
||||
it helps in understanding the operation.
|
||||
Placing the documentation at the beginning is recommended since it helps in
|
||||
understanding the operation.
|
||||
|
||||
> * Place documentation at the beginning of the operation definition
|
||||
> * The summary should be short and concise. It should be a one-liner without
|
||||
> trailing punctuation. Put expanded explanation in description.
|
||||
> * Place documentation at the beginning of the operation definition
|
||||
> * The summary should be short and concise. It should be a one-liner without
|
||||
> trailing punctuation. Put expanded explanation in description.
|
||||
|
||||
### Operation arguments
|
||||
|
||||
|
@ -172,16 +173,16 @@ There are two kinds of arguments: operands and attributes. Operands are runtime
|
|||
values produced by other ops; while attributes are compile-time known constant
|
||||
values, including two categories:
|
||||
|
||||
1. Natural attributes: these attributes affect the behavior of the operations
|
||||
(e.g., padding for convolution);
|
||||
1. Derived attributes: these attributes are not needed to define the operation
|
||||
but are instead derived from information of the operation. E.g., the output
|
||||
shape of type. This is mostly used for convenience interface generation or
|
||||
interaction with other frameworks/translation.
|
||||
1. Natural attributes: these attributes affect the behavior of the operations
|
||||
(e.g., padding for convolution);
|
||||
1. Derived attributes: these attributes are not needed to define the operation
|
||||
but are instead derived from information of the operation. E.g., the output
|
||||
shape of type. This is mostly used for convenience interface generation or
|
||||
interaction with other frameworks/translation.
|
||||
|
||||
All derived attributes should be materializable as an Attribute. That is,
|
||||
even though they are not materialized, it should be possible to store as
|
||||
an attribute.
|
||||
All derived attributes should be materializable as an Attribute. That is,
|
||||
even though they are not materialized, it should be possible to store as an
|
||||
attribute.
|
||||
|
||||
Both operands and attributes are specified inside the `dag`-typed `arguments`,
|
||||
led by `ins`:
|
||||
|
@ -203,11 +204,11 @@ information.
|
|||
There is no requirements on the relative order of operands and attributes; they
|
||||
can mix freely. The relative order of operands themselves matters. From each
|
||||
named argument a named getter will be generated that returns the argument with
|
||||
the return type (in the case of attributes the return type will be
|
||||
constructed from the storage type, while for operands it will be `Value`). Each
|
||||
attribute's raw value (e.g., as stored) can also be accessed via generated
|
||||
`<name>Attr` getters for use in transformation passes where the more user
|
||||
friendly return type is less suitable.
|
||||
the return type (in the case of attributes the return type will be constructed
|
||||
from the storage type, while for operands it will be `Value`). Each attribute's
|
||||
raw value (e.g., as stored) can also be accessed via generated `<name>Attr`
|
||||
getters for use in transformation passes where the more user friendly return
|
||||
type is less suitable.
|
||||
|
||||
All the arguments should be named to 1) provide documentation, 2) drive
|
||||
auto-generation of getter methods, 3) provide a handle to reference for other
|
||||
|
@ -313,9 +314,9 @@ let results = (outs
|
|||
|
||||
#### Variadic results
|
||||
|
||||
Similar to variadic operands, `Variadic<...>` can also be used for results.
|
||||
And similarly, `SameVariadicResultSize` for multiple variadic results in the
|
||||
same operation.
|
||||
Similar to variadic operands, `Variadic<...>` can also be used for results. And
|
||||
similarly, `SameVariadicResultSize` for multiple variadic results in the same
|
||||
operation.
|
||||
|
||||
### Operation successors
|
||||
|
||||
|
@ -337,8 +338,8 @@ currently only be specified as the last successor in the successor list.
|
|||
|
||||
### Operation traits and constraints
|
||||
|
||||
Traits are operation properties that affect syntax or semantics. MLIR C++
|
||||
models various traits in the `mlir::OpTrait` namespace.
|
||||
Traits are operation properties that affect syntax or semantics. MLIR C++ models
|
||||
various traits in the `mlir::OpTrait` namespace.
|
||||
|
||||
Both operation traits, [interfaces](Interfaces.md#utilizing-the-ods-framework),
|
||||
and constraints involving multiple operands/attributes/results are provided as
|
||||
|
@ -548,8 +549,8 @@ Functions to parse and print the operation's custom assembly form.
|
|||
### Custom verifier code
|
||||
|
||||
Verification code will be automatically generated for
|
||||
[constraints](#constraints) specified on various entities of the op. To
|
||||
perform _additional_ verification, you can use
|
||||
[constraints](#constraints) specified on various entities of the op. To perform
|
||||
_additional_ verification, you can use
|
||||
|
||||
```tablegen
|
||||
let verifier = [{
|
||||
|
@ -700,8 +701,8 @@ identifier used as a suffix to these two calls, i.e., `custom<MyDirective>(...)`
|
|||
would result in calls to `parseMyDirective` and `printMyDirective` within the
|
||||
parser and printer respectively. `Params` may be any combination of variables
|
||||
(i.e. Attribute, Operand, Successor, etc.), type directives, and `attr-dict`.
|
||||
The type directives must refer to a variable, but that variable need not also
|
||||
be a parameter to the custom directive.
|
||||
The type directives must refer to a variable, but that variable need not also be
|
||||
a parameter to the custom directive.
|
||||
|
||||
The arguments to the `parse<UserDirective>` method are firstly a reference to
|
||||
the `OpAsmParser`(`OpAsmParser &`), and secondly a set of output parameters
|
||||
|
@ -734,9 +735,9 @@ declarative parameter to `parse` method argument is detailed below:
|
|||
When a variable is optional, the value should only be specified if the variable
|
||||
is present. Otherwise, the value should remain `None` or null.
|
||||
|
||||
The arguments to the `print<UserDirective>` method is firstly a reference to
|
||||
the `OpAsmPrinter`(`OpAsmPrinter &`), second the op (e.g. `FooOp op` which
|
||||
can be `Operation *op` alternatively), and finally a set of output parameters
|
||||
The arguments to the `print<UserDirective>` method is firstly a reference to the
|
||||
`OpAsmPrinter`(`OpAsmPrinter &`), second the op (e.g. `FooOp op` which can be
|
||||
`Operation *op` alternatively), and finally a set of output parameters
|
||||
corresponding to the parameters specified in the format. The mapping of
|
||||
declarative parameter to `print` method argument is detailed below:
|
||||
|
||||
|
@ -866,21 +867,21 @@ always be present. In certain instances, the type of a variable may be deduced
|
|||
via type constraints or other information available. In these cases, the type of
|
||||
that variable may be elided from the format.
|
||||
|
||||
* Buildable Types
|
||||
* Buildable Types
|
||||
|
||||
Some type constraints may only have one representation, allowing for them to
|
||||
be directly buildable; for example the `I32` or `Index` types. Types in `ODS`
|
||||
may mark themselves as buildable by setting the `builderCall` field or
|
||||
inheriting from the `BuildableType` class.
|
||||
Some type constraints may only have one representation, allowing for them to be
|
||||
directly buildable; for example the `I32` or `Index` types. Types in `ODS` may
|
||||
mark themselves as buildable by setting the `builderCall` field or inheriting
|
||||
from the `BuildableType` class.
|
||||
|
||||
* Trait Equality Constraints
|
||||
* Trait Equality Constraints
|
||||
|
||||
There are many operations that have known type equality constraints registered
|
||||
as traits on the operation; for example the true, false, and result values of a
|
||||
`select` operation often have the same type. The assembly format may inspect
|
||||
these equal constraints to discern the types of missing variables. The currently
|
||||
supported traits are: `AllTypesMatch`, `TypesMatchWith`, `SameTypeOperands`,
|
||||
and `SameOperandsAndResultType`.
|
||||
supported traits are: `AllTypesMatch`, `TypesMatchWith`, `SameTypeOperands`, and
|
||||
`SameOperandsAndResultType`.
|
||||
|
||||
### `hasCanonicalizer`
|
||||
|
||||
|
@ -890,8 +891,8 @@ be defined.
|
|||
|
||||
### `hasFolder`
|
||||
|
||||
This boolean field indicate whether general folding rules have been defined
|
||||
for this operation. If it is `1`, then `::fold()` should be defined.
|
||||
This boolean field indicate whether general folding rules have been defined for
|
||||
this operation. If it is `1`, then `::fold()` should be defined.
|
||||
|
||||
### Extra declarations
|
||||
|
||||
|
@ -901,8 +902,8 @@ long-tail cases that won't be covered. For such cases, you can use
|
|||
`extraClassDeclaration`. Code in `extraClassDeclaration` will be copied
|
||||
literally to the generated C++ op class.
|
||||
|
||||
Note that `extraClassDeclaration` is a mechanism intended for long-tail cases
|
||||
by power users; for not-yet-implemented widely-applicable cases, improving the
|
||||
Note that `extraClassDeclaration` is a mechanism intended for long-tail cases by
|
||||
power users; for not-yet-implemented widely-applicable cases, improving the
|
||||
infrastructure is preferable.
|
||||
|
||||
### Generated C++ code
|
||||
|
@ -922,16 +923,16 @@ defining `GET_OP_LIST`.
|
|||
#### Class name and namespaces
|
||||
|
||||
For each operation, its generated C++ class name is the symbol `def`ed with
|
||||
TableGen with dialect prefix removed. The first `_` serves as the delimiter.
|
||||
For example, for `def TF_AddOp`, the C++ class name would be `AddOp`.
|
||||
We remove the `TF` prefix because it is for scoping ops; other dialects
|
||||
may as well define their own `AddOp`s.
|
||||
TableGen with dialect prefix removed. The first `_` serves as the delimiter. For
|
||||
example, for `def TF_AddOp`, the C++ class name would be `AddOp`. We remove the
|
||||
`TF` prefix because it is for scoping ops; other dialects may as well define
|
||||
their own `AddOp`s.
|
||||
|
||||
The namespaces of the generated C++ class will come from the dialect's
|
||||
`cppNamespace` field. For example, if a dialect's `cppNamespace` is `A::B`,
|
||||
then an op of that dialect will be placed in
|
||||
`namespace A { namespace B { ... } }`. If a dialect does not specify a
|
||||
`cppNamespace`, we then use the dialect's name as the namespace.
|
||||
`cppNamespace` field. For example, if a dialect's `cppNamespace` is `A::B`, then
|
||||
an op of that dialect will be placed in `namespace A { namespace B { ... } }`.
|
||||
If a dialect does not specify a `cppNamespace`, we then use the dialect's name
|
||||
as the namespace.
|
||||
|
||||
This means the qualified name of the generated C++ class does not necessarily
|
||||
match exactly with the operation name as explained in
|
||||
|
@ -976,10 +977,11 @@ significantly involve writing constraints. We have the `Constraint` class in
|
|||
|
||||
An operation's constraint can cover different range; it may
|
||||
|
||||
* Only concern a single attribute (e.g. being a 32-bit integer greater than 5),
|
||||
* Multiple operands and results (e.g., the 1st result's shape must be the same
|
||||
as the 1st operand), or
|
||||
* Intrinsic to the operation itself (e.g., having no side effect).
|
||||
* Only concern a single attribute (e.g. being a 32-bit integer greater than
|
||||
5),
|
||||
* Multiple operands and results (e.g., the 1st result's shape must be the same
|
||||
as the 1st operand), or
|
||||
* Intrinsic to the operation itself (e.g., having no side effect).
|
||||
|
||||
We call them as single-entity constraint, multi-entity constraint, and traits,
|
||||
respectively.
|
||||
|
@ -993,8 +995,8 @@ the entity's declaration place as described in
|
|||
|
||||
To help modelling constraints of common types, a set of `TypeConstraint`s are
|
||||
created; they are the `Type` subclass hierarchy. It includes `F32` for the
|
||||
constraints of being a float, `TensorOf<[F32]>` for the constraints of being
|
||||
a float tensor, and so on.
|
||||
constraints of being a float, `TensorOf<[F32]>` for the constraints of being a
|
||||
float tensor, and so on.
|
||||
|
||||
Similarly, a set of `AttrConstraint`s are created for helping modelling
|
||||
constraints of common attribute kinds. They are the `Attr` subclass hierarchy.
|
||||
|
@ -1003,8 +1005,8 @@ It includes `F32Attr` for the constraints of being a float attribute,
|
|||
|
||||
### Multi-entity constraint
|
||||
|
||||
Constraints involving more than one operand/attribute/result are quite common
|
||||
on operations, like the element type and shape relation between operands and
|
||||
Constraints involving more than one operand/attribute/result are quite common on
|
||||
operations, like the element type and shape relation between operands and
|
||||
results. These constraints should be specified as the `Op` class template
|
||||
parameter as described in
|
||||
[Operation traits and constraints](#operation-traits-and-constraints).
|
||||
|
@ -1037,31 +1039,31 @@ in a nested manner, using the two categories of predicates:
|
|||
substitution: `SubstLeaves`, concatenation: `Concat`).
|
||||
|
||||
`CPred` is the basis for composing more complex predicates. It is the "atom"
|
||||
predicate from the perspective of TableGen and the "interface" between
|
||||
TableGen and C++. What is inside is already C++ code, which will be treated
|
||||
as opaque strings with special placeholders to be substituted.
|
||||
predicate from the perspective of TableGen and the "interface" between TableGen
|
||||
and C++. What is inside is already C++ code, which will be treated as opaque
|
||||
strings with special placeholders to be substituted.
|
||||
|
||||
You can put any C++ code that returns a boolean value inside a `CPred`,
|
||||
including evaluating expressions, calling functions, calling class methods,
|
||||
and so on.
|
||||
including evaluating expressions, calling functions, calling class methods, and
|
||||
so on.
|
||||
|
||||
To help interaction with the C++ environment, there are a few special
|
||||
placeholders provided to refer to entities in the context where this predicate
|
||||
is used. They serve as "hooks" to the enclosing environment. This includes
|
||||
is used. They serve as "hooks" to the enclosing environment. This includes
|
||||
`$_builder`, `$_op`, and `$_self`:
|
||||
|
||||
* `$_builder` will be replaced by a `mlir::Builder` instance so that you can
|
||||
access common build methods.
|
||||
* `$_op` will be replaced by the current operation so that you can access
|
||||
information of the current operation.
|
||||
* `$_self` will be replaced with the entity this predicate is attached to.
|
||||
E.g., `BoolAttr` is an attribute constraint that wraps a
|
||||
`CPred<"$_self.isa<BoolAttr>()">`. Then for `F32:$attr`,`$_self` will be
|
||||
replaced by `$attr`. For type constraints, it's a little bit special since
|
||||
we want the constraints on each type definition reads naturally and we want
|
||||
to attach type constraints directly to an operand/result, `$_self` will be
|
||||
replaced by the operand/result's type. E.g., for `F32` in `F32:$operand`, its
|
||||
`$_self` will be expanded as `getOperand(...).getType()`.
|
||||
* `$_builder` will be replaced by a `mlir::Builder` instance so that you can
|
||||
access common build methods.
|
||||
* `$_op` will be replaced by the current operation so that you can access
|
||||
information of the current operation.
|
||||
* `$_self` will be replaced with the entity this predicate is attached to.
|
||||
E.g., `BoolAttr` is an attribute constraint that wraps a
|
||||
`CPred<"$_self.isa<BoolAttr>()">`. Then for `F32:$attr`,`$_self` will be
|
||||
replaced by `$attr`. For type constraints, it's a little bit special since
|
||||
we want the constraints on each type definition reads naturally and we want
|
||||
to attach type constraints directly to an operand/result, `$_self` will be
|
||||
replaced by the operand/result's type. E.g., for `F32` in `F32:$operand`,
|
||||
its `$_self` will be expanded as `getOperand(...).getType()`.
|
||||
|
||||
TODO: Reconsider the leading symbol for special placeholders. Eventually we want
|
||||
to allow referencing operand/result $-names; such $-names can start with
|
||||
|
@ -1072,10 +1074,9 @@ just call `attr.isa<IntegerAttr>()`. The code can be wrapped in a `CPred` as
|
|||
`$_self.isa<IntegerAttr>()`, with `$_self` as the special placeholder to be
|
||||
replaced by the current attribute `attr` at expansion time.
|
||||
|
||||
For more complicated predicates, you can wrap it in a single `CPred`, or you
|
||||
can use predicate combiners to combine them. For example, to write the
|
||||
constraint that an attribute `attr` is a 32-bit or 64-bit integer, you can
|
||||
write it as
|
||||
For more complicated predicates, you can wrap it in a single `CPred`, or you can
|
||||
use predicate combiners to combine them. For example, to write the constraint
|
||||
that an attribute `attr` is a 32-bit or 64-bit integer, you can write it as
|
||||
|
||||
```tablegen
|
||||
And<[
|
||||
|
@ -1096,9 +1097,9 @@ I64Attr.predicate]>`.)
|
|||
TODO: Build up a library of reusable primitive constraints
|
||||
|
||||
If the predicate is very complex to write with `CPred` together with predicate
|
||||
combiners, you can also write it as a normal C++ function and use the `CPred`
|
||||
as a way to "invoke" the function. For example, to verify an attribute `attr`
|
||||
has some property, you can write a C++ function like
|
||||
combiners, you can also write it as a normal C++ function and use the `CPred` as
|
||||
a way to "invoke" the function. For example, to verify an attribute `attr` has
|
||||
some property, you can write a C++ function like
|
||||
|
||||
```cpp
|
||||
bool HasSomeProperty(Attribute attr) { ... }
|
||||
|
@ -1118,13 +1119,13 @@ def MyOp : Op<...> {
|
|||
}
|
||||
```
|
||||
|
||||
As to whether we should define the predicate using a single `CPred` wrapping
|
||||
the whole expression, multiple `CPred`s with predicate combiners, or a single
|
||||
As to whether we should define the predicate using a single `CPred` wrapping the
|
||||
whole expression, multiple `CPred`s with predicate combiners, or a single
|
||||
`CPred` "invoking" a function, there are no clear-cut criteria. Defining using
|
||||
`CPred` and predicate combiners is preferable since it exposes more information
|
||||
(instead hiding all the logic behind a C++ function) into the op definition spec
|
||||
so that it can potentially drive more auto-generation cases. But it will
|
||||
require a nice library of common predicates as the building blocks to avoid the
|
||||
so that it can potentially drive more auto-generation cases. But it will require
|
||||
a nice library of common predicates as the building blocks to avoid the
|
||||
duplication, which is being worked on right now.
|
||||
|
||||
## Attribute Definition
|
||||
|
@ -1133,11 +1134,11 @@ An attribute is a compile-time known constant of an operation.
|
|||
|
||||
ODS provides attribute wrappers over C++ attribute classes. There are a few
|
||||
common C++ [attribute classes][AttrClasses] defined in MLIR's core IR library
|
||||
and one is free to define dialect-specific attribute classes. ODS allows one
|
||||
to use these attributes in TableGen to define operations, potentially with
|
||||
more fine-grained constraints. For example, `StrAttr` directly maps to
|
||||
`StringAttr`; `F32Attr`/`F64Attr` requires the `FloatAttr` to additionally
|
||||
be of a certain bitwidth.
|
||||
and one is free to define dialect-specific attribute classes. ODS allows one to
|
||||
use these attributes in TableGen to define operations, potentially with more
|
||||
fine-grained constraints. For example, `StrAttr` directly maps to `StringAttr`;
|
||||
`F32Attr`/`F64Attr` requires the `FloatAttr` to additionally be of a certain
|
||||
bitwidth.
|
||||
|
||||
ODS attributes are defined as having a storage type (corresponding to a backing
|
||||
`mlir::Attribute` that _stores_ the attribute), a return type (corresponding to
|
||||
|
@ -1440,8 +1441,8 @@ need allocation in the storage constructor, there are two options:
|
|||
### TypeParameter tablegen class
|
||||
|
||||
This is used to further specify attributes about each of the types parameters.
|
||||
It includes documentation (`description` and `syntax`), the C++ type to use, and
|
||||
a custom allocator to use in the storage constructor method.
|
||||
It includes documentation (`summary` and `syntax`), the C++ type to use, and a
|
||||
custom allocator to use in the storage constructor method.
|
||||
|
||||
```tablegen
|
||||
// DO NOT DO THIS!
|
||||
|
@ -1539,8 +1540,8 @@ responsible for parsing/printing the types in `Dialect::printType` and
|
|||
|
||||
### Run `mlir-tblgen` to see the generated content
|
||||
|
||||
TableGen syntax sometimes can be obscure; reading the generated content can be
|
||||
a very helpful way to understand and debug issues. To build `mlir-tblgen`, run
|
||||
TableGen syntax sometimes can be obscure; reading the generated content can be a
|
||||
very helpful way to understand and debug issues. To build `mlir-tblgen`, run
|
||||
`cmake --build . --target mlir-tblgen` in your build directory and find the
|
||||
`mlir-tblgen` binary in the `bin/` subdirectory. All the supported generators
|
||||
can be found via `mlir-tblgen --help`. For example, `--gen-op-decls` and
|
||||
|
@ -1571,8 +1572,8 @@ mlir-tblgen --gen-op-interface-doc -I /path/to/mlir/include /path/to/input/td/fi
|
|||
|
||||
The op description should as declarative as possible to allow a wide range of
|
||||
tools to work with them and query methods generated from them. In particular
|
||||
this means specifying traits, constraints and shape inference information in
|
||||
a way that is easily analyzable (e.g., avoid opaque calls to C++ functions where
|
||||
this means specifying traits, constraints and shape inference information in a
|
||||
way that is easily analyzable (e.g., avoid opaque calls to C++ functions where
|
||||
possible).
|
||||
|
||||
We considered the approaches of several contemporary systems and focused on
|
||||
|
|
|
@ -38,7 +38,7 @@ def ArmSVE_ScalableVectorType : DialectType<ArmSVE_Dialect,
|
|||
CPred<"$_self.isa<ScalableVectorType>()">,
|
||||
"scalable vector type">,
|
||||
BuildableType<"$_builder.getType<ScalableVectorType>()"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
`arm_sve.vector` represents vectors that will be processed by a scalable
|
||||
vector architecture.
|
||||
}];
|
||||
|
@ -119,8 +119,8 @@ class ScalableVectorOfLengthAndType<list<int> allowedLengths,
|
|||
list<Type> allowedTypes> : Type<
|
||||
And<[ScalableVectorOf<allowedTypes>.predicate,
|
||||
ScalableVectorOfLength<allowedLengths>.predicate]>,
|
||||
ScalableVectorOf<allowedTypes>.description #
|
||||
ScalableVectorOfLength<allowedLengths>.description>;
|
||||
ScalableVectorOf<allowedTypes>.summary #
|
||||
ScalableVectorOfLength<allowedLengths>.summary>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ArmSVE op definitions
|
||||
|
|
|
@ -33,7 +33,7 @@ def AsyncDialect : Dialect {
|
|||
def Async_TokenType : DialectType<AsyncDialect,
|
||||
CPred<"$_self.isa<::mlir::async::TokenType>()">, "token type">,
|
||||
BuildableType<"$_builder.getType<::mlir::async::TokenType>()"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
`async.token` is a type returned by asynchronous operations, and it becomes
|
||||
`ready` when the asynchronous operations that created it is completed.
|
||||
}];
|
||||
|
@ -46,8 +46,8 @@ class Async_ValueType<Type type>
|
|||
SubstLeaves<"$_self",
|
||||
"$_self.cast<::mlir::async::ValueType>().getValueType()",
|
||||
type.predicate>
|
||||
]>, "async value type with " # type.description # " underlying type"> {
|
||||
let typeDescription = [{
|
||||
]>, "async value type with " # type.summary # " underlying type"> {
|
||||
let description = [{
|
||||
`async.value` represents a value returned by asynchronous operations,
|
||||
which may or may not be available currently, but will be available at some
|
||||
point in the future.
|
||||
|
@ -59,7 +59,7 @@ class Async_ValueType<Type type>
|
|||
def Async_GroupType : DialectType<AsyncDialect,
|
||||
CPred<"$_self.isa<::mlir::async::GroupType>()">, "group type">,
|
||||
BuildableType<"$_builder.getType<::mlir::async::GroupType>()"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
`async.group` represent a set of async tokens or values and allows to
|
||||
execute async operations on all of them together (e.g. wait for the
|
||||
completion of all/any of them).
|
||||
|
|
|
@ -102,7 +102,7 @@ class LLVM_PointerTo<Type pointee> : Type<
|
|||
"$_self",
|
||||
"$_self.cast<::mlir::LLVM::LLVMPointerType>().getElementType()",
|
||||
pointee.predicate>]>,
|
||||
"LLVM pointer to " # pointee.description>;
|
||||
"LLVM pointer to " # pointee.summary>;
|
||||
|
||||
// Type constraint accepting any LLVM structure type.
|
||||
def LLVM_AnyStruct : Type<CPred<"$_self.isa<::mlir::LLVM::LLVMStructType>()">,
|
||||
|
@ -142,7 +142,7 @@ class LLVM_VectorOf<Type element> : Type<
|
|||
"$_self",
|
||||
"$_self.cast<::mlir::LLVM::LLVMVectorType>().getElementType()",
|
||||
element.predicate>]>,
|
||||
"LLVM vector of " # element.description>;
|
||||
"LLVM vector of " # element.summary>;
|
||||
|
||||
// Type constraint accepting a constrained type, or a vector of such types.
|
||||
class LLVM_ScalarOrVectorOf<Type element> :
|
||||
|
|
|
@ -28,7 +28,7 @@ class quant_TypedPrimitiveOrContainer<Type etype> :
|
|||
Type<Or<[etype.predicate,
|
||||
TensorOf<[etype]>.predicate,
|
||||
VectorOf<[etype]>.predicate]>,
|
||||
"primitive/tensor/vector of " # etype.description>;
|
||||
"primitive/tensor/vector of " # etype.summary>;
|
||||
|
||||
// An implementation of QuantizedType.
|
||||
def quant_QuantizedType :
|
||||
|
|
|
@ -43,7 +43,7 @@ def ShapeDialect : Dialect {
|
|||
def Shape_ShapeType : DialectType<ShapeDialect,
|
||||
CPred<"$_self.isa<::mlir::shape::ShapeType>()">, "shape">,
|
||||
BuildableType<"$_builder.getType<::mlir::shape::ShapeType>()"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
`shape.shape` represents either an unranked shape, a ranked shape with
|
||||
possibly unknown dimensions or an invalid shape. The rank is of type
|
||||
`shape.size` and, if rank is known, the extent is a 1D tensor of type
|
||||
|
@ -62,7 +62,7 @@ def Shape_ShapeType : DialectType<ShapeDialect,
|
|||
def Shape_SizeType : DialectType<ShapeDialect,
|
||||
CPred<"$_self.isa<::mlir::shape::SizeType>()">, "size">,
|
||||
BuildableType<"$_builder.getType<::mlir::shape::SizeType>()"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
`shape.size` represents a non-negative integer with support for being
|
||||
unknown and invalid.
|
||||
|
||||
|
@ -76,7 +76,7 @@ def Shape_ValueShapeType : DialectType<ShapeDialect,
|
|||
CPred<"$_self.isa<::mlir::shape::ValueShapeType>()">, "value shape">,
|
||||
BuildableType<"::mlir::shape::ValueShapeType::get($_builder.getContext())">
|
||||
{
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
`shape.value_shape` represents the value produced by an operation (this
|
||||
corresponds to `Value` in the compiler) and a shape. Conceptually this is a
|
||||
tuple of a value (potentially unknown) and `shape.shape`. The value and
|
||||
|
@ -93,7 +93,7 @@ def Shape_ExtentTensorType :
|
|||
1DTensorOf<[Index]>,
|
||||
BuildableType<"::mlir::RankedTensorType::get({ShapedType::kDynamicSize}, "
|
||||
"$_builder.getType<::mlir::IndexType>())"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
The extent tensor is a tensor of rank one with arbitrarily many index
|
||||
elements (tensor<?xindex>). Like `!shape.shape`, it is used to represent
|
||||
shapes with the difference that it is guaranteed to be error-free.
|
||||
|
@ -112,7 +112,7 @@ def Shape_SizeOrIndexType : AnyTypeOf<[Shape_SizeType, Index], "size or index">;
|
|||
def Shape_WitnessType : DialectType<ShapeDialect,
|
||||
CPred<"$_self.isa<::mlir::shape::WitnessType>()">, "witness">,
|
||||
BuildableType<"$_builder.getType<::mlir::shape::WitnessType>()"> {
|
||||
let typeDescription = [{
|
||||
let description = [{
|
||||
A witness is a structural device in the compiler to maintain ordering of
|
||||
code relying on information obtained from passing assertions. Witnesses do
|
||||
not represent any physical data.
|
||||
|
|
|
@ -63,7 +63,7 @@ def Tosa_UnaryOpQuantizationAttr : StructAttr<"UnaryOpQuantizationAttr",
|
|||
StructFieldAttr<"input_zp", I32Attr>,
|
||||
StructFieldAttr<"output_zp", I32Attr>
|
||||
]> {
|
||||
let description = "Attribute for UnaryOp quantization information.";
|
||||
let summary = "Attribute for UnaryOp quantization information.";
|
||||
}
|
||||
|
||||
// There is no explicit BinaryOpQuantizationAttr for 2-input/1-output ops. In
|
||||
|
@ -82,7 +82,7 @@ def Tosa_ConvOpQuantizationAttr : StructAttr<"ConvOpQuantizationAttr",
|
|||
StructFieldAttr<"input_zp", I32Attr>,
|
||||
StructFieldAttr<"weight_zp", I32Attr>
|
||||
]> {
|
||||
let description = "Attribute for Conv type op quantization information.";
|
||||
let summary = "Attribute for Conv type op quantization information.";
|
||||
}
|
||||
|
||||
def Tosa_MatMulOpQuantizationAttr : StructAttr<"MatMulOpQuantizationAttr",
|
||||
|
@ -90,7 +90,7 @@ def Tosa_MatMulOpQuantizationAttr : StructAttr<"MatMulOpQuantizationAttr",
|
|||
StructFieldAttr<"a_zp", I32Attr>,
|
||||
StructFieldAttr<"b_zp", I32Attr>
|
||||
]> {
|
||||
let description = "Attribute for MatMulOp quantization information.";
|
||||
let summary = "Attribute for MatMulOp quantization information.";
|
||||
}
|
||||
|
||||
// This attribute holds input zero point correction applied to the padding
|
||||
|
@ -101,7 +101,7 @@ def Tosa_PadOpQuantizationAttr : StructAttr<"PadOpQuantizationAttr",
|
|||
Tosa_Dialect, [
|
||||
StructFieldAttr<"input_zp", I32Attr>
|
||||
]> {
|
||||
let description = "Attribute for PadOp quantization information.";
|
||||
let summary = "Attribute for PadOp quantization information.";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -154,9 +154,9 @@ class Concat<string pre, Pred child, string suf> :
|
|||
class Constraint<Pred pred, string desc = ""> {
|
||||
// The predicates that this constraint requires.
|
||||
Pred predicate = pred;
|
||||
// User-readable description used in error reporting messages. If empty, a
|
||||
// generic message will be used.
|
||||
string description = desc;
|
||||
// User-readable one line summary used in error reporting messages. If empty,
|
||||
// a generic message will be used.
|
||||
string summary = desc;
|
||||
}
|
||||
|
||||
// Subclasses used to differentiate different constraint kinds. These are used
|
||||
|
@ -165,24 +165,24 @@ class Constraint<Pred pred, string desc = ""> {
|
|||
// are considered as uncategorized constraints.
|
||||
|
||||
// Subclass for constraints on a type.
|
||||
class TypeConstraint<Pred predicate, string description = "",
|
||||
class TypeConstraint<Pred predicate, string summary = "",
|
||||
string cppClassNameParam = "::mlir::Type"> :
|
||||
Constraint<predicate, description> {
|
||||
Constraint<predicate, summary> {
|
||||
// The name of the C++ Type class if known, or Type if not.
|
||||
string cppClassName = cppClassNameParam;
|
||||
}
|
||||
|
||||
// Subclass for constraints on an attribute.
|
||||
class AttrConstraint<Pred predicate, string description = ""> :
|
||||
Constraint<predicate, description>;
|
||||
class AttrConstraint<Pred predicate, string summary = ""> :
|
||||
Constraint<predicate, summary>;
|
||||
|
||||
// Subclass for constraints on a region.
|
||||
class RegionConstraint<Pred predicate, string description = ""> :
|
||||
Constraint<predicate, description>;
|
||||
class RegionConstraint<Pred predicate, string summary = ""> :
|
||||
Constraint<predicate, summary>;
|
||||
|
||||
// Subclass for constraints on a successor.
|
||||
class SuccessorConstraint<Pred predicate, string description = ""> :
|
||||
Constraint<predicate, description>;
|
||||
class SuccessorConstraint<Pred predicate, string summary = ""> :
|
||||
Constraint<predicate, summary>;
|
||||
|
||||
// How to use these constraint categories:
|
||||
//
|
||||
|
@ -282,14 +282,14 @@ class Dialect {
|
|||
class Type<Pred condition, string descr = "",
|
||||
string cppClassName = "::mlir::Type"> :
|
||||
TypeConstraint<condition, descr, cppClassName> {
|
||||
string typeDescription = "";
|
||||
string description = "";
|
||||
string builderCall = "";
|
||||
}
|
||||
|
||||
// Allows providing an alternative name and description to an existing type def.
|
||||
class TypeAlias<Type t, string description = t.description> :
|
||||
Type<t.predicate, description> {
|
||||
let typeDescription = t.typeDescription;
|
||||
// Allows providing an alternative name and summary to an existing type def.
|
||||
class TypeAlias<Type t, string summary = t.summary> :
|
||||
Type<t.predicate, summary> {
|
||||
let description = t.description;
|
||||
let builderCall = t.builderCall;
|
||||
}
|
||||
|
||||
|
@ -302,13 +302,13 @@ class DialectType<Dialect d, Pred condition, string descr = "",
|
|||
|
||||
// A variadic type constraint. It expands to zero or more of the base type. This
|
||||
// class is used for supporting variadic operands/results.
|
||||
class Variadic<Type type> : TypeConstraint<type.predicate, type.description> {
|
||||
class Variadic<Type type> : TypeConstraint<type.predicate, type.summary> {
|
||||
Type baseType = type;
|
||||
}
|
||||
|
||||
// An optional type constraint. It expands to either zero or one of the base
|
||||
// type. This class is used for supporting optional operands/results.
|
||||
class Optional<Type type> : TypeConstraint<type.predicate, type.description> {
|
||||
class Optional<Type type> : TypeConstraint<type.predicate, type.summary> {
|
||||
Type baseType = type;
|
||||
}
|
||||
|
||||
|
@ -339,13 +339,13 @@ def NoneType : Type<CPred<"$_self.isa<::mlir::NoneType>()">, "none type",
|
|||
BuildableType<"$_builder.getType<::mlir::NoneType>()">;
|
||||
|
||||
// Any type from the given list
|
||||
class AnyTypeOf<list<Type> allowedTypes, string description = "",
|
||||
class AnyTypeOf<list<Type> allowedTypes, string summary = "",
|
||||
string cppClassName = "::mlir::Type"> : Type<
|
||||
// Satisfy any of the allowed type's condition
|
||||
Or<!foreach(allowedtype, allowedTypes, allowedtype.predicate)>,
|
||||
!if(!eq(description, ""),
|
||||
!interleave(!foreach(t, allowedTypes, t.description), " or "),
|
||||
description)>;
|
||||
!if(!eq(summary, ""),
|
||||
!interleave(!foreach(t, allowedTypes, t.summary), " or "),
|
||||
summary)>;
|
||||
|
||||
// Integer types.
|
||||
|
||||
|
@ -475,7 +475,7 @@ class Complex<Type type>
|
|||
SubstLeaves<"$_self",
|
||||
"$_self.cast<::mlir::ComplexType>().getElementType()",
|
||||
type.predicate>]>,
|
||||
"complex type with " # type.description # " elements",
|
||||
"complex type with " # type.summary # " elements",
|
||||
"::mlir::ComplexType">,
|
||||
SameBuildabilityAs<type, "::mlir::ComplexType::get($_builder.get" # type #
|
||||
"Type())"> {
|
||||
|
@ -485,9 +485,9 @@ class Complex<Type type>
|
|||
def AnyComplex : Type<CPred<"$_self.isa<::mlir::ComplexType>()">,
|
||||
"complex-type", "::mlir::ComplexType">;
|
||||
|
||||
class OpaqueType<string dialect, string name, string description>
|
||||
class OpaqueType<string dialect, string name, string summary>
|
||||
: Type<CPred<"isOpaqueTypeWithName($_self, \""#dialect#"\", \""#name#"\")">,
|
||||
description, "::mlir::OpaqueType">,
|
||||
summary, "::mlir::OpaqueType">,
|
||||
BuildableType<"::mlir::OpaqueType::get($_builder.getContext(), "
|
||||
"$_builder.getIdentifier(\"" # dialect # "\"), \""
|
||||
# name # "\")">;
|
||||
|
@ -506,7 +506,7 @@ class ContainerType<Type etype, Pred containerPred, code elementTypeCall,
|
|||
Type<And<[containerPred,
|
||||
SubstLeaves<"$_self", !cast<string>(elementTypeCall),
|
||||
etype.predicate>]>,
|
||||
descr # " of " # etype.description # " values", cppClassName> {
|
||||
descr # " of " # etype.summary # " values", cppClassName> {
|
||||
// The type of elements in the container.
|
||||
Type elementType = etype;
|
||||
|
||||
|
@ -558,8 +558,7 @@ class VectorOfRankAndType<list<int> allowedRanks,
|
|||
list<Type> allowedTypes> : Type<
|
||||
And<[VectorOf<allowedTypes>.predicate,
|
||||
VectorOfRank<allowedRanks>.predicate]>,
|
||||
VectorOf<allowedTypes>.description #
|
||||
VectorOfRank<allowedRanks>.description,
|
||||
VectorOf<allowedTypes>.summary # VectorOfRank<allowedRanks>.summary,
|
||||
"::mlir::VectorType">;
|
||||
|
||||
// Whether the number of elements of a vector is from the given
|
||||
|
@ -585,8 +584,7 @@ class VectorOfLengthAndType<list<int> allowedLengths,
|
|||
list<Type> allowedTypes> : Type<
|
||||
And<[VectorOf<allowedTypes>.predicate,
|
||||
VectorOfLength<allowedLengths>.predicate]>,
|
||||
VectorOf<allowedTypes>.description #
|
||||
VectorOfLength<allowedLengths>.description,
|
||||
VectorOf<allowedTypes>.summary # VectorOfLength<allowedLengths>.summary,
|
||||
"::mlir::VectorType">;
|
||||
|
||||
def AnyVector : VectorOf<[AnyType]>;
|
||||
|
@ -612,7 +610,7 @@ def AnyRankedTensor :
|
|||
// TODO: Have an easy way to add another constraint to a type.
|
||||
class StaticShapeTensorOf<list<Type> allowedTypes>
|
||||
: Type<And<[TensorOf<allowedTypes>.predicate, HasStaticShapePred]>,
|
||||
"statically shaped " # TensorOf<allowedTypes>.description,
|
||||
"statically shaped " # TensorOf<allowedTypes>.summary,
|
||||
"::mlir::TensorType">;
|
||||
|
||||
def AnyStaticShapeTensor : StaticShapeTensorOf<[AnyType]>;
|
||||
|
@ -633,7 +631,7 @@ def F64Tensor : TensorOf<[F64]>;
|
|||
class TensorRankOf<list<Type> allowedTypes, list<int> ranks> :
|
||||
Type<And<[TensorOf<allowedTypes>.predicate, HasAnyRankOfPred<ranks>]>,
|
||||
!interleave(!foreach(rank, ranks, rank # "D"), "/") # " " #
|
||||
TensorOf<allowedTypes>.description, "::mlir::TensorType">;
|
||||
TensorOf<allowedTypes>.summary, "::mlir::TensorType">;
|
||||
|
||||
class 0DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [0]>;
|
||||
class 1DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [1]>;
|
||||
|
@ -674,11 +672,11 @@ def F64MemRef : MemRefOf<[F64]>;
|
|||
class MemRefRankOf<list<Type> allowedTypes, list<int> ranks> :
|
||||
Type<And<[MemRefOf<allowedTypes>.predicate, HasAnyRankOfPred<ranks>]>,
|
||||
!interleave(!foreach(rank, ranks, rank # "D"), "/") # " " #
|
||||
MemRefOf<allowedTypes>.description>;
|
||||
MemRefOf<allowedTypes>.summary>;
|
||||
|
||||
class StaticShapeMemRefOf<list<Type> allowedTypes>
|
||||
: Type<And<[MemRefOf<allowedTypes>.predicate, HasStaticShapePred]>,
|
||||
"statically shaped " # MemRefOf<allowedTypes>.description>;
|
||||
"statically shaped " # MemRefOf<allowedTypes>.summary>;
|
||||
|
||||
def AnyStaticShapeMemRef : StaticShapeMemRefOf<[AnyType]>;
|
||||
|
||||
|
@ -687,19 +685,19 @@ def HasStridesPred : CPred<[{ isStrided($_self.cast<::mlir::MemRefType>()) }]>;
|
|||
|
||||
class StridedMemRefOf<list<Type> allowedTypes>
|
||||
: Type<And<[MemRefOf<allowedTypes>.predicate, HasStridesPred]>,
|
||||
"strided " # MemRefOf<allowedTypes>.description>;
|
||||
"strided " # MemRefOf<allowedTypes>.summary>;
|
||||
|
||||
def AnyStridedMemRef : StridedMemRefOf<[AnyType]>;
|
||||
|
||||
class AnyStridedMemRefOfRank<int rank> :
|
||||
Type<And<[AnyStridedMemRef.predicate,
|
||||
MemRefRankOf<[AnyType], [rank]>.predicate]>,
|
||||
AnyStridedMemRef.description # " of rank " # rank>;
|
||||
AnyStridedMemRef.summary # " of rank " # rank>;
|
||||
|
||||
class StridedMemRefRankOf<list<Type> allowedTypes, list<int> ranks> :
|
||||
Type<And<[MemRefOf<allowedTypes>.predicate, HasAnyRankOfPred<ranks>]>,
|
||||
!interleave(!foreach(rank, ranks, rank # "D"), "/") # " " #
|
||||
MemRefOf<allowedTypes>.description>;
|
||||
MemRefOf<allowedTypes>.summary>;
|
||||
|
||||
// This represents a generic tuple without any constraints on element type.
|
||||
def AnyTuple : Type<IsTupleTypePred, "tuple", "::mlir::TupleType">;
|
||||
|
@ -718,7 +716,7 @@ class MixedContainerType<Type etype, Pred containerPred, code elementTypesCall,
|
|||
"; })"
|
||||
>
|
||||
]>,
|
||||
descr # " with any combination of " # etype.description # " values"> {
|
||||
descr # " with any combination of " # etype.summary # " values"> {
|
||||
// The type of elements in the container.
|
||||
Type elementType = etype;
|
||||
|
||||
|
@ -838,7 +836,7 @@ class DialectAttr<Dialect d, Pred condition, string descr = ""> :
|
|||
|
||||
// Decorates an attribute to have an (unvalidated) default value if not present.
|
||||
class DefaultValuedAttr<Attr attr, string val> :
|
||||
Attr<attr.predicate, attr.description> {
|
||||
Attr<attr.predicate, attr.summary> {
|
||||
// Construct this attribute with the input attribute and change only
|
||||
// the default value.
|
||||
// Note: this has to be kept up to date with Attr above.
|
||||
|
@ -854,7 +852,7 @@ class DefaultValuedAttr<Attr attr, string val> :
|
|||
|
||||
// Decorates an attribute as optional. The return type of the generated
|
||||
// attribute accessor method will be Optional<>.
|
||||
class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.description> {
|
||||
class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.summary> {
|
||||
// Rewrite the attribute to be optional.
|
||||
// Note: this has to be kept up to date with Attr above.
|
||||
let storageType = attr.storageType;
|
||||
|
@ -1057,12 +1055,12 @@ class TypedStrAttr<Type ty>
|
|||
// Base class for attributes containing types. Example:
|
||||
// def IntTypeAttr : TypeAttrBase<"IntegerType", "integer type attribute">
|
||||
// defines a type attribute containing an integer type.
|
||||
class TypeAttrBase<string retType, string description> :
|
||||
class TypeAttrBase<string retType, string summary> :
|
||||
Attr<And<[
|
||||
CPred<"$_self.isa<::mlir::TypeAttr>()">,
|
||||
CPred<"$_self.cast<::mlir::TypeAttr>().getValue().isa<"
|
||||
# retType # ">()">]>,
|
||||
description> {
|
||||
summary> {
|
||||
let storageType = [{ ::mlir::TypeAttr }];
|
||||
let returnType = retType;
|
||||
let valueType = NoneType;
|
||||
|
@ -1188,43 +1186,42 @@ class EnumAttrInfo<string name, list<EnumAttrCaseInfo> cases> {
|
|||
// Op attributes of this kind are stored as StringAttr. Extra verification will
|
||||
// be generated on the string though: only the symbols of the allowed cases are
|
||||
// permitted as the string value.
|
||||
class StrEnumAttr<string name, string description,
|
||||
list<StrEnumAttrCase> cases> :
|
||||
EnumAttrInfo<name, cases>,
|
||||
class StrEnumAttr<string name, string summary, list<StrEnumAttrCase> cases>
|
||||
: EnumAttrInfo<name, cases>,
|
||||
StringBasedAttr<
|
||||
And<[StrAttr.predicate, Or<!foreach(case, cases, case.predicate)>]>,
|
||||
!if(!empty(description), "allowed string cases: " #
|
||||
!if(!empty(summary), "allowed string cases: " #
|
||||
!interleave(!foreach(case, cases, "'" # case.symbol # "'"), ", "),
|
||||
description)>;
|
||||
summary)>;
|
||||
|
||||
// An enum attribute backed by IntegerAttr.
|
||||
//
|
||||
// Op attributes of this kind are stored as IntegerAttr. Extra verification will
|
||||
// be generated on the integer though: only the values of the allowed cases are
|
||||
// permitted as the integer value.
|
||||
class IntEnumAttr<I intType, string name, string description,
|
||||
class IntEnumAttr<I intType, string name, string summary,
|
||||
list<IntEnumAttrCaseBase> cases> :
|
||||
EnumAttrInfo<name, cases>,
|
||||
SignlessIntegerAttrBase<intType,
|
||||
!if(!empty(description), "allowed " # intType.description # " cases: " #
|
||||
!interleave(!foreach(case, cases, case.value), ", "), description)> {
|
||||
!if(!empty(summary), "allowed " # intType.summary # " cases: " #
|
||||
!interleave(!foreach(case, cases, case.value), ", "), summary)> {
|
||||
let predicate = And<[
|
||||
SignlessIntegerAttrBase<intType, "">.predicate,
|
||||
Or<!foreach(case, cases, case.predicate)>]>;
|
||||
}
|
||||
|
||||
class I32EnumAttr<string name, string description,
|
||||
class I32EnumAttr<string name, string summary,
|
||||
list<I32EnumAttrCase> cases> :
|
||||
IntEnumAttr<I32, name, description, cases> {
|
||||
IntEnumAttr<I32, name, summary, cases> {
|
||||
let returnType = cppNamespace # "::" # name;
|
||||
let underlyingType = "uint32_t";
|
||||
let convertFromStorage = "static_cast<" # returnType # ">($_self.getInt())";
|
||||
let constBuilderCall =
|
||||
"$_builder.getI32IntegerAttr(static_cast<int32_t>($0))";
|
||||
}
|
||||
class I64EnumAttr<string name, string description,
|
||||
class I64EnumAttr<string name, string summary,
|
||||
list<I64EnumAttrCase> cases> :
|
||||
IntEnumAttr<I64, name, description, cases> {
|
||||
IntEnumAttr<I64, name, summary, cases> {
|
||||
let returnType = cppNamespace # "::" # name;
|
||||
let underlyingType = "uint64_t";
|
||||
let convertFromStorage = "static_cast<" # returnType # ">($_self.getInt())";
|
||||
|
@ -1238,9 +1235,9 @@ class I64EnumAttr<string name, string description,
|
|||
// be generated on the integer to make sure only allowed bit are set. Besides,
|
||||
// helper methods are generated to parse a string separated with a specified
|
||||
// delimiter to a symbol and vice versa.
|
||||
class BitEnumAttr<string name, string description,
|
||||
class BitEnumAttr<string name, string summary,
|
||||
list<BitEnumAttrCase> cases> :
|
||||
EnumAttrInfo<name, cases>, SignlessIntegerAttrBase<I32, description> {
|
||||
EnumAttrInfo<name, cases>, SignlessIntegerAttrBase<I32, summary> {
|
||||
let predicate = And<[
|
||||
I32Attr.predicate,
|
||||
// Make sure we don't have unknown bit set.
|
||||
|
@ -1266,8 +1263,8 @@ class BitEnumAttr<string name, string description,
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Composite attribute kinds
|
||||
|
||||
class DictionaryAttrBase<Pred condition, string description> :
|
||||
Attr<condition, description> {
|
||||
class DictionaryAttrBase<Pred condition, string summary> :
|
||||
Attr<condition, summary> {
|
||||
let storageType = [{ ::mlir::DictionaryAttr }];
|
||||
let returnType = [{ ::mlir::DictionaryAttr }];
|
||||
let valueType = NoneType;
|
||||
|
@ -1278,8 +1275,8 @@ def DictionaryAttr
|
|||
: DictionaryAttrBase<CPred<"$_self.isa<::mlir::DictionaryAttr>()">,
|
||||
"dictionary of named attribute values">;
|
||||
|
||||
class ElementsAttrBase<Pred condition, string description> :
|
||||
Attr<condition, description> {
|
||||
class ElementsAttrBase<Pred condition, string summary> :
|
||||
Attr<condition, summary> {
|
||||
let storageType = [{ ::mlir::ElementsAttr }];
|
||||
let returnType = [{ ::mlir::ElementsAttr }];
|
||||
let convertFromStorage = "$_self";
|
||||
|
@ -1288,10 +1285,10 @@ class ElementsAttrBase<Pred condition, string description> :
|
|||
def ElementsAttr : ElementsAttrBase<CPred<"$_self.isa<::mlir::ElementsAttr>()">,
|
||||
"constant vector/tensor attribute">;
|
||||
|
||||
class IntElementsAttrBase<Pred condition, string description> :
|
||||
class IntElementsAttrBase<Pred condition, string summary> :
|
||||
ElementsAttrBase<And<[CPred<"$_self.isa<::mlir::DenseIntElementsAttr>()">,
|
||||
condition]>,
|
||||
description> {
|
||||
summary> {
|
||||
let storageType = [{ ::mlir::DenseIntElementsAttr }];
|
||||
let returnType = [{ ::mlir::DenseIntElementsAttr }];
|
||||
|
||||
|
@ -1338,8 +1335,8 @@ class RankedSignlessIntElementsAttr<int width, list<int> dims> :
|
|||
CPred<"$_self.cast<::mlir::DenseIntElementsAttr>().getType().getShape() == "
|
||||
"::mlir::ArrayRef<int64_t>({" # !interleave(dims, ", ") # "})">]>;
|
||||
|
||||
let description = width # "-bit signless int elements attribute of shape [" #
|
||||
!interleave(dims, ", ") # "]";
|
||||
let summary = width # "-bit signless int elements attribute of shape [" #
|
||||
!interleave(dims, ", ") # "]";
|
||||
|
||||
let constBuilderCall = "::mlir::DenseIntElementsAttr::get("
|
||||
"::mlir::RankedTensorType::get({" # !interleave(dims, ", ") #
|
||||
|
@ -1415,8 +1412,7 @@ CPred<"$_self.isa<::mlir::AffineMapAttr>()">, "AffineMap attribute"> {
|
|||
}
|
||||
|
||||
// Base class for array attributes.
|
||||
class ArrayAttrBase<Pred condition, string description> :
|
||||
Attr<condition, description> {
|
||||
class ArrayAttrBase<Pred condition, string summary> : Attr<condition, summary> {
|
||||
let storageType = [{ ::mlir::ArrayAttr }];
|
||||
let returnType = [{ ::mlir::ArrayAttr }];
|
||||
let valueType = NoneType;
|
||||
|
@ -1428,7 +1424,7 @@ def ArrayAttr : ArrayAttrBase<CPred<"$_self.isa<::mlir::ArrayAttr>()">,
|
|||
|
||||
// Base class for array attributes whose elements are of the same kind.
|
||||
// `element` specifies the element attribute kind stored in this array.
|
||||
class TypedArrayAttrBase<Attr element, string description>: ArrayAttrBase<
|
||||
class TypedArrayAttrBase<Attr element, string summary>: ArrayAttrBase<
|
||||
And<[
|
||||
// Guarantee this is an ArrayAttr first
|
||||
CPred<"$_self.isa<::mlir::ArrayAttr>()">,
|
||||
|
@ -1437,7 +1433,7 @@ class TypedArrayAttrBase<Attr element, string description>: ArrayAttrBase<
|
|||
"[](::mlir::Attribute attr) { return ",
|
||||
SubstLeaves<"$_self", "attr", element.predicate>,
|
||||
"; })">]>,
|
||||
description> {
|
||||
summary> {
|
||||
let constBuilderCall = "$_builder.getArrayAttr($0)";
|
||||
|
||||
Attr elementAttr = element;
|
||||
|
@ -1597,8 +1593,8 @@ def ConstUnitAttr : ConstantAttr<UnitAttr, "unit">;
|
|||
class Confined<Attr attr, list<AttrConstraint> constraints> : Attr<
|
||||
And<!listconcat([attr.predicate],
|
||||
!foreach(pred, constraints, pred.predicate))>,
|
||||
!foldl(/*init*/attr.description, /*list*/constraints,
|
||||
prev, cur, prev # " " # cur.description)> {
|
||||
!foldl(/*init*/attr.summary, /*list*/constraints,
|
||||
prev, cur, prev # " " # cur.summary)> {
|
||||
let storageType = attr.storageType;
|
||||
let returnType = attr.returnType;
|
||||
let convertFromStorage = attr.convertFromStorage;
|
||||
|
@ -1615,7 +1611,7 @@ class Confined<Attr attr, list<AttrConstraint> constraints> : Attr<
|
|||
class AllAttrConstraintsOf<list<AttrConstraint> constraints> : AttrConstraint<
|
||||
And<!listconcat([!head(constraints).predicate],
|
||||
!foreach(pred, !tail(constraints), pred.predicate))>,
|
||||
!interleave(!foreach(con, constraints, con.description), " and ")> {
|
||||
!interleave(!foreach(con, constraints, con.summary), " and ")> {
|
||||
}
|
||||
|
||||
class IntMinValue<int n> : AttrConstraint<
|
||||
|
@ -1688,7 +1684,7 @@ class SizedRegion<int numBlocks> : Region<
|
|||
|
||||
// A variadic region constraint. It expands to zero or more of the base region.
|
||||
class VariadicRegion<Region region>
|
||||
: Region<region.predicate, region.description>;
|
||||
: Region<region.predicate, region.summary>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Successor definitions
|
||||
|
@ -1703,7 +1699,7 @@ def AnySuccessor : Successor<?, "any successor">;
|
|||
// A variadic successor constraint. It expands to zero or more of the base
|
||||
// successor.
|
||||
class VariadicSuccessor<Successor successor>
|
||||
: Successor<successor.predicate, successor.description>;
|
||||
: Successor<successor.predicate, successor.summary>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpTrait definitions
|
||||
|
@ -1736,7 +1732,7 @@ class GenInternalOpTrait<string prop> : OpTrait {
|
|||
|
||||
// PredOpTrait is an op trait implemented by way of a predicate on the op.
|
||||
class PredOpTrait<string descr, Pred pred> : OpTrait {
|
||||
string description = descr;
|
||||
string summary = descr;
|
||||
Pred predicate = pred;
|
||||
}
|
||||
|
||||
|
@ -2015,8 +2011,8 @@ class OpVariable<Constraint varConstraint, string desc = "",
|
|||
// The constraint, either attribute or type, of the argument.
|
||||
Constraint constraint = varConstraint;
|
||||
|
||||
// A description for the argument.
|
||||
string description = desc;
|
||||
// One-line human-readable description of the argument.
|
||||
string summary = desc;
|
||||
|
||||
// The list of decorators for this variable, e.g. side effects.
|
||||
list<OpVariableDecorator> decorators = varDecorators;
|
||||
|
@ -2161,17 +2157,17 @@ class AllMatchPred<list<string> values> :
|
|||
CPred<"::llvm::is_splat(::llvm::makeArrayRef({"
|
||||
# !interleave(values, ", ") #"}))">;
|
||||
|
||||
class AllMatch<list<string> values, string description> :
|
||||
PredOpTrait<description, AllMatchPred<values>>;
|
||||
class AllMatch<list<string> values, string summary> :
|
||||
PredOpTrait<summary, AllMatchPred<values>>;
|
||||
|
||||
// TODO: Only works for non-variadic.
|
||||
class AllMatchSameOperatorPred<list<string> names, string operator> :
|
||||
AllMatchPred<!foreach(n, names, !subst("$_self", "$" # n, operator))>;
|
||||
|
||||
class AllMatchSameOperatorTrait<list<string> names, string operator,
|
||||
string description> :
|
||||
string summary> :
|
||||
PredOpTrait<
|
||||
"all of {" # !interleave(names, ", ") # "} have same " # description,
|
||||
"all of {" # !interleave(names, ", ") # "} have same " # summary,
|
||||
AllMatchSameOperatorPred<names, operator>> {
|
||||
list<string> values = names;
|
||||
}
|
||||
|
@ -2194,9 +2190,9 @@ class AllTypesMatch<list<string> names> :
|
|||
AllMatchSameOperatorTrait<names, "$_self.getType()", "type">;
|
||||
|
||||
// A type constraint that denotes `transform(lhs.getType()) == rhs.getType()`.
|
||||
class TypesMatchWith<string description, string lhsArg, string rhsArg,
|
||||
class TypesMatchWith<string summary, string lhsArg, string rhsArg,
|
||||
string transform> :
|
||||
PredOpTrait<description, CPred<
|
||||
PredOpTrait<summary, CPred<
|
||||
!subst("$_self", "$" # lhsArg # ".getType()", transform)
|
||||
# " == $" # rhsArg # ".getType()">> {
|
||||
string lhs = lhsArg;
|
||||
|
@ -2217,7 +2213,7 @@ class TCopVTEtIs<int idx, Type type> : And<[
|
|||
class TypeIsPred<string name, Type type> :
|
||||
SubstLeaves<"$_self", "$" # name # ".getType()", type.predicate>;
|
||||
class TypeIs<string name, Type type> : PredOpTrait<
|
||||
"'" # name # "' is " # type.description, TypeIsPred<name, type>>;
|
||||
"'" # name # "' is " # type.summary, TypeIsPred<name, type>>;
|
||||
|
||||
// Predicate to verify that a named argument or result's element type matches a
|
||||
// given type.
|
||||
|
@ -2226,7 +2222,7 @@ class ElementTypeIsPred<string name, Type type> : And<[
|
|||
SubstLeaves<"$_self", "getElementTypeOrSelf($" # name # ")",
|
||||
type.predicate>]>;
|
||||
class ElementTypeIs<string name, Type type> : PredOpTrait<
|
||||
"'" # name # "' is " # type.description, ElementTypeIsPred<name, type>>;
|
||||
"'" # name # "' is " # type.summary, ElementTypeIsPred<name, type>>;
|
||||
|
||||
// Predicate to verify that the i'th operand and the j'th operand have the same
|
||||
// elemental type.
|
||||
|
@ -2441,8 +2437,8 @@ class TypeDef<Dialect dialect, string name,
|
|||
// The name of the C++ base class to use for this Type.
|
||||
string cppBaseClassName = baseCppClass;
|
||||
|
||||
// Short summary of the type.
|
||||
string summary = ?;
|
||||
// Additional, longer human-readable description of what the op does.
|
||||
string description = "";
|
||||
|
||||
// Name of storage class to generate or use.
|
||||
string storageClass = name # "TypeStorage";
|
||||
|
@ -2514,8 +2510,8 @@ class TypeParameter<string type, string desc> {
|
|||
code allocator = ?;
|
||||
// The C++ type of this parameter.
|
||||
string cppType = type;
|
||||
// A description of this parameter.
|
||||
string description = desc;
|
||||
// One-line human-readable description of the argument.
|
||||
string summary = desc;
|
||||
// The format string for the asm syntax (documentation only).
|
||||
string syntax = ?;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
|
||||
// Returns the user-readable description of this constraint. If the
|
||||
// description is not provided, returns the TableGen def name.
|
||||
StringRef getDescription() const;
|
||||
StringRef getSummary() const;
|
||||
|
||||
// Constraint kind
|
||||
enum Kind { CK_Attr, CK_Region, CK_Successor, CK_Type, CK_Uncategorized };
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
std::string getPredTemplate() const;
|
||||
|
||||
// Returns the description of what the predicate is verifying.
|
||||
StringRef getDescription() const;
|
||||
StringRef getSummary() const;
|
||||
|
||||
static bool classof(const OpTrait *t) { return t->getKind() == Kind::Pred; }
|
||||
};
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
explicit Type(const llvm::Record *record);
|
||||
|
||||
// Returns the description of the type.
|
||||
StringRef getTypeDescription() const;
|
||||
StringRef getDescription() const;
|
||||
|
||||
// Returns the dialect for the type if defined.
|
||||
Dialect getDialect() const;
|
||||
|
|
|
@ -119,11 +119,11 @@ public:
|
|||
// Get the parameter name.
|
||||
StringRef getName() const;
|
||||
// If specified, get the custom allocator code for this parameter.
|
||||
llvm::Optional<StringRef> getAllocator() const;
|
||||
Optional<StringRef> getAllocator() const;
|
||||
// Get the C++ type of this parameter.
|
||||
StringRef getCppType() const;
|
||||
// Get a description of this parameter for documentation purposes.
|
||||
llvm::Optional<StringRef> getDescription() const;
|
||||
Optional<StringRef> getSummary() const;
|
||||
// Get the assembly syntax documentation.
|
||||
StringRef getSyntax() const;
|
||||
|
||||
|
|
|
@ -57,17 +57,9 @@ std::string Constraint::getConditionTemplate() const {
|
|||
return getPredicate().getCondition();
|
||||
}
|
||||
|
||||
StringRef Constraint::getDescription() const {
|
||||
// If a summary is found, we use that given that it is a focused single line
|
||||
// comment.
|
||||
StringRef Constraint::getSummary() const {
|
||||
if (Optional<StringRef> summary = def->getValueAsOptionalString("summary"))
|
||||
return *summary;
|
||||
// If a summary can't be found, look for a specific description field to use
|
||||
// for the constraint.
|
||||
StringRef desc = def->getValueAsString("description");
|
||||
if (!desc.empty())
|
||||
return desc;
|
||||
// Otherwise, fallback to the name of the constraint definition.
|
||||
return def->getName();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ std::string PredOpTrait::getPredTemplate() const {
|
|||
return pred.getCondition();
|
||||
}
|
||||
|
||||
llvm::StringRef PredOpTrait::getDescription() const {
|
||||
return def->getValueAsString("description");
|
||||
llvm::StringRef PredOpTrait::getSummary() const {
|
||||
return def->getValueAsString("summary");
|
||||
}
|
||||
|
||||
OpInterface InterfaceOpTrait::getOpInterface() const {
|
||||
|
|
|
@ -60,8 +60,8 @@ StringRef TypeConstraint::getCPPClassName() const {
|
|||
|
||||
Type::Type(const llvm::Record *record) : TypeConstraint(record) {}
|
||||
|
||||
StringRef Type::getTypeDescription() const {
|
||||
return def->getValueAsString("typeDescription");
|
||||
StringRef Type::getDescription() const {
|
||||
return def->getValueAsString("description");
|
||||
}
|
||||
|
||||
Dialect Type::getDialect() const {
|
||||
|
|
|
@ -109,7 +109,7 @@ bool TypeDef::operator<(const TypeDef &other) const {
|
|||
StringRef TypeParameter::getName() const {
|
||||
return def->getArgName(num)->getValue();
|
||||
}
|
||||
llvm::Optional<StringRef> TypeParameter::getAllocator() const {
|
||||
Optional<StringRef> TypeParameter::getAllocator() const {
|
||||
llvm::Init *parameterType = def->getArg(num);
|
||||
if (isa<llvm::StringInit>(parameterType))
|
||||
return llvm::Optional<StringRef>();
|
||||
|
@ -142,14 +142,14 @@ StringRef TypeParameter::getCppType() const {
|
|||
"Parameters DAG arguments must be either strings or defs "
|
||||
"which inherit from TypeParameter\n");
|
||||
}
|
||||
llvm::Optional<StringRef> TypeParameter::getDescription() const {
|
||||
Optional<StringRef> TypeParameter::getSummary() const {
|
||||
auto *parameterType = def->getArg(num);
|
||||
if (auto *typeParameter = dyn_cast<llvm::DefInit>(parameterType)) {
|
||||
const auto *desc = typeParameter->getDef()->getValue("description");
|
||||
if (llvm::StringInit *ci = dyn_cast<llvm::StringInit>(desc->getValue()))
|
||||
return ci->getValue();
|
||||
}
|
||||
return llvm::Optional<StringRef>();
|
||||
return Optional<StringRef>();
|
||||
}
|
||||
StringRef TypeParameter::getSyntax() const {
|
||||
auto *parameterType = def->getArg(num);
|
||||
|
|
|
@ -290,7 +290,7 @@ def Test_Dialect_2 : Dialect {
|
|||
}
|
||||
def MyStruct : StructAttr<"MyStruct", Test_Dialect_2,
|
||||
[StructFieldAttr<"potatoes", I64ElementsAttr>]> {
|
||||
let description = "A structure describing a number of potatoes.";
|
||||
let summary = "A structure describing a number of potatoes.";
|
||||
}
|
||||
|
||||
def StructAttrOp : NS_Op<"struct_attr_op", []> {
|
||||
|
|
|
@ -336,7 +336,7 @@ static void emitEnumDecl(const Record &enumDef, raw_ostream &os) {
|
|||
StringRef enumName = enumAttr.getEnumClassName();
|
||||
StringRef cppNamespace = enumAttr.getCppNamespace();
|
||||
std::string underlyingType = std::string(enumAttr.getUnderlyingType());
|
||||
StringRef description = enumAttr.getDescription();
|
||||
StringRef description = enumAttr.getSummary();
|
||||
StringRef strToSymFnName = enumAttr.getStringToSymbolFnName();
|
||||
StringRef symToStrFnName = enumAttr.getSymbolToStringFnName();
|
||||
StringRef symToStrFnRetType = enumAttr.getSymbolToStringFnRetType();
|
||||
|
|
|
@ -248,7 +248,7 @@ void StaticVerifierFunctionEmitter::emitTypeConstraintMethods(
|
|||
<< formatv(
|
||||
" return op->emitOpError(valueKind) << \" #\" << "
|
||||
"valueGroupStartIndex << \" must be {0}, but got \" << type;\n",
|
||||
constraint.getDescription())
|
||||
constraint.getSummary())
|
||||
<< " }\n"
|
||||
<< " return ::mlir::success();\n"
|
||||
<< "}\n\n";
|
||||
|
@ -576,7 +576,7 @@ static void genAttributeVerifier(const Operator &op, const char *attrGet,
|
|||
body << tgfmt(" if (!($0)) return $1\"attribute '$2' "
|
||||
"failed to satisfy constraint: $3\");\n",
|
||||
/*ctx=*/nullptr, tgfmt(condition, &ctx.withSelf(varName)),
|
||||
emitErrorPrefix, attrName, attr.getDescription());
|
||||
emitErrorPrefix, attrName, attr.getSummary());
|
||||
if (allowMissingAttr)
|
||||
body << " }\n";
|
||||
body << " }\n";
|
||||
|
@ -1991,7 +1991,7 @@ void OpEmitter::genVerifier() {
|
|||
body << tgfmt(" if (!($0))\n "
|
||||
"return emitOpError(\"failed to verify that $1\");\n",
|
||||
&verifyCtx, tgfmt(t->getPredTemplate(), &verifyCtx),
|
||||
t->getDescription());
|
||||
t->getSummary());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2086,7 +2086,7 @@ void OpEmitter::genRegionVerifier(OpMethodBody &body) {
|
|||
"verify constraint: {2}\";\n }\n",
|
||||
constraint,
|
||||
region.name.empty() ? "" : "('" + region.name + "') ",
|
||||
region.constraint.getDescription())
|
||||
region.constraint.getSummary())
|
||||
<< " ++index;\n"
|
||||
<< " }\n";
|
||||
}
|
||||
|
@ -2125,7 +2125,7 @@ void OpEmitter::genSuccessorVerifier(OpMethodBody &body) {
|
|||
"failed to "
|
||||
"verify constraint: {2}\";\n }\n",
|
||||
constraint, successor.name,
|
||||
successor.constraint.getDescription())
|
||||
successor.constraint.getSummary())
|
||||
<< " ++index;\n"
|
||||
<< " }\n";
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ static void emitNamedConstraint(const T &it, raw_ostream &os) {
|
|||
os << "`" << it.name << "`";
|
||||
else
|
||||
os << "«unnamed»";
|
||||
os << " | " << it.constraint.getDescription() << "\n";
|
||||
os << " | " << it.constraint.getSummary() << "\n";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -106,7 +106,7 @@ static void emitOpDoc(Operator op, raw_ostream &os) {
|
|||
for (const auto &it : op.getAttributes()) {
|
||||
StringRef storageType = it.attr.getStorageType();
|
||||
os << "`" << it.name << "` | " << storageType << " | "
|
||||
<< it.attr.getDescription() << "\n";
|
||||
<< it.attr.getSummary() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,8 +153,8 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void emitTypeDoc(const Type &type, raw_ostream &os) {
|
||||
os << "### " << type.getDescription() << "\n";
|
||||
emitDescription(type.getTypeDescription(), os);
|
||||
os << "### " << type.getSummary() << "\n";
|
||||
emitDescription(type.getDescription(), os);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
|
@ -198,12 +198,12 @@ static void emitTypeDefDoc(TypeDef td, raw_ostream &os) {
|
|||
// Emit attribute documentation.
|
||||
SmallVector<TypeParameter, 4> parameters;
|
||||
td.getParameters(parameters);
|
||||
if (parameters.size() != 0) {
|
||||
if (!parameters.empty()) {
|
||||
os << "\n#### Type parameters:\n\n";
|
||||
os << "| Parameter | C++ type | Description |\n"
|
||||
<< "| :-------: | :-------: | ----------- |\n";
|
||||
for (const auto &it : parameters) {
|
||||
auto desc = it.getDescription();
|
||||
auto desc = it.getSummary();
|
||||
os << "| " << it.getName() << " | `" << td.getCppClassName() << "` | "
|
||||
<< (desc ? *desc : "") << " |\n";
|
||||
}
|
||||
|
|
|
@ -1268,7 +1268,7 @@ void OperationFormat::genParserTypeResolution(Operator &op,
|
|||
<< ")) {\n"
|
||||
<< formatv(" return parser.emitError(parser.getNameLoc()) << "
|
||||
"\"'{0}' must be {1}, but got \" << type;\n",
|
||||
variable->name, constraint.getDescription())
|
||||
variable->name, constraint.getSummary())
|
||||
<< " }\n"
|
||||
<< " }\n";
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ void PatternEmitter::emitNativeCodeMatch(DagNode tree, StringRef opName,
|
|||
formatv("\"operand {0} of native code call '{1}' failed to satisfy "
|
||||
"constraint: "
|
||||
"'{2}'\"",
|
||||
i, tree.getNativeCodeTemplate(), constraint.getDescription()));
|
||||
i, tree.getNativeCodeTemplate(), constraint.getSummary()));
|
||||
}
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "done emitting match for native code call\n");
|
||||
|
@ -425,7 +425,7 @@ void PatternEmitter::emitOperandMatch(DagNode tree, StringRef opName,
|
|||
formatv("\"operand {0} of op '{1}' failed to satisfy constraint: "
|
||||
"'{2}'\"",
|
||||
operand - op.operand_begin(), op.getOperationName(),
|
||||
constraint.getDescription()));
|
||||
constraint.getSummary()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,7 +491,7 @@ void PatternEmitter::emitAttributeMatch(DagNode tree, StringRef opName,
|
|||
formatv("\"op '{0}' attribute '{1}' failed to satisfy constraint: "
|
||||
"{2}\"",
|
||||
op.getOperationName(), namedAttr->name,
|
||||
matcher.getAsConstraint().getDescription()));
|
||||
matcher.getAsConstraint().getSummary()));
|
||||
}
|
||||
|
||||
// Capture the value
|
||||
|
@ -536,7 +536,7 @@ void PatternEmitter::emitMatchLogic(DagNode tree, StringRef opName) {
|
|||
emitMatchCheck(
|
||||
opName, tgfmt(condition, &fmtCtx.withSelf(self.str())),
|
||||
formatv("\"value entity '{0}' failed to satisfy constraint: {1}\"",
|
||||
entities.front(), constraint.getDescription()));
|
||||
entities.front(), constraint.getSummary()));
|
||||
|
||||
} else if (isa<AttrConstraint>(constraint)) {
|
||||
PrintFatalError(
|
||||
|
@ -562,7 +562,7 @@ void PatternEmitter::emitMatchLogic(DagNode tree, StringRef opName) {
|
|||
formatv("\"entities '{0}' failed to satisfy constraint: "
|
||||
"{1}\"",
|
||||
llvm::join(entities, ", "),
|
||||
constraint.getDescription()));
|
||||
constraint.getSummary()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ static void emitStructDecl(const Record &structDef, raw_ostream &os) {
|
|||
StructAttr structAttr(&structDef);
|
||||
StringRef structName = structAttr.getStructClassName();
|
||||
StringRef cppNamespace = structAttr.getCppNamespace();
|
||||
StringRef description = structAttr.getDescription();
|
||||
StringRef description = structAttr.getSummary();
|
||||
auto fields = structAttr.getAllFields();
|
||||
|
||||
// Wrap in the appropriate namespace.
|
||||
|
|
|
@ -20,5 +20,5 @@ def Test_Struct : StructAttr<"TestStruct", Test_Dialect, [
|
|||
OptionalAttr<I32Attr>>,
|
||||
StructFieldAttr<"sample_default_valued_integer",
|
||||
DefaultValuedAttr<I32Attr, "42">>] > {
|
||||
let description = "Structure for test data";
|
||||
let summary = "Structure for test data";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue