[MLIR] Generate cpp comments for TableGen summary and description (#139606)
This commit takes the `summary` and `description` of TableGen files and generate a cpp comments on top of the declarations of generated cpp classes. The main motivation is to improve the developer experience. When people work on compilers from an IDE, they will be able to hover over the symbols (e.g. `"ADialect::BOp"`) in their cpp code and see the summary and descriptions without having to referring to the `.td` files.
This commit is contained in:
parent
5ee67ee6bc
commit
3138f6cc8c
139
mlir/test/mlir-tblgen/cpp-class-comments.td
Normal file
139
mlir/test/mlir-tblgen/cpp-class-comments.td
Normal file
@ -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
|
||||
}
|
@ -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)
|
||||
|
@ -33,6 +33,7 @@ add_tablegen(mlir-tblgen MLIR
|
||||
RewriterGen.cpp
|
||||
SPIRVUtilsGen.cpp
|
||||
TosaUtilsGen.cpp
|
||||
CppGenUtilities.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(mlir-tblgen
|
||||
|
39
mlir/tools/mlir-tblgen/CppGenUtilities.cpp
Normal file
39
mlir/tools/mlir-tblgen/CppGenUtilities.cpp
Normal file
@ -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
mlir/tools/mlir-tblgen/CppGenUtilities.h
Normal file
29
mlir/tools/mlir-tblgen/CppGenUtilities.h
Normal file
@ -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_
|
@ -10,6 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CppGenUtilities.h"
|
||||
#include "DialectGenUtilities.h"
|
||||
#include "mlir/TableGen/Class.h"
|
||||
#include "mlir/TableGen/CodeGenHelpers.h"
|
||||
@ -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);
|
||||
|
||||
@ -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.
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user