[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