Skip to content

[MLIR] Generate cpp comments for TableGen summary and description #139606

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions mlir/test/mlir-tblgen/cpp-class-comments.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// 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
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;
}

def A_TensorType : TypeDef<A_Dialect,"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;
}

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
}
9 changes: 8 additions & 1 deletion mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions mlir/tools/mlir-tblgen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ add_tablegen(mlir-tblgen MLIR
RewriterGen.cpp
SPIRVUtilsGen.cpp
TosaUtilsGen.cpp
CppGenUtilities.cpp
)

target_link_libraries(mlir-tblgen
Expand Down
39 changes: 39 additions & 0 deletions mlir/tools/mlir-tblgen/CppGenUtilities.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
29 changes: 29 additions & 0 deletions mlir/tools/mlir-tblgen/CppGenUtilities.h
Original file line number Diff line number Diff line change
@@ -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_
8 changes: 7 additions & 1 deletion mlir/tools/mlir-tblgen/DialectGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//

#include "CppGenUtilities.h"
#include "DialectGenUtilities.h"
#include "mlir/TableGen/Class.h"
#include "mlir/TableGen/CodeGenHelpers.h"
Expand Down Expand Up @@ -108,7 +109,9 @@ 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} {
explicit {0}(::mlir::MLIRContext *context);

Expand Down Expand Up @@ -245,8 +248,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.
Expand Down
9 changes: 7 additions & 2 deletions mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//

#include "CppGenUtilities.h"
#include "OpClass.h"
#include "OpFormatGen.h"
#include "OpGenHelpers.h"
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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";
}

Expand Down
9 changes: 8 additions & 1 deletion mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//

#include "CppGenUtilities.h"
#include "DocGenUtilities.h"
#include "mlir/TableGen/Format.h"
#include "mlir/TableGen/GenInfo.h"
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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";
}
Expand Down