[Mlir-commits] [mlir] [MLIR] Generate cpp comments for TableGen summary and description (PR #139606)

Peng Chen llvmlistbot at llvm.org
Wed May 14 08:58:31 PDT 2025


https://github.com/pchen7e2 updated https://github.com/llvm/llvm-project/pull/139606

>From 427ea4babf058e6dee467024e875be1ad7876c34 Mon Sep 17 00:00:00 2001
From: Peng Chen <pchen7e2 at gmail.com>
Date: Mon, 12 May 2025 11:45:43 -0700
Subject: [PATCH 1/3] [MLIR] Generate cpp comments on top of generated cpp
 classes derived from TableGen summary and description

---
 mlir/test/mlir-tblgen/cpp-class-comments.td | 74 +++++++++++++++++++++
 mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp |  9 ++-
 mlir/tools/mlir-tblgen/CMakeLists.txt       |  1 +
 mlir/tools/mlir-tblgen/CppGenUtilities.cpp  | 39 +++++++++++
 mlir/tools/mlir-tblgen/CppGenUtilities.h    | 29 ++++++++
 mlir/tools/mlir-tblgen/DialectGen.cpp       |  7 +-
 mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp |  9 ++-
 7 files changed, 164 insertions(+), 4 deletions(-)
 create mode 100644 mlir/test/mlir-tblgen/cpp-class-comments.td
 create mode 100644 mlir/tools/mlir-tblgen/CppGenUtilities.cpp
 create mode 100644 mlir/tools/mlir-tblgen/CppGenUtilities.h

diff --git a/mlir/test/mlir-tblgen/cpp-class-comments.td b/mlir/test/mlir-tblgen/cpp-class-comments.td
new file mode 100644
index 0000000000000..66d7e692dee25
--- /dev/null
+++ b/mlir/test/mlir-tblgen/cpp-class-comments.td
@@ -0,0 +1,74 @@
+// RUN: mlir-tblgen -gen-dialect-decls -I %S/../../include %s | FileCheck %s --check-prefix=DIALECT
+// RUN: mlir-tblgen -gen-op-decls -I %S/../../include %s | FileCheck %s --check-prefix=OP
+// RUN: mlir-tblgen -gen-typedef-decls -I %S/../../include %s | FileCheck %s --check-prefix=TYPE
+
+include "mlir/IR/OpBase.td"
+
+// check dialect with summary and description
+def A_Dialect : Dialect {
+  let name = "a";
+  let cppNamespace = "";
+
+  let summary = "This is a summary";
+  let description = [{
+
+    This is a description, needs trimming
+
+  }];
+// DIALECT: /// This is a summary
+// DIALECT-NEXT: /// This is a description, needs trimming
+// DIALECT-NEXT: class ADialect : public ::mlir::Dialect {
+}
+
+def A_SomeOp1 : Op<A_Dialect, "some_op1", []>{
+  let summary = "Some Op1 summary line1 \nsummary line2";
+
+  let description = [{
+      Some Op1 description
+  }];
+
+  let cppNamespace = "OP1";
+// OP: namespace OP1
+// OP-NEXT: /// Some Op1 summary line1
+// OP-NEXT: /// summary line2
+// OP-NEXT: /// Some Op1 description
+// OP-NEXT: class SomeOp1;
+}
+
+// test weird characters in description
+def A_SomeOp2 : Op<A_Dialect, "some_op2", []>{
+  let summary = "";
+
+  let description = [{
+      $ptr (`,` $mask^)? (`,` $other^)?
+      oilist(
+        `a` `=` $1 | `b` `=` $2
+      )
+  }];
+// OP: /// $ptr (`,` $mask^)? (`,` $other^)?
+// OP-NEXT: /// oilist(
+// OP-NEXT: /// `a` `=` $1 | `b` `=` $2
+// OP-NEXT: /// )
+// OP-NEXT: class SomeOp2;
+}
+
+class AType<string name> : TypeDef<A_Dialect, name> { }
+
+
+def A_TensorType : AType<"Tensor"> {
+  let typeName = "a.simple_a_tensor";
+
+  let summary = "Tensor Type A summary";
+
+  let description = [{
+      Tensor Type A description
+  }];
+
+  let extraClassDeclaration = [{
+    void getSignlessBlockType() const {
+    }
+  }];
+// TYPE: /// Tensor Type A summary
+// TYPE-NEXT: /// Tensor Type A description
+// TYPE-NEXT: class TensorType;
+}
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index 05686c0539754..2a6071602fa49 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AttrOrTypeFormatGen.h"
+#include "CppGenUtilities.h"
 #include "mlir/TableGen/AttrOrTypeDef.h"
 #include "mlir/TableGen/Class.h"
 #include "mlir/TableGen/CodeGenHelpers.h"
@@ -813,8 +814,14 @@ bool DefGenerator::emitDecls(StringRef selectedDialect) {
     NamespaceEmitter nsEmitter(os, defs.front().getDialect());
 
     // Declare all the def classes first (in case they reference each other).
-    for (const AttrOrTypeDef &def : defs)
+    for (const AttrOrTypeDef &def : defs) {
+      std::string comments = tblgen::emitSummaryAndDescComments(
+          def.getSummary(), def.getDescription());
+      if (!comments.empty()) {
+        os << comments << "\n";
+      }
       os << "class " << def.getCppClassName() << ";\n";
+    }
 
     // Emit the declarations.
     for (const AttrOrTypeDef &def : defs)
diff --git a/mlir/tools/mlir-tblgen/CMakeLists.txt b/mlir/tools/mlir-tblgen/CMakeLists.txt
index 9431c59860522..2a7ef7e0576c8 100644
--- a/mlir/tools/mlir-tblgen/CMakeLists.txt
+++ b/mlir/tools/mlir-tblgen/CMakeLists.txt
@@ -33,6 +33,7 @@ add_tablegen(mlir-tblgen MLIR
   RewriterGen.cpp
   SPIRVUtilsGen.cpp
   TosaUtilsGen.cpp
+  CppGenUtilities.cpp
   )
 
 target_link_libraries(mlir-tblgen
diff --git a/mlir/tools/mlir-tblgen/CppGenUtilities.cpp b/mlir/tools/mlir-tblgen/CppGenUtilities.cpp
new file mode 100644
index 0000000000000..ebca20cc685f4
--- /dev/null
+++ b/mlir/tools/mlir-tblgen/CppGenUtilities.cpp
@@ -0,0 +1,39 @@
+//===- CppGenUtilities.cpp - MLIR cpp gen utilities --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines common utilities for generating cpp files from tablegen
+// structures.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CppGenUtilities.h"
+#include "mlir/Support/IndentedOstream.h"
+
+std::string
+mlir::tblgen::emitSummaryAndDescComments(llvm::StringRef summary,
+                                         llvm::StringRef description) {
+
+  std::string comments = "";
+  StringRef trimmedSummary = summary.trim();
+  StringRef trimmedDesc = description.trim();
+  llvm::raw_string_ostream os(comments);
+  raw_indented_ostream ros(os);
+
+  if (!trimmedSummary.empty()) {
+    ros.printReindented(trimmedSummary, "/// ");
+  }
+
+  if (!trimmedDesc.empty()) {
+    if (!trimmedSummary.empty()) {
+      // If there is a summary, add a newline after it.
+      ros << "\n";
+    }
+    ros.printReindented(trimmedDesc, "/// ");
+  }
+  return comments;
+}
diff --git a/mlir/tools/mlir-tblgen/CppGenUtilities.h b/mlir/tools/mlir-tblgen/CppGenUtilities.h
new file mode 100644
index 0000000000000..231c59a9e148f
--- /dev/null
+++ b/mlir/tools/mlir-tblgen/CppGenUtilities.h
@@ -0,0 +1,29 @@
+//===- CppGenUtilities.h - MLIR cpp gen utilities ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines common utilities for generating cpp files from tablegen
+// structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TOOLS_MLIRTBLGEN_CPPGENUTILITIES_H_
+#define MLIR_TOOLS_MLIRTBLGEN_CPPGENUTILITIES_H_
+
+#include "llvm/ADT/StringRef.h"
+
+namespace mlir {
+namespace tblgen {
+
+// Emit the summary and description as a C++ comment, perperly aligned placed
+// adjacent to the class declaration of generated classes.
+std::string emitSummaryAndDescComments(llvm::StringRef summary,
+                                       llvm::StringRef description);
+} // namespace tblgen
+} // namespace mlir
+
+#endif // MLIR_TOOLS_MLIRTBLGEN_CPPGENUTILITIES_H_
diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp
index 6cf71d2bb0174..292ff0b9daa73 100644
--- a/mlir/tools/mlir-tblgen/DialectGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectGen.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CppGenUtilities.h"
 #include "DialectGenUtilities.h"
 #include "mlir/TableGen/Class.h"
 #include "mlir/TableGen/CodeGenHelpers.h"
@@ -109,6 +110,7 @@ tblgen::findDialectToGenerate(ArrayRef<Dialect> dialects) {
 /// {1}: The dialect namespace.
 /// {2}: The dialect parent class.
 static const char *const dialectDeclBeginStr = R"(
+{3}
 class {0} : public ::mlir::{2} {
   explicit {0}(::mlir::MLIRContext *context);
 
@@ -245,8 +247,11 @@ static void emitDialectDecl(Dialect &dialect, raw_ostream &os) {
     std::string cppName = dialect.getCppClassName();
     StringRef superClassName =
         dialect.isExtensible() ? "ExtensibleDialect" : "Dialect";
+
+    std::string comments = tblgen::emitSummaryAndDescComments(
+        dialect.getSummary(), dialect.getDescription());
     os << llvm::formatv(dialectDeclBeginStr, cppName, dialect.getName(),
-                        superClassName);
+                        superClassName, comments);
 
     // If the dialect requested the default attribute printer and parser, emit
     // the declarations for the hooks.
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 3f397f3a8e6fd..373d3762cbb1a 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CppGenUtilities.h"
 #include "OpClass.h"
 #include "OpFormatGen.h"
 #include "OpGenHelpers.h"
@@ -2640,8 +2641,7 @@ void OpEmitter::genSeparateArgParamBuilder() {
 
       // Avoid emitting "resultTypes.size() >= 0u" which is always true.
       if (!hasVariadicResult || numNonVariadicResults != 0)
-        body << "  "
-             << "assert(resultTypes.size() "
+        body << "  " << "assert(resultTypes.size() "
              << (hasVariadicResult ? ">=" : "==") << " "
              << numNonVariadicResults
              << "u && \"mismatched number of results\");\n";
@@ -4749,6 +4749,11 @@ static void emitOpClassDecls(const RecordKeeper &records,
   for (auto *def : defs) {
     Operator op(*def);
     NamespaceEmitter emitter(os, op.getCppNamespace());
+    std::string comments = tblgen::emitSummaryAndDescComments(
+        op.getSummary(), op.getDescription());
+    if (!comments.empty()) {
+      os << comments << "\n";
+    }
     os << "class " << op.getCppClassName() << ";\n";
   }
 

>From 49a8491df44fc1a56b1a66759f71c159d5aaad95 Mon Sep 17 00:00:00 2001
From: Peng Chen <pchen7e2 at gmail.com>
Date: Mon, 12 May 2025 14:26:41 -0700
Subject: [PATCH 2/3] add explanation to DialectGen.cpp for readability

---
 mlir/tools/mlir-tblgen/DialectGen.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp
index 292ff0b9daa73..02941ec1268cb 100644
--- a/mlir/tools/mlir-tblgen/DialectGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectGen.cpp
@@ -109,6 +109,7 @@ tblgen::findDialectToGenerate(ArrayRef<Dialect> dialects) {
 /// {0}: The name of the dialect class.
 /// {1}: The dialect namespace.
 /// {2}: The dialect parent class.
+/// {3}: The summary and description comments.
 static const char *const dialectDeclBeginStr = R"(
 {3}
 class {0} : public ::mlir::{2} {

>From ba62b7dc51f3b507a68aac28bbbad54e5b9796af Mon Sep 17 00:00:00 2001
From: Peng Chen <pchen7e2 at gmail.com>
Date: Tue, 13 May 2025 22:16:20 -0700
Subject: [PATCH 3/3] Generate cpp comments for Attr/Op/Type Interface

Also add test cases for Attr and Enum
---
 mlir/test/mlir-tblgen/cpp-class-comments.td | 75 +++++++++++++++++++--
 mlir/tools/mlir-tblgen/OpInterfacesGen.cpp  |  9 ++-
 2 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/mlir/test/mlir-tblgen/cpp-class-comments.td b/mlir/test/mlir-tblgen/cpp-class-comments.td
index 66d7e692dee25..a896888d944b2 100644
--- a/mlir/test/mlir-tblgen/cpp-class-comments.td
+++ b/mlir/test/mlir-tblgen/cpp-class-comments.td
@@ -1,7 +1,14 @@
 // RUN: mlir-tblgen -gen-dialect-decls -I %S/../../include %s | FileCheck %s --check-prefix=DIALECT
 // RUN: mlir-tblgen -gen-op-decls -I %S/../../include %s | FileCheck %s --check-prefix=OP
 // RUN: mlir-tblgen -gen-typedef-decls -I %S/../../include %s | FileCheck %s --check-prefix=TYPE
-
+// RUN: mlir-tblgen -gen-attrdef-decls -I %S/../../include %s | FileCheck %s --check-prefix=ATTR
+// RUN: mlir-tblgen -gen-attr-interface-decls -I %S/../../include %s | FileCheck %s --check-prefix=ATTR-INTERFACE
+// RUN: mlir-tblgen -gen-op-interface-decls -I %S/../../include %s | FileCheck %s --check-prefix=OP-INTERFACE
+// RUN: mlir-tblgen -gen-type-interface-decls -I %S/../../include %s | FileCheck %s --check-prefix=TYPE-INTERFACE
+// RUN: mlir-tblgen -gen-enum-decls -I %S/../../include %s | FileCheck %s --check-prefix=ENUM
+
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/EnumAttr.td"
 include "mlir/IR/OpBase.td"
 
 // check dialect with summary and description
@@ -52,10 +59,7 @@ def A_SomeOp2 : Op<A_Dialect, "some_op2", []>{
 // OP-NEXT: class SomeOp2;
 }
 
-class AType<string name> : TypeDef<A_Dialect, name> { }
-
-
-def A_TensorType : AType<"Tensor"> {
+def A_TensorType : TypeDef<A_Dialect,"Tensor"> {
   let typeName = "a.simple_a_tensor";
 
   let summary = "Tensor Type A summary";
@@ -72,3 +76,64 @@ def A_TensorType : AType<"Tensor"> {
 // TYPE-NEXT: /// Tensor Type A description
 // TYPE-NEXT: class TensorType;
 }
+
+def A_SimpleAttr : AttrDef<A_Dialect,"SimpleA"> {
+  let attrName = "a.simple_attr";
+  let summary = "Simple Attr A summary";
+
+  let description = [{
+      Simple Attr A description
+  }];
+// ATTR: /// Simple Attr A summary
+// ATTR-NEXT: /// Simple Attr A description
+// ATTR-NEXT: class SimpleAAttr;
+}
+
+def EncodingTrait : AttrInterface<"EncodingTrait"> {
+  let cppNamespace = "mlir::a::traits";
+  let description = [{
+    Common trait for all layouts.
+  }];
+  let methods = [
+  ];
+// ATTR-INTERFACE: namespace mlir
+// ATTR-INTERFACE-NEXT: namespace a
+// ATTR-INTERFACE-NEXT: namespace traits
+// ATTR-INTERFACE-NEXT: /// Common trait for all layouts.
+// ATTR-INTERFACE-NEXT: class EncodingTrait;
+}
+
+def SimpleEncodingTrait : AttrInterface<"SimpleEncodingTrait"> {
+  let cppNamespace = "a::traits";
+// ATTR-INTERFACE: namespace a {
+// ATTR-INTERFACE-NEXT: namespace traits {
+// ATTR-INTERFACE-NEXT: class SimpleEncodingTrait;
+}
+
+def SimpleOpInterface : OpInterface<"SimpleOpInterface"> {
+  let cppNamespace = "a::traits";
+  let description = [{
+
+    Simple Op Interface description
+    }];
+// OP-INTERFACE: namespace a {
+// OP-INTERFACE-NEXT: namespace traits {
+// OP-INTERFACE-NEXT: /// Simple Op Interface description
+// OP-INTERFACE-NEXT: class SimpleOpInterface;
+}
+
+def SimpleTypeInterface : TypeInterface<"SimpleTypeInterface"> {
+  let description = [{
+    Simple Type Interface description
+  }];
+// TYPE-INTERFACE: /// Simple Type Interface description
+// TYPE-INTERFACE-NEXT: class SimpleTypeInterface;
+}
+
+def MyBitEnum: I32BitEnumAttr<"MyBitEnum", "An example bit enum",
+                           [I32BitEnumCaseBit<"Bit0", 0, "tagged">,
+                           I32BitEnumCaseBit<"Bit1", 1>]> {
+  let genSpecializedAttr = 0;
+// ENUM: // An example bit enum
+// ENUM-NEXT: enum class MyBitEnum
+}
diff --git a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
index dcd68e6c2d636..4dfa1908b3267 100644
--- a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CppGenUtilities.h"
 #include "DocGenUtilities.h"
 #include "mlir/TableGen/Format.h"
 #include "mlir/TableGen/GenInfo.h"
@@ -527,6 +528,11 @@ void InterfaceGenerator::emitInterfaceDecl(const Interface &interface) {
 
   // Emit a forward declaration of the interface class so that it becomes usable
   // in the signature of its methods.
+  std::string comments = tblgen::emitSummaryAndDescComments(
+      "", interface.getDescription().value_or(""));
+  if (!comments.empty()) {
+    os << comments << "\n";
+  }
   os << "class " << interfaceName << ";\n";
 
   // Emit the traits struct containing the concept and model declarations.
@@ -589,7 +595,8 @@ void InterfaceGenerator::emitInterfaceDecl(const Interface &interface) {
        << "    auto* interface = getInterfaceFor(base);\n"
        << "    if (!interface)\n"
           "      return false;\n"
-          "    " << interfaceName << " odsInterfaceInstance(base, interface);\n"
+          "    "
+       << interfaceName << " odsInterfaceInstance(base, interface);\n"
        << "    " << tblgen::tgfmt(extraClassOf->trim(), &extraClassOfFmt)
        << "\n  }\n";
   }



More information about the Mlir-commits mailing list