[Mlir-commits] [mlir] 1a083f0 - [mlir] Revamp operation documentation generation

River Riddle llvmlistbot at llvm.org
Tue Mar 24 12:05:27 PDT 2020


Author: River Riddle
Date: 2020-03-24T12:05:18-07:00
New Revision: 1a083f027f33f4014247df4c0e757e23d5cdab64

URL: https://github.com/llvm/llvm-project/commit/1a083f027f33f4014247df4c0e757e23d5cdab64
DIFF: https://github.com/llvm/llvm-project/commit/1a083f027f33f4014247df4c0e757e23d5cdab64.diff

LOG: [mlir] Revamp operation documentation generation

Summary:
This revisions performs several cleanups to the generated dialect documentation:
* Standardizes format of attributes/operands/results sections
* Splits out operation/type/dialect documentation generation to allow for composing generated and hand-written documentation
* Add section for declarative assembly syntax and successors
* General cleanup

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

Added: 
    

Modified: 
    mlir/cmake/modules/AddMLIR.cmake
    mlir/docs/CreatingADialect.md
    mlir/docs/Dialects/Vector.md
    mlir/docs/OpDefinitions.md
    mlir/include/mlir/Dialect/Affine/IR/CMakeLists.txt
    mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
    mlir/include/mlir/Dialect/GPU/CMakeLists.txt
    mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
    mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
    mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
    mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt
    mlir/include/mlir/Dialect/Quant/CMakeLists.txt
    mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
    mlir/include/mlir/Dialect/Vector/CMakeLists.txt
    mlir/include/mlir/TableGen/Operator.h
    mlir/lib/TableGen/Operator.cpp
    mlir/tools/mlir-tblgen/OpDocGen.cpp
    mlir/tools/mlir-tblgen/OpFormatGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/cmake/modules/AddMLIR.cmake b/mlir/cmake/modules/AddMLIR.cmake
index e9101ed25dca..2adb8f2f2935 100644
--- a/mlir/cmake/modules/AddMLIR.cmake
+++ b/mlir/cmake/modules/AddMLIR.cmake
@@ -32,26 +32,28 @@ function(whole_archive_link target)
 endfunction(whole_archive_link)
 
 # Declare a dialect in the include directory
-function(add_mlir_dialect dialect dialect_namespace dialect_doc_filename)
+function(add_mlir_dialect dialect dialect_namespace)
   set(LLVM_TARGET_DEFINITIONS ${dialect}.td)
   mlir_tablegen(${dialect}.h.inc -gen-op-decls)
   mlir_tablegen(${dialect}.cpp.inc -gen-op-defs)
   mlir_tablegen(${dialect}Dialect.h.inc -gen-dialect-decls -dialect=${dialect_namespace})
   add_public_tablegen_target(MLIR${dialect}IncGen)
   add_dependencies(mlir-headers MLIR${dialect}IncGen)
+endfunction()
 
-  # Generate Dialect Documentation
-  set(LLVM_TARGET_DEFINITIONS ${dialect_doc_filename}.td)
-  tablegen(MLIR ${dialect_doc_filename}.md -gen-op-doc "-I${MLIR_MAIN_SRC_DIR}" "-I${MLIR_INCLUDE_DIR}")
-  set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/Dialects/${dialect_doc_filename}.md)
+# Generate Documentation
+function(add_mlir_doc doc_filename command output_file output_directory)
+  set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td)
+  tablegen(MLIR ${output_file}.md ${command} "-I${MLIR_MAIN_SRC_DIR}" "-I${MLIR_INCLUDE_DIR}")
+  set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/${output_directory}${output_file}.md)
   add_custom_command(
           OUTPUT ${GEN_DOC_FILE}
           COMMAND ${CMAKE_COMMAND} -E copy
-                  ${CMAKE_CURRENT_BINARY_DIR}/${dialect_doc_filename}.md
+                  ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md
                   ${GEN_DOC_FILE}
-          DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${dialect_doc_filename}.md)
-  add_custom_target(${dialect_doc_filename}DocGen DEPENDS ${GEN_DOC_FILE})
-  add_dependencies(mlir-doc ${dialect_doc_filename}DocGen)
+          DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md)
+  add_custom_target(${output_file}DocGen DEPENDS ${GEN_DOC_FILE})
+  add_dependencies(mlir-doc ${output_file}DocGen)
 endfunction()
 
 # Declare a library which can be compiled in libMLIR.so

