From 427ea4babf058e6dee467024e875be1ad7876c34 Mon Sep 17 00:00:00 2001 From: Peng Chen 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{ + 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{ + 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 : TypeDef { } + + +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 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 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 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 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{ // OP-NEXT: class SomeOp2; } -class AType : TypeDef { } - - -def A_TensorType : AType<"Tensor"> { +def A_TensorType : TypeDef { 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 { + 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"; }