[Mlir-commits] [mlir] 6f87809 - [MLIR] ODS TypeDef documentation

John Demme llvmlistbot at llvm.org
Sun Oct 18 17:22:35 PDT 2020

Author: John Demme
Date: 2020-10-19T00:22:20Z
New Revision: 6f878096640f49798e9001bc26a70216725a1463

URL: https://github.com/llvm/llvm-project/commit/6f878096640f49798e9001bc26a70216725a1463
DIFF: https://github.com/llvm/llvm-project/commit/6f878096640f49798e9001bc26a70216725a1463.diff

LOG: [MLIR] ODS TypeDef documentation

Adds documentation for the new ODS TypeDef support.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D89440




diff  --git a/mlir/docs/OpDefinitions.md b/mlir/docs/OpDefinitions.md
index 7c5058e04a9b..96c257cef08c 100644
--- a/mlir/docs/OpDefinitions.md
+++ b/mlir/docs/OpDefinitions.md
@@ -1,11 +1,11 @@
 # Operation Definition Specification (ODS)
 In addition to specializing the `mlir::Op` C++ template, MLIR also supports
-defining operations in a table-driven manner. This is achieved via
-[TableGen][TableGen], which is both a generic language and its tooling to
+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
@@ -1412,6 +1412,173 @@ llvm::Optional<MyBitEnum> symbolizeMyBitEnum(uint32_t value) {
+## Type Definitions
+MLIR defines the TypeDef class hierarchy to enable generation of data types
+from their specifications. A type is defined by specializing the TypeDef
+class with concrete contents for all the fields it requires. For example, an
+integer type could be defined as:
+// All of the types will extend this class.
+class Test_Type<string name> : TypeDef<Test_Dialect, name> { }
+// An alternate int type.
+def IntegerType : Test_Type<"TestInteger"> {
+  let mnemonic = "int";
+  let summary = "An integer type with special semantics";
+  let description = [{
+    An alternate integer type. This type 
diff erentiates itself from the
+    standard integer type by not having a SignednessSemantics parameter, just
+    a width.
+  }];
+  let parameters = (ins "unsigned":$width);
+  // We define the printer inline.
+  let printer = [{
+    $_printer << "int<" << getImpl()->width << ">";
+  }];
+  // The parser is defined here also.
+  let parser = [{
+    if (parser.parseLess())
+      return Type();
+    int width;
+    if ($_parser.parseInteger(width))
+      return Type();
+    if ($_parser.parseGreater())
+      return Type();
+    return get(ctxt, width);
+  }];
+### Type name
+The name of the C++ class which gets generated defaults to
+`<classParamName>Type` (e.g. `TestIntegerType` in the above example). This
+can be overridden via the the `cppClassName` field. The field `mnemonic` is
+to specify the asm name for parsing. It is optional and not specifying it
+will imply that no parser or printer methods are attached to this class.
+### Type documentation
+The `summary` and `description` fields exist and are to be used the same way
+as in Operations. Namely, the summary should be a one-liner and `description`
+should be a longer explanation.
+### Type parameters
+The `parameters` field is a list of the types parameters. If no parameters
+are specified (the default), this type is considered a singleton type.
+Parameters are in the `"c++Type":$paramName` format.
+To use C++ types as parameters which need allocation in the storage
+constructor, there are two options:
+- Set `hasCustomStorageConstructor` to generate the TypeStorage class with
+a constructor which is just declared -- no definition -- so you can write it
+- Use the `TypeParameter` tablegen class instead of the "c++Type" string.
+### 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.
+let parameters = (ins
+  "ArrayRef<int>":$dims);
+The default storage constructor blindly copies fields by value. It does not
+know anything about the types. In this case, the ArrayRef<int> requires
+allocation with `dims = allocator.copyInto(dims)`.
+You can specify the necessary constuctor by specializing the `TypeParameter`
+tblgen class:
+class ArrayRefIntParam :
+    TypeParameter<"::llvm::ArrayRef<int>", "Array of ints"> {
+  let allocator = [{$_dst = $_allocator.copyInto($_self);}];
+let parameters = (ins
+  ArrayRefIntParam:$dims);
+The `allocator` code block has the following substitutions:
+- `$_allocator` is the TypeStorageAllocator in which to allocate objects.
+- `$_dst` is the variable in which to place the allocated data.
+MLIR includes several specialized classes for common situations:
+- `StringRefParameter<descriptionOfParam>` for StringRefs.
+- `ArrayRefParameter<arrayOf, descriptionOfParam>` for ArrayRefs of value
+- `SelfAllocationParameter<descriptionOfParam>` for C++ classes which contain
+a method called `allocateInto(StorageAllocator &allocator)` to allocate
+itself into `allocator`.
+- `ArrayRefOfSelfAllocationParameter<arrayOf, descriptionOfParam>` for arrays
+of objects which self-allocate as per the last specialization.
+If we were to use one of these included specializations:
+let parameters = (ins
+  ArrayRefParameter<"int", "The dimensions">:$dims
+### Parsing and printing
+If a mnemonic is specified, the `printer` and `parser` code fields are active.
+The rules for both are:
+- If null, generate just the declaration.
+- If non-null and non-empty, use the code in the definition. The `$_printer`
+or `$_parser` substitutions are valid and should be used.
+- It is an error to have an empty code block.
+For each dialect, two "dispatch" functions will be created: one for parsing
+and one for printing. You should add calls to these in your
+`Dialect::printType` and `Dialect::parseType` methods. They are created in
+the dialect's namespace and their function signatures are:
+Type generatedTypeParser(MLIRContext* ctxt, DialectAsmParser& parser,
+                         StringRef mnemonic);
+LogicalResult generatedTypePrinter(Type type, DialectAsmPrinter& printer);
+The mnemonic, parser, and printer fields are optional. If they're not
+defined, the generated code will not include any parsing or printing code and
+omit the type from the dispatch functions above. In this case, the dialect
+author is responsible for parsing/printing the types in `Dialect::printType`
+and `Dialect::parseType`.
+### Other fields
+- If the `genStorageClass` field is set to 1 (the default) a storage class is
+generated with member variables corresponding to each of the specified
+- If the `genAccessors` field is 1 (the default) accessor methods will be
+generated on the Type class (e.g. `int getWidth() const` in the example
+- If the `genVerifyInvariantsDecl` field is set, a declaration for a method
+`static LogicalResult verifyConstructionInvariants(Location, parameters...)`
+is added to the class as well as a `getChecked(Location, parameters...)`
+method which gets the result of `verifyConstructionInvariants` before calling
+- The `storageClass` field can be used to set the name of the storage class.
+- The `storageNamespace` field is used to set the namespace where the storage
+class should sit. Defaults to "detail".
+- The `extraClassDeclaration` field is used to include extra code in the
+class declaration.
 ## Debugging Tips
 ### Run `mlir-tblgen` to see the generated content


More information about the Mlir-commits mailing list