[Mlir-commits] [mlir] 67d0bc2 - [mlir][doc] Move documentation of extensible dialects

River Riddle llvmlistbot at llvm.org
Mon May 9 16:01:40 PDT 2022


Author: Mathieu Fehr
Date: 2022-05-09T16:01:12-07:00
New Revision: 67d0bc27c0fde04a3e0c7130419eb1b8a5fda7db

URL: https://github.com/llvm/llvm-project/commit/67d0bc27c0fde04a3e0c7130419eb1b8a5fda7db
DIFF: https://github.com/llvm/llvm-project/commit/67d0bc27c0fde04a3e0c7130419eb1b8a5fda7db.diff

LOG: [mlir][doc] Move documentation of extensible dialects

Merge the documentation of the definition of extensible dialects
with the definition of dialects.

Reviewed By: rriddle

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

Added: 
    

Modified: 
    mlir/docs/DefiningDialects.md

Removed: 
    mlir/docs/ExtensibleDialects.md


################################################################################
diff  --git a/mlir/docs/DefiningDialects.md b/mlir/docs/DefiningDialects.md
index 33c13aa31965b..6445b52cb9c6b 100644
--- a/mlir/docs/DefiningDialects.md
+++ b/mlir/docs/DefiningDialects.md
@@ -331,3 +331,369 @@ All new dialects are strongly encouraged to use the `kEmitAccessorPrefix_Prefixe
 the `Raw` form is deprecated and in the process of being removed.
 
 Note: Remove this section when all dialects have been switched to the new accessor form.
+
+## Defining an Extensible dialect
+
+This section documents the design and API of the extensible dialects. Extensible
+dialects are dialects that can be extended with new operations and types defined
+at runtime. This allows for users to define dialects via with meta-programming,
+or from another language, without having to recompile C++ code.
+
+### Defining an extensible dialect
+
+Dialects defined in C++ can be extended with new operations, types, etc., at
+runtime by inheriting from `mlir::ExtensibleDialect` instead of `mlir::Dialect`
+(note that `ExtensibleDialect` inherits from `Dialect`). The `ExtensibleDialect`
+class contains the necessary fields and methods to extend the dialect at
+runtime.
+
+```c++
+class MyDialect : public mlir::ExtensibleDialect {
+    ...
+}
+```
+
+For dialects defined in TableGen, this is done by setting the `isExtensible`
+flag to `1`.
+
+```tablegen
+def Test_Dialect : Dialect {
+  let isExtensible = 1;
+  ...
+}
+```
+
+An extensible `Dialect` can be casted back to `ExtensibleDialect` using
+`llvm::dyn_cast`, or `llvm::cast`:
+
+```c++
+if (auto extensibleDialect = llvm::dyn_cast<ExtensibleDialect>(dialect)) {
+    ...
+}
+```
+
+### Defining an operation at runtime
+
+The `DynamicOpDefinition` class represents the definition of an operation
+defined at runtime. It is created using the `DynamicOpDefinition::get`
+functions. An operation defined at runtime must provide a name, a dialect in
+which the operation will be registered in, an operation verifier. It may also
+optionally define a custom parser and a printer, fold hook, and more.
+
+```c++
+// The operation name, without the dialect name prefix.
+StringRef name = "my_operation_name";
+
+// The dialect defining the operation.
+Dialect* dialect = ctx->getOrLoadDialect<MyDialect>();
+
+// Operation verifier definition.
+AbstractOperation::VerifyInvariantsFn verifyFn = [](Operation* op) {
+    // Logic for the operation verification.
+    ...
+}
+
+// Parser function definition.
+AbstractOperation::ParseAssemblyFn parseFn =
+    [](OpAsmParser &parser, OperationState &state) {
+        // Parse the operation, given that the name is already parsed.
+        ...    
+};
+
+// Printer function
+auto printFn = [](Operation *op, OpAsmPrinter &printer) {
+        printer << op->getName();
+        // Print the operation, given that the name is already printed.
+        ...
+};
+
+// General folder implementation, see AbstractOperation::foldHook for more
+// information.
+auto foldHookFn = [](Operation * op, ArrayRef<Attribute> operands, 
+                                   SmallVectorImpl<OpFoldResult> &result) {
+    ...
+};
+
+// Returns any canonicalization pattern rewrites that the operation
+// supports, for use by the canonicalization pass.
+auto getCanonicalizationPatterns = 
+        [](RewritePatternSet &results, MLIRContext *context) {
+    ...
+}
+
+// Definition of the operation.
+std::unique_ptr<DynamicOpDefinition> opDef =
+    DynamicOpDefinition::get(name, dialect, std::move(verifyFn),
+        std::move(parseFn), std::move(printFn), std::move(foldHookFn),
+        std::move(getCanonicalizationPatterns));
+```
+
+Once the operation is defined, it can be registered by an `ExtensibleDialect`:
+
+```c++
+extensibleDialect->registerDynamicOperation(std::move(opDef));
+```
+
+Note that the `Dialect` given to the operation should be the one registering
+the operation.
+
+### Using an operation defined at runtime
+
+It is possible to match on an operation defined at runtime using their names:
+
+```c++
+if (op->getName().getStringRef() == "my_dialect.my_dynamic_op") {
+    ...
+}
+```
+
+An operation defined at runtime can be created by instantiating an
+`OperationState` with the operation name, and using it with a rewriter
+(for instance a `PatternRewriter`) to create the operation.
+
+```c++
+OperationState state(location, "my_dialect.my_dynamic_op",
+                     operands, resultTypes, attributes);
+
+rewriter.createOperation(state);
+```
+
+
+### Defining a type at runtime
+
+Contrary to types defined in C++ or in TableGen, types defined at runtime can
+only have as argument a list of `Attribute`.
+
+Similarily to operations, a type is defined at runtime using the class
+`DynamicTypeDefinition`, which is created using the `DynamicTypeDefinition::get`
+functions. A type definition requires a name, the dialect that will register the
+type, and a parameter verifier. It can also define optionally a custom parser
+and printer for the arguments (the type name is assumed to be already
+parsed/printed).
+
+```c++
+// The type name, without the dialect name prefix.
+StringRef name = "my_type_name";
+
+// The dialect defining the type.
+Dialect* dialect = ctx->getOrLoadDialect<MyDialect>();
+
+// The type verifier.
+// A type defined at runtime has a list of attributes as parameters.
+auto verifier = [](function_ref<InFlightDiagnostic()> emitError,
+                   ArrayRef<Attribute> args) {
+    ...
+};
+
+// The type parameters parser.
+auto parser = [](DialectAsmParser &parser,
+                 llvm::SmallVectorImpl<Attribute> &parsedParams) {
+    ...
+};
+
+// The type parameters printer.
+auto printer =[](DialectAsmPrinter &printer, ArrayRef<Attribute> params) {
+    ...
+};
+
+std::unique_ptr<DynamicTypeDefinition> typeDef =
+    DynamicTypeDefinition::get(std::move(name), std::move(dialect),
+                               std::move(verifier), std::move(printer),
+                               std::move(parser));
+```
+
+If the printer and the parser are ommited, a default parser and printer is
+generated with the format `!dialect.typename<arg1, arg2, ..., argN>`.
+
+The type can then be registered by the `ExtensibleDialect`:
+
+```c++
+dialect->registerDynamicType(std::move(typeDef));
+```
+
+### Parsing types defined at runtime in an extensible dialect
+
+`parseType` methods generated by TableGen can parse types defined at runtime,
+though overriden `parseType` methods need to add the necessary support for them.
+
+```c++
+Type MyDialect::parseType(DialectAsmParser &parser) const {
+    ...
+    
+    // The type name.
+    StringRef typeTag;
+    if (failed(parser.parseKeyword(&typeTag)))
+        return Type();
+
+    // Try to parse a dynamic type with 'typeTag' name.
+    Type dynType;
+    auto parseResult = parseOptionalDynamicType(typeTag, parser, dynType);
+    if (parseResult.hasValue()) {
+        if (succeeded(parseResult.getValue()))
+            return dynType;
+         return Type();
+    }
+    
+    ...
+}
+```
+
+### Using a type defined at runtime
+
+Dynamic types are instances of `DynamicType`. It is possible to get a dynamic
+type with `DynamicType::get` and `ExtensibleDialect::lookupTypeDefinition`.
+
+```c++
+auto typeDef = extensibleDialect->lookupTypeDefinition("my_dynamic_type");
+ArrayRef<Attribute> params = ...;
+auto type = DynamicType::get(typeDef, params);
+```
+
+It is also possible to cast a `Type` known to be defined at runtime to a
+`DynamicType`.
+
+```c++
+auto dynType = type.cast<DynamicType>();
+auto typeDef = dynType.getTypeDef();
+auto args = dynType.getParams();
+```
+
+### Defining an attribute at runtime
+
+Similar to types defined at runtime, attributes defined at runtime can only have
+as argument a list of `Attribute`.
+
+Similarily to types, an attribute is defined at runtime using the class
+`DynamicAttrDefinition`, which is created using the `DynamicAttrDefinition::get`
+functions. An attribute definition requires a name, the dialect that will
+register the attribute, and a parameter verifier. It can also define optionally
+a custom parser and printer for the arguments (the attribute name is assumed to
+be already parsed/printed).
+
+```c++
+// The attribute name, without the dialect name prefix.
+StringRef name = "my_attribute_name";
+
+// The dialect defining the attribute.
+Dialect* dialect = ctx->getOrLoadDialect<MyDialect>();
+
+// The attribute verifier.
+// An attribute defined at runtime has a list of attributes as parameters.
+auto verifier = [](function_ref<InFlightDiagnostic()> emitError,
+                   ArrayRef<Attribute> args) {
+    ...
+};
+
+// The attribute parameters parser.
+auto parser = [](DialectAsmParser &parser,
+                 llvm::SmallVectorImpl<Attribute> &parsedParams) {
+    ...
+};
+
+// The attribute parameters printer.
+auto printer =[](DialectAsmPrinter &printer, ArrayRef<Attribute> params) {
+    ...
+};
+
+std::unique_ptr<DynamicAttrDefinition> attrDef =
+    DynamicAttrDefinition::get(std::move(name), std::move(dialect),
+                               std::move(verifier), std::move(printer),
+                               std::move(parser));
+```
+
+If the printer and the parser are ommited, a default parser and printer is
+generated with the format `!dialect.attrname<arg1, arg2, ..., argN>`.
+
+The attribute can then be registered by the `ExtensibleDialect`:
+
+```c++
+dialect->registerDynamicAttr(std::move(typeDef));
+```
+
+### Parsing attributes defined at runtime in an extensible dialect
+
+`parseAttribute` methods generated by TableGen can parse attributes defined at
+runtime, though overriden `parseAttribute` methods need to add the necessary
+support for them.
+
+```c++
+Attribute MyDialect::parseAttribute(DialectAsmParser &parser,
+                                    Type type) const override {
+    ...
+    // The attribute name.
+    StringRef attrTag;
+    if (failed(parser.parseKeyword(&attrTag)))
+        return Attribute();
+
+    // Try to parse a dynamic attribute with 'attrTag' name.
+    Attribute dynAttr;
+    auto parseResult = parseOptionalDynamicAttr(attrTag, parser, dynAttr);
+    if (parseResult.hasValue()) {
+        if (succeeded(parseResult.getValue()))
+            return dynAttr;
+         return Attribute();
+    }
+```
+
+### Using an attribute defined at runtime
+
+Similar to types, attributes defined at runtime are instances of `DynamicAttr`.
+It is possible to get a dynamic attribute with `DynamicAttr::get` and
+`ExtensibleDialect::lookupAttrDefinition`.
+
+```c++
+auto attrDef = extensibleDialect->lookupAttrDefinition("my_dynamic_attr");
+ArrayRef<Attribute> params = ...;
+auto attr = DynamicAttr::get(attrDef, params);
+```
+
+It is also possible to cast an `Attribute` known to be defined at runtime to a
+`DynamicAttr`.
+
+```c++
+auto dynAttr = attr.cast<DynamicAttr>();
+auto attrDef = dynAttr.getAttrDef();
+auto args = dynAttr.getParams();
+```
+
+### Implementation Details of Extensible Dialects
+
+#### Extensible dialect
+
+The role of extensible dialects is to own the necessary data for defined
+operations and types. They also contain the necessary accessors to easily
+access them.
+
+In order to cast a `Dialect` back to an `ExtensibleDialect`, we implement the
+`IsExtensibleDialect` interface to all `ExtensibleDialect`. The casting is done
+by checking if the `Dialect` implements `IsExtensibleDialect` or not.
+
+#### Operation representation and registration
+
+Operations are represented in mlir using the `AbstractOperation` class. They are
+registered in dialects the same way operations defined in C++ are registered,
+which is by calling `AbstractOperation::insert`.
+
+The only 
diff erence is that a new `TypeID` needs to be created for each
+operation, since operations are not represented by a C++ class. This is done
+using a `TypeIDAllocator`, which can allocate a new unique `TypeID` at runtime.
+
+#### Type representation and registration
+
+Unlike operations, types need to define a C++ storage class that takes care of
+type parameters. They also need to define another C++ class to access that
+storage. `DynamicTypeStorage` defines the storage of types defined at runtime,
+and `DynamicType` gives access to the storage, as well as defining useful
+functions. A `DynamicTypeStorage` contains a list of `Attribute` type
+parameters, as well as a pointer to the type definition.
+
+Types are registered using the `Dialect::addType` method, which expect a
+`TypeID` that is generated using a `TypeIDAllocator`. The type uniquer also
+register the type with the given `TypeID`. This mean that we can reuse our
+single `DynamicType` with 
diff erent `TypeID` to represent the 
diff erent types
+defined at runtime.
+
+Since the 
diff erent types defined at runtime have 
diff erent `TypeID`, it is not
+possible to use `TypeID` to cast a `Type` into a `DynamicType`. Thus, similar to
+`Dialect`, all `DynamicType` define a `IsDynamicTypeTrait`, so casting a `Type`
+to a `DynamicType` boils down to querying the `IsDynamicTypeTrait` trait.

diff  --git a/mlir/docs/ExtensibleDialects.md b/mlir/docs/ExtensibleDialects.md
deleted file mode 100644
index e46e4061924b7..0000000000000
--- a/mlir/docs/ExtensibleDialects.md
+++ /dev/null
@@ -1,369 +0,0 @@
-# Extensible dialects
-
-This file documents the design and API of the extensible dialects. Extensible
-dialects are dialects that can be extended with new operations and types defined
-at runtime. This allows for users to define dialects via with meta-programming,
-or from another language, without having to recompile C++ code.
-
-[TOC]
-
-## Usage
-
-### Defining an extensible dialect
-
-Dialects defined in C++ can be extended with new operations, types, etc., at
-runtime by inheriting from `mlir::ExtensibleDialect` instead of `mlir::Dialect`
-(note that `ExtensibleDialect` inherits from `Dialect`). The `ExtensibleDialect`
-class contains the necessary fields and methods to extend the dialect at
-runtime.
-
-```c++
-class MyDialect : public mlir::ExtensibleDialect {
-    ...
-}
-```
-
-For dialects defined in TableGen, this is done by setting the `isExtensible`
-flag to `1`.
-
-```tablegen
-def Test_Dialect : Dialect {
-  let isExtensible = 1;
-  ...
-}
-```
-
-An extensible `Dialect` can be casted back to `ExtensibleDialect` using
-`llvm::dyn_cast`, or `llvm::cast`:
-
-```c++
-if (auto extensibleDialect = llvm::dyn_cast<ExtensibleDialect>(dialect)) {
-    ...
-}
-```
-
-### Defining an operation at runtime
-
-The `DynamicOpDefinition` class represents the definition of an operation
-defined at runtime. It is created using the `DynamicOpDefinition::get`
-functions. An operation defined at runtime must provide a name, a dialect in
-which the operation will be registered in, an operation verifier. It may also
-optionally define a custom parser and a printer, fold hook, and more.
-
-```c++
-// The operation name, without the dialect name prefix.
-StringRef name = "my_operation_name";
-
-// The dialect defining the operation.
-Dialect* dialect = ctx->getOrLoadDialect<MyDialect>();
-
-// Operation verifier definition.
-AbstractOperation::VerifyInvariantsFn verifyFn = [](Operation* op) {
-    // Logic for the operation verification.
-    ...
-}
-
-// Parser function definition.
-AbstractOperation::ParseAssemblyFn parseFn =
-    [](OpAsmParser &parser, OperationState &state) {
-        // Parse the operation, given that the name is already parsed.
-        ...    
-};
-
-// Printer function
-auto printFn = [](Operation *op, OpAsmPrinter &printer) {
-        printer << op->getName();
-        // Print the operation, given that the name is already printed.
-        ...
-};
-
-// General folder implementation, see AbstractOperation::foldHook for more
-// information.
-auto foldHookFn = [](Operation * op, ArrayRef<Attribute> operands, 
-                                   SmallVectorImpl<OpFoldResult> &result) {
-    ...
-};
-
-// Returns any canonicalization pattern rewrites that the operation
-// supports, for use by the canonicalization pass.
-auto getCanonicalizationPatterns = 
-        [](RewritePatternSet &results, MLIRContext *context) {
-    ...
-}
-
-// Definition of the operation.
-std::unique_ptr<DynamicOpDefinition> opDef =
-    DynamicOpDefinition::get(name, dialect, std::move(verifyFn),
-        std::move(parseFn), std::move(printFn), std::move(foldHookFn),
-        std::move(getCanonicalizationPatterns));
-```
-
-Once the operation is defined, it can be registered by an `ExtensibleDialect`:
-
-```c++
-extensibleDialect->registerDynamicOperation(std::move(opDef));
-```
-
-Note that the `Dialect` given to the operation should be the one registering
-the operation.
-
-### Using an operation defined at runtime
-
-It is possible to match on an operation defined at runtime using their names:
-
-```c++
-if (op->getName().getStringRef() == "my_dialect.my_dynamic_op") {
-    ...
-}
-```
-
-An operation defined at runtime can be created by instantiating an
-`OperationState` with the operation name, and using it with a rewriter
-(for instance a `PatternRewriter`) to create the operation.
-
-```c++
-OperationState state(location, "my_dialect.my_dynamic_op",
-                     operands, resultTypes, attributes);
-
-rewriter.createOperation(state);
-```
-
-
-### Defining a type at runtime
-
-Contrary to types defined in C++ or in TableGen, types defined at runtime can
-only have as argument a list of `Attribute`.
-
-Similarily to operations, a type is defined at runtime using the class
-`DynamicTypeDefinition`, which is created using the `DynamicTypeDefinition::get`
-functions. A type definition requires a name, the dialect that will register the
-type, and a parameter verifier. It can also define optionally a custom parser
-and printer for the arguments (the type name is assumed to be already
-parsed/printed).
-
-```c++
-// The type name, without the dialect name prefix.
-StringRef name = "my_type_name";
-
-// The dialect defining the type.
-Dialect* dialect = ctx->getOrLoadDialect<MyDialect>();
-
-// The type verifier.
-// A type defined at runtime has a list of attributes as parameters.
-auto verifier = [](function_ref<InFlightDiagnostic()> emitError,
-                   ArrayRef<Attribute> args) {
-    ...
-};
-
-// The type parameters parser.
-auto parser = [](DialectAsmParser &parser,
-                 llvm::SmallVectorImpl<Attribute> &parsedParams) {
-    ...
-};
-
-// The type parameters printer.
-auto printer =[](DialectAsmPrinter &printer, ArrayRef<Attribute> params) {
-    ...
-};
-
-std::unique_ptr<DynamicTypeDefinition> typeDef =
-    DynamicTypeDefinition::get(std::move(name), std::move(dialect),
-                               std::move(verifier), std::move(printer),
-                               std::move(parser));
-```
-
-If the printer and the parser are ommited, a default parser and printer is
-generated with the format `!dialect.typename<arg1, arg2, ..., argN>`.
-
-The type can then be registered by the `ExtensibleDialect`:
-
-```c++
-dialect->registerDynamicType(std::move(typeDef));
-```
-
-### Parsing types defined at runtime in an extensible dialect
-
-`parseType` methods generated by TableGen can parse types defined at runtime,
-though overriden `parseType` methods need to add the necessary support for them.
-
-```c++
-Type MyDialect::parseType(DialectAsmParser &parser) const {
-    ...
-    
-    // The type name.
-    StringRef typeTag;
-    if (failed(parser.parseKeyword(&typeTag)))
-        return Type();
-
-    // Try to parse a dynamic type with 'typeTag' name.
-    Type dynType;
-    auto parseResult = parseOptionalDynamicType(typeTag, parser, dynType);
-    if (parseResult.hasValue()) {
-        if (succeeded(parseResult.getValue()))
-            return dynType;
-         return Type();
-    }
-    
-    ...
-}
-```
-
-### Using a type defined at runtime
-
-Dynamic types are instances of `DynamicType`. It is possible to get a dynamic
-type with `DynamicType::get` and `ExtensibleDialect::lookupTypeDefinition`.
-
-```c++
-auto typeDef = extensibleDialect->lookupTypeDefinition("my_dynamic_type");
-ArrayRef<Attribute> params = ...;
-auto type = DynamicType::get(typeDef, params);
-```
-
-It is also possible to cast a `Type` known to be defined at runtime to a
-`DynamicType`.
-
-```c++
-auto dynType = type.cast<DynamicType>();
-auto typeDef = dynType.getTypeDef();
-auto args = dynType.getParams();
-```
-
-### Defining an attribute at runtime
-
-Similar to types defined at runtime, attributes defined at runtime can only have
-as argument a list of `Attribute`.
-
-Similarily to types, an attribute is defined at runtime using the class
-`DynamicAttrDefinition`, which is created using the `DynamicAttrDefinition::get`
-functions. An attribute definition requires a name, the dialect that will
-register the attribute, and a parameter verifier. It can also define optionally
-a custom parser and printer for the arguments (the attribute name is assumed to
-be already parsed/printed).
-
-```c++
-// The attribute name, without the dialect name prefix.
-StringRef name = "my_attribute_name";
-
-// The dialect defining the attribute.
-Dialect* dialect = ctx->getOrLoadDialect<MyDialect>();
-
-// The attribute verifier.
-// An attribute defined at runtime has a list of attributes as parameters.
-auto verifier = [](function_ref<InFlightDiagnostic()> emitError,
-                   ArrayRef<Attribute> args) {
-    ...
-};
-
-// The attribute parameters parser.
-auto parser = [](DialectAsmParser &parser,
-                 llvm::SmallVectorImpl<Attribute> &parsedParams) {
-    ...
-};
-
-// The attribute parameters printer.
-auto printer =[](DialectAsmPrinter &printer, ArrayRef<Attribute> params) {
-    ...
-};
-
-std::unique_ptr<DynamicAttrDefinition> attrDef =
-    DynamicAttrDefinition::get(std::move(name), std::move(dialect),
-                               std::move(verifier), std::move(printer),
-                               std::move(parser));
-```
-
-If the printer and the parser are ommited, a default parser and printer is
-generated with the format `!dialect.attrname<arg1, arg2, ..., argN>`.
-
-The attribute can then be registered by the `ExtensibleDialect`:
-
-```c++
-dialect->registerDynamicAttr(std::move(typeDef));
-```
-
-### Parsing attributes defined at runtime in an extensible dialect
-
-`parseAttribute` methods generated by TableGen can parse attributes defined at
-runtime, though overriden `parseAttribute` methods need to add the necessary
-support for them.
-
-```c++
-Attribute MyDialect::parseAttribute(DialectAsmParser &parser,
-                                    Type type) const override {
-    ...
-    // The attribute name.
-    StringRef attrTag;
-    if (failed(parser.parseKeyword(&attrTag)))
-        return Attribute();
-
-    // Try to parse a dynamic attribute with 'attrTag' name.
-    Attribute dynAttr;
-    auto parseResult = parseOptionalDynamicAttr(attrTag, parser, dynAttr);
-    if (parseResult.hasValue()) {
-        if (succeeded(parseResult.getValue()))
-            return dynAttr;
-         return Attribute();
-    }
-```
-
-### Using an attribute defined at runtime
-
-Similar to types, attributes defined at runtime are instances of `DynamicAttr`.
-It is possible to get a dynamic attribute with `DynamicAttr::get` and
-`ExtensibleDialect::lookupAttrDefinition`.
-
-```c++
-auto attrDef = extensibleDialect->lookupAttrDefinition("my_dynamic_attr");
-ArrayRef<Attribute> params = ...;
-auto attr = DynamicAttr::get(attrDef, params);
-```
-
-It is also possible to cast an `Attribute` known to be defined at runtime to a
-`DynamicAttr`.
-
-```c++
-auto dynAttr = attr.cast<DynamicAttr>();
-auto attrDef = dynAttr.getAttrDef();
-auto args = dynAttr.getParams();
-```
-
-## Implementation details
-
-### Extensible dialect
-
-The role of extensible dialects is to own the necessary data for defined
-operations and types. They also contain the necessary accessors to easily
-access them.
-
-In order to cast a `Dialect` back to an `ExtensibleDialect`, we implement the
-`IsExtensibleDialect` interface to all `ExtensibleDialect`. The casting is done
-by checking if the `Dialect` implements `IsExtensibleDialect` or not.
-
-### Operation representation and registration
-
-Operations are represented in mlir using the `AbstractOperation` class. They are
-registered in dialects the same way operations defined in C++ are registered,
-which is by calling `AbstractOperation::insert`.
-
-The only 
diff erence is that a new `TypeID` needs to be created for each
-operation, since operations are not represented by a C++ class. This is done
-using a `TypeIDAllocator`, which can allocate a new unique `TypeID` at runtime.
-
-### Type representation and registration
-
-Unlike operations, types need to define a C++ storage class that takes care of
-type parameters. They also need to define another C++ class to access that
-storage. `DynamicTypeStorage` defines the storage of types defined at runtime,
-and `DynamicType` gives access to the storage, as well as defining useful
-functions. A `DynamicTypeStorage` contains a list of `Attribute` type
-parameters, as well as a pointer to the type definition.
-
-Types are registered using the `Dialect::addType` method, which expect a
-`TypeID` that is generated using a `TypeIDAllocator`. The type uniquer also
-register the type with the given `TypeID`. This mean that we can reuse our
-single `DynamicType` with 
diff erent `TypeID` to represent the 
diff erent types
-defined at runtime.
-
-Since the 
diff erent types defined at runtime have 
diff erent `TypeID`, it is not
-possible to use `TypeID` to cast a `Type` into a `DynamicType`. Thus, similar to
-`Dialect`, all `DynamicType` define a `IsDynamicTypeTrait`, so casting a `Type`
-to a `DynamicType` boils down to querying the `IsDynamicTypeTrait` trait.


        


More information about the Mlir-commits mailing list