diff  --git a/mlir/docs/CreatingADialect.md b/mlir/docs/CreatingADialect.md
index 8757bf5e2a90..e8a8d40ff096 100644
--- a/mlir/docs/CreatingADialect.md
+++ b/mlir/docs/CreatingADialect.md
@@ -39,7 +39,8 @@ is declared using add_mlir_dialect().
 
 ```cmake
 
-add_mlir_dialect(FooOps foo FooOps)
+add_mlir_dialect(FooOps foo)
+add_mlir_doc(FooOps -gen-dialect-doc FooDialect Dialects/)
 
 ```
 

diff  --git a/mlir/docs/Dialects/Vector.md b/mlir/docs/Dialects/Vector.md
index 565060795083..10de1731a2f2 100644
--- a/mlir/docs/Dialects/Vector.md
+++ b/mlir/docs/Dialects/Vector.md
@@ -1,5 +1,7 @@
 # Vector Dialect
 
+[TOC]
+
 MLIR supports multi-dimensional `vector` types and custom operations on those
 types. A generic, retargetable, higher-order ``vector`` type (`n-D` with `n >
 1`) is a structured type, that carries semantic information useful for
@@ -488,6 +490,6 @@ low-level abstraction.
 The use of special intrinsics in a `1-D` LLVM world is still available thanks
 to an explicit `vector.cast` op.
 
+## Operations
 
-### Operations
-
+[include "Dialects/VectorOps.md"]

diff  --git a/mlir/docs/OpDefinitions.md b/mlir/docs/OpDefinitions.md
index cc8761eccb15..4757dfcf3390 100644
--- a/mlir/docs/OpDefinitions.md
+++ b/mlir/docs/OpDefinitions.md
@@ -1222,7 +1222,7 @@ mlir-tblgen --gen-op-decls -I /path/to/mlir/include /path/to/input/td/file
 # To see op C++ class definition
 mlir-tblgen --gen-op-defs -I /path/to/mlir/include /path/to/input/td/file
 # To see op documentation
-mlir-tblgen --gen-op-doc -I /path/to/mlir/include /path/to/input/td/file
+mlir-tblgen --gen-dialect-doc -I /path/to/mlir/include /path/to/input/td/file
 
 # To see op interface C++ class declaration
 mlir-tblgen --gen-op-interface-decls -I /path/to/mlir/include /path/to/input/td/file
@@ -1232,7 +1232,6 @@ mlir-tblgen --gen-op-interface-defs -I /path/to/mlir/include /path/to/input/td/f
 mlir-tblgen --gen-op-interface-doc -I /path/to/mlir/include /path/to/input/td/file
 ```
 
-
 ## Appendix
 
 ### Requirements and existing mechanisms analysis

diff  --git a/mlir/include/mlir/Dialect/Affine/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Affine/IR/CMakeLists.txt
index 155e066a4725..4a7144ef96e4 100644
--- a/mlir/include/mlir/Dialect/Affine/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Affine/IR/CMakeLists.txt
@@ -1 +1,2 @@
-add_mlir_dialect(AffineOps affine AffineOps)
+add_mlir_dialect(AffineOps affine)
+add_mlir_doc(AffineOps -gen-dialect-doc AffineDialect Dialects/)

diff  --git a/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt b/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
index cff7f3ea1548..2a493d6c1b20 100644
--- a/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
@@ -1 +1,2 @@
-add_mlir_dialect(FxpMathOps fxpmath FxpMathOps)
+add_mlir_dialect(FxpMathOps fxpmath)
+add_mlir_doc(FxpMathOps -gen-dialect-doc FxpMathDialect Dialects/)

diff  --git a/mlir/include/mlir/Dialect/GPU/CMakeLists.txt b/mlir/include/mlir/Dialect/GPU/CMakeLists.txt
index bb4c4f5d34c4..3122b8421cbb 100644
--- a/mlir/include/mlir/Dialect/GPU/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/GPU/CMakeLists.txt
@@ -1 +1,2 @@
-add_mlir_dialect(GPUOps gpu GPUOps)
+add_mlir_dialect(GPUOps gpu)
+add_mlir_doc(GPUOps -gen-dialect-doc GPUDialect Dialects/)

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 22b155b4035e..d7e581b1b949 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -6,8 +6,10 @@ mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
 mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
 add_public_tablegen_target(MLIRLLVMOpsIncGen)
 
-add_mlir_dialect(NVVMOps nvvm NVVMOps)
-add_mlir_dialect(ROCDLOps rocdl ROCDLOps)
+add_mlir_dialect(NVVMOps nvvm)
+add_mlir_doc(NVVMOps -gen-dialect-doc NVVMDialect Dialects/)
+add_mlir_dialect(ROCDLOps rocdl)
+add_mlir_doc(ROCDLOps -gen-dialect-doc ROCDLDialect Dialects/)
 
 set(LLVM_TARGET_DEFINITIONS LLVMOps.td)
 mlir_tablegen(LLVMConversions.inc -gen-llvmir-conversions)

diff  --git a/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
index 212e3022262d..2c8c33ff62a6 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
@@ -1,4 +1,5 @@
-add_mlir_dialect(LinalgOps linalg LinalgDoc)
+add_mlir_dialect(LinalgOps linalg)
+add_mlir_doc(LinalgDoc -gen-dialect-doc LinalgDialect Dialects/)
 set(LLVM_TARGET_DEFINITIONS LinalgStructuredOps.td)
 mlir_tablegen(LinalgStructuredOps.h.inc -gen-op-decls)
 mlir_tablegen(LinalgStructuredOps.cpp.inc -gen-op-defs)

diff  --git a/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt b/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
index 511c32d32a47..4a838cc1d52d 100644
--- a/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
@@ -1 +1,2 @@
-add_mlir_dialect(LoopOps loop LoopOps)
+add_mlir_dialect(LoopOps loop)
+add_mlir_doc(LoopOps -gen-dialect-doc LoopDialect Dialects/)

diff  --git a/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt b/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt
index 0362a631dc2e..0df7a04f52b9 100644
--- a/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt
@@ -1 +1,2 @@
-add_mlir_dialect(OpenMPOps omp OpenMPOps)
+add_mlir_dialect(OpenMPOps omp)
+add_mlir_doc(OpenMPOps -gen-dialect-doc OpenMPDialect Dialects/)

diff  --git a/mlir/include/mlir/Dialect/Quant/CMakeLists.txt b/mlir/include/mlir/Dialect/Quant/CMakeLists.txt
index 87a9fd6a3066..b18726736e94 100644
--- a/mlir/include/mlir/Dialect/Quant/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Quant/CMakeLists.txt
@@ -1 +1,2 @@
-add_mlir_dialect(QuantOps quant QuantOps)
+add_mlir_dialect(QuantOps quant)
+add_mlir_doc(QuantOps -gen-dialect-doc QuantDialect Dialects/)

diff  --git a/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt b/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
index 8d297cc92117..771d4c1a43bb 100644
--- a/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
@@ -1,4 +1,5 @@
-add_mlir_dialect(SPIRVOps spv SPIRVOps)
+add_mlir_dialect(SPIRVOps spv)
+add_mlir_doc(SPIRVOps -gen-dialect-doc SPIRVDialect Dialects/)
 
 set(LLVM_TARGET_DEFINITIONS SPIRVBase.td)
 mlir_tablegen(SPIRVEnums.h.inc -gen-enum-decls)

diff  --git a/mlir/include/mlir/Dialect/Vector/CMakeLists.txt b/mlir/include/mlir/Dialect/Vector/CMakeLists.txt
index 4977e117e7e0..a27eef693a28 100644
--- a/mlir/include/mlir/Dialect/Vector/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Vector/CMakeLists.txt
@@ -1,4 +1,5 @@
-add_mlir_dialect(VectorOps vector VectorOps)
+add_mlir_dialect(VectorOps vector)
+add_mlir_doc(VectorOps -gen-op-doc VectorOps Dialects/)
 
 set(LLVM_TARGET_DEFINITIONS VectorTransformPatterns.td)
 mlir_tablegen(VectorTransformPatterns.h.inc -gen-rewriters)

diff  --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h
index 08af550499a7..aaf93d3964e8 100644
--- a/mlir/include/mlir/TableGen/Operator.h
+++ b/mlir/include/mlir/TableGen/Operator.h
@@ -198,6 +198,10 @@ class Operator {
   bool hasSummary() const;
   StringRef getSummary() const;
 
+  // Query functions for the assembly format of the operator.
+  bool hasAssemblyFormat() const;
+  StringRef getAssemblyFormat() const;
+
   // Returns this op's extra class declaration code.
   StringRef getExtraClassDeclaration() const;
 

diff  --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp
index 6492b772e4b7..ff84456d5491 100644
--- a/mlir/lib/TableGen/Operator.cpp
+++ b/mlir/lib/TableGen/Operator.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/TableGen/Operator.h"
+#include "mlir/ADT/TypeSwitch.h"
 #include "mlir/TableGen/OpTrait.h"
 #include "mlir/TableGen/Predicate.h"
 #include "mlir/TableGen/Type.h"
@@ -411,6 +412,17 @@ StringRef tblgen::Operator::getSummary() const {
   return def.getValueAsString("summary");
 }
 
+bool tblgen::Operator::hasAssemblyFormat() const {
+  auto *valueInit = def.getValueInit("assemblyFormat");
+  return isa<llvm::CodeInit>(valueInit) || isa<llvm::StringInit>(valueInit);
+}
+
+StringRef tblgen::Operator::getAssemblyFormat() const {
+  return TypeSwitch<llvm::Init *, StringRef>(def.getValueInit("assemblyFormat"))
+      .Case<llvm::StringInit, llvm::CodeInit>(
+          [&](auto *init) { return init->getValue(); });
+}
+
 void tblgen::Operator::print(llvm::raw_ostream &os) const {
   os << "op '" << getOperationName() << "'\n";
   for (Argument arg : arguments) {

diff  --git a/mlir/tools/mlir-tblgen/OpDocGen.cpp b/mlir/tools/mlir-tblgen/OpDocGen.cpp
index b8a00af10af2..a432b4a2f21c 100644
--- a/mlir/tools/mlir-tblgen/OpDocGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDocGen.cpp
@@ -78,82 +78,140 @@ static void emitIfNotEmpty(StringRef str, raw_ostream &os) {
   }
 }
 
-static void emitOpDocForDialect(const Dialect &dialect,
-                                const std::vector<Operator> &ops,
-                                const std::vector<Type> &types,
-                                raw_ostream &os) {
-  os << "# Dialect '" << dialect.getName() << "' definition\n\n";
-  emitIfNotEmpty(dialect.getSummary(), os);
-  emitIfNotEmpty(dialect.getDescription(), os);
-
-  // TODO(b/143543720) Generate TOC where extension is not supported.
-  os << "[TOC]\n\n";
+/// Emit the given named constraint.
+template <typename T>
+static void emitNamedConstraint(const T &it, raw_ostream &os) {
+  if (!it.name.empty())
+    os << "`" << it.name << "`";
+  else
+    os << "«unnamed»";
+  os << " | " << it.constraint.getDescription() << "\n";
+}
 
-  // TODO(antiagainst): Add link between use and def for types
-  if (!types.empty())
-    os << "## Type definition\n\n";
-  for (auto type : types) {
-    os << "### " << type.getDescription() << "\n";
-    emitDescription(type.getTypeDescription(), os);
-    os << "\n";
-  }
+//===----------------------------------------------------------------------===//
+// Operation Documentation
+//===----------------------------------------------------------------------===//
 
-  if (!ops.empty())
-    os << "## Operation definition\n\n";
-  for (auto op : ops) {
-    os << "### " << op.getOperationName() << " (" << op.getQualCppClassName()
-       << ")";
-
-    // Emit summary & description of operator.
-    if (op.hasSummary())
-      os << "\n" << op.getSummary() << "\n";
-    os << "\n#### Description:\n\n";
-    if (op.hasDescription())
-      mlir::tblgen::emitDescription(op.getDescription(), os);
-
-    // Emit operands & type of operand. All operands are numbered, some may be
-    // named too.
-    os << "\n#### Operands:\n\n";
-    for (const auto &operand : op.getOperands()) {
-      os << "1. ";
-      if (!operand.name.empty())
-        os << "`" << operand.name << "`: ";
-      else
-        os << "«unnamed»: ";
-      os << operand.constraint.getDescription() << "\n";
-    }
+/// Emit the assembly format of an operation.
+static void emitAssemblyFormat(StringRef opName, StringRef format,
+                               raw_ostream &os) {
+  os << "\nSyntax:\n\n```\noperation ::= `" << opName << "` ";
+
+  // Print the assembly format aligned.
+  unsigned indent = strlen("operation ::= ");
+  std::pair<StringRef, StringRef> split = format.split('\n');
+  os << split.first.trim() << "\n";
+  do {
+    split = split.second.split('\n');
+    StringRef formatChunk = split.first.trim();
+    if (!formatChunk.empty())
+      os.indent(indent) << formatChunk << "\n";
+  } while (!split.second.empty());
+  os << "```\n\n";
+}
 
-    // Emit attributes.
+static void emitOpDoc(Operator op, raw_ostream &os) {
+  os << llvm::formatv("### `{0}` ({1})\n", op.getOperationName(),
+                      op.getQualCppClassName());
+
+  // Emit the summary, syntax, and description if present.
+  if (op.hasSummary())
+    os << "\n" << op.getSummary() << "\n";
+  if (op.hasAssemblyFormat())
+    emitAssemblyFormat(op.getOperationName(), op.getAssemblyFormat().trim(),
+                       os);
+  if (op.hasDescription())
+    mlir::tblgen::emitDescription(op.getDescription(), os);
+
+  // Emit attributes.
+  if (op.getNumAttributes() != 0) {
     // TODO: Attributes are only documented by TableGen name, with no further
     // info. This should be improved.
     os << "\n#### Attributes:\n\n";
-    if (op.getNumAttributes() > 0) {
-      os << "| Attribute | MLIR Type | Description |\n"
-         << "| :-------: | :-------: | ----------- |\n";
-    }
-    for (auto namedAttr : op.getAttributes()) {
-      os << "| `" << namedAttr.name << "` | `"
-         << namedAttr.attr.getStorageType() << "` | "
-         << namedAttr.attr.getDescription() << " attribute |\n";
+    os << "| Attribute | MLIR Type | Description |\n"
+       << "| :-------: | :-------: | ----------- |\n";
+    for (const auto &it : op.getAttributes()) {
+      StringRef storageType = it.attr.getStorageType();
+      os << "`" << it.name << "` | " << storageType << " | "
+         << it.attr.getDescription() << "\n";
     }
+  }
 
-    // Emit results.
+  // Emit each of the operands.
+  if (op.getNumOperands() != 0) {
+    os << "\n#### Operands:\n\n";
+    os << "| Operand | Description |\n"
+       << "| :-----: | ----------- |\n";
+    for (const auto &it : op.getOperands())
+      emitNamedConstraint(it, os);
+  }
+
+  // Emit results.
+  if (op.getNumResults() != 0) {
     os << "\n#### Results:\n\n";
-    for (unsigned i = 0, e = op.getNumResults(); i < e; ++i) {
-      os << "1. ";
-      auto name = op.getResultName(i);
-      if (name.empty())
-        os << "«unnamed»: ";
-      else
-        os << "`" << name << "`: ";
-      os << op.getResultTypeConstraint(i).getDescription() << "\n";
-    }
+    os << "| Result | Description |\n"
+       << "| :----: | ----------- |\n";
+    for (const auto &it : op.getResults())
+      emitNamedConstraint(it, os);
+  }
 
-    os << "\n";
+  // Emit successors.
+  if (op.getNumSuccessors() != 0) {
+    os << "\n#### Successors:\n\n";
+    os << "| Successor | Description |\n"
+       << "| :-------: | ----------- |\n";
+    for (const auto &it : op.getSuccessors())
+      emitNamedConstraint(it, os);
   }
+
+  os << "\n";
 }
 
 static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
+  auto opDefs = recordKeeper.getAllDerivedDefinitions("Op");
+
+  os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
+  for (const llvm::Record *opDef : opDefs)
+    emitOpDoc(Operator(opDef), os);
+}
+
+//===----------------------------------------------------------------------===//
+// Type Documentation
+//===----------------------------------------------------------------------===//
+
+static void emitTypeDoc(const Type &type, raw_ostream &os) {
+  os << "### " << type.getDescription() << "\n";
+  emitDescription(type.getTypeDescription(), os);
+  os << "\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Dialect Documentation
+//===----------------------------------------------------------------------===//
+
+static void emitDialectDoc(const Dialect &dialect, ArrayRef<Operator> ops,
+                           ArrayRef<Type> types, raw_ostream &os) {
+  os << "# '" << dialect.getName() << "' Dialect\n\n";
+  emitIfNotEmpty(dialect.getSummary(), os);
+  emitIfNotEmpty(dialect.getDescription(), os);
+
+  os << "[TOC]\n\n";
+
+  // TODO(antiagainst): Add link between use and def for types
+  if (!types.empty()) {
+    os << "## Type definition\n\n";
+    for (const Type &type : types)
+      emitTypeDoc(type, os);
+  }
+
+  if (!ops.empty()) {
+    os << "## Operation definition\n\n";
+    for (const Operator &op : ops)
+      emitOpDoc(op, os);
+  }
+}
+
+static void emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
   const auto &opDefs = recordKeeper.getAllDerivedDefinitions("Op");
   const auto &typeDefs = recordKeeper.getAllDerivedDefinitions("DialectType");
 
@@ -171,13 +229,24 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
 
   os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
   for (auto dialectWithOps : dialectOps)
-    emitOpDocForDialect(dialectWithOps.first, dialectWithOps.second,
-                        dialectTypes[dialectWithOps.first], os);
+    emitDialectDoc(dialectWithOps.first, dialectWithOps.second,
+                   dialectTypes[dialectWithOps.first], os);
 }
 
+//===----------------------------------------------------------------------===//
+// Gen Registration
+//===----------------------------------------------------------------------===//
+
+static mlir::GenRegistration
+    genOpRegister("gen-op-doc", "Generate dialect documentation",
+                  [](const RecordKeeper &records, raw_ostream &os) {
+                    emitOpDoc(records, os);
+                    return false;
+                  });
+
 static mlir::GenRegistration
-    genRegister("gen-op-doc", "Generate operation documentation",
+    genRegister("gen-dialect-doc", "Generate dialect documentation",
                 [](const RecordKeeper &records, raw_ostream &os) {
-                  emitOpDoc(records, os);
+                  emitDialectDoc(records, os);
                   return false;
                 });

diff  --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
index 3249d06bb764..525981e03c86 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
@@ -1830,19 +1830,13 @@ void mlir::tblgen::generateOpFormat(const Operator &constOp, OpClass &opClass) {
   // TODO(riverriddle) Operator doesn't expose all necessary functionality via
   // the const interface.
   Operator &op = const_cast<Operator &>(constOp);
-
-  // Check if the operation specified the format field.
-  StringRef formatStr;
-  TypeSwitch<llvm::Init *>(op.getDef().getValueInit("assemblyFormat"))
-      .Case<llvm::StringInit, llvm::CodeInit>(
-          [&](auto *init) { formatStr = init->getValue(); });
-  if (formatStr.empty())
+  if (!op.hasAssemblyFormat())
     return;
 
   // Parse the format description.
   llvm::SourceMgr mgr;
-  mgr.AddNewSourceBuffer(llvm::MemoryBuffer::getMemBuffer(formatStr),
-                         llvm::SMLoc());
+  mgr.AddNewSourceBuffer(
+      llvm::MemoryBuffer::getMemBuffer(op.getAssemblyFormat()), llvm::SMLoc());
   OperationFormat format(op);
   if (failed(FormatParser(mgr, format, op).parse())) {
     // Exit the process if format errors are treated as fatal.


        


More information about the Mlir-commits mailing list