[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:
River Riddle 2021-01-06 14:08:03 -08:00
parent 4726bec8f2
commit e0a93e4b65
24 changed files with 261 additions and 272 deletions

View File

@ -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

View File

@ -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

View File

@ -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).

View File

@ -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> :

View File

@ -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 :

View File

@ -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.

View File

@ -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.";
}
//===----------------------------------------------------------------------===//

View File

@ -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 = ?;
}

View File

@ -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 };

View File

@ -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; }
};

View File

@ -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;

View File

@ -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;

View File

@ -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();
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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);

View File

@ -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", []> {

View File

@ -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();

View File

@ -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";
}

View File

@ -58,7 +58,7 @@ static void emitNamedConstraint(const T &it, raw_ostream &os) {
os << "`" << it.name << "`";
else
os << "&laquo;unnamed&raquo;";
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";
}

View File

@ -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";
}

View File

@ -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()));
}
}

View File

@ -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.

View File

@ -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";
}