diff --git a/mlir/test/mlir-tblgen/op-interface.td b/mlir/test/mlir-tblgen/op-interface.td --- a/mlir/test/mlir-tblgen/op-interface.td +++ b/mlir/test/mlir-tblgen/op-interface.td @@ -73,6 +73,7 @@ // DECL-LABEL: TestOpInterfaceInterfaceTraits // DECL: class TestOpInterface : public ::mlir::OpInterface +// DECL: /// some function comment // DECL: int foo(int input); // DECL: template diff --git a/mlir/tools/mlir-tblgen/DocGenUtilities.h b/mlir/tools/mlir-tblgen/DocGenUtilities.h --- a/mlir/tools/mlir-tblgen/DocGenUtilities.h +++ b/mlir/tools/mlir-tblgen/DocGenUtilities.h @@ -14,9 +14,10 @@ #ifndef MLIR_TOOLS_MLIRTBLGEN_DOCGENUTILITIES_H_ #define MLIR_TOOLS_MLIRTBLGEN_DOCGENUTILITIES_H_ +#include "llvm/ADT/StringRef.h" + namespace llvm { class raw_ostream; -class StringRef; } // namespace llvm namespace mlir { @@ -30,6 +31,10 @@ // nested. void emitDescription(llvm::StringRef description, llvm::raw_ostream &os); +// Emit the description as a C++ comment while realigning it. +void emitDescriptionComment(llvm::StringRef description, llvm::raw_ostream &os, + llvm::StringRef prefix = ""); + } // namespace tblgen } // namespace mlir diff --git a/mlir/tools/mlir-tblgen/OpDocGen.cpp b/mlir/tools/mlir-tblgen/OpDocGen.cpp --- a/mlir/tools/mlir-tblgen/OpDocGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDocGen.cpp @@ -48,6 +48,24 @@ ros.printReindented(description.rtrim(" \t")); } +void mlir::tblgen::emitDescriptionComment(StringRef description, + raw_ostream &os, StringRef prefix) { + // Split the description string at newline and drop leading and trailing empty + // strings, but not the intermediate empty strings that may help with comment + // readability. + SmallVector parts; + description.split(parts, '\n'); + ArrayRef partsRef = llvm::makeArrayRef(parts); + while (!partsRef.empty() && partsRef.front().trim().empty()) { + partsRef = partsRef.drop_front(); + } + while (!partsRef.empty() && partsRef.back().trim().empty()) + partsRef = partsRef.drop_back(); + + for (StringRef part : partsRef) + os << prefix << "/// " << part.trim() << "\n"; +} + // Emits `str` with trailing newline if not empty. static void emitIfNotEmpty(StringRef str, raw_ostream &os) { if (!str.empty()) { diff --git a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp --- a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp +++ b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp @@ -158,6 +158,12 @@ // GEN: Interface definitions //===----------------------------------------------------------------------===// +static void emitInterfaceMethodDoc(const InterfaceMethod &method, + raw_ostream &os, StringRef prefix = "") { + if (Optional description = method.getDescription()) + tblgen::emitDescriptionComment(*description, os, prefix); +} + static void emitInterfaceDef(const Interface &interface, StringRef valueType, raw_ostream &os) { StringRef interfaceName = interface.getName(); @@ -167,6 +173,7 @@ // Insert the method definitions. bool isOpInterface = isa(interface); for (auto &method : interface.getMethods()) { + emitInterfaceMethodDoc(method, os); emitCPPType(method.getReturnType(), os); if (!cppNamespace.empty()) os << cppNamespace << "::"; @@ -401,6 +408,7 @@ if (!defaultImpl) continue; + emitInterfaceMethodDoc(method, os, " "); os << " " << (method.isStatic() ? "static " : ""); emitCPPType(method.getReturnType(), os); emitMethodNameAndArgs(method, os, valueType, /*addThisArg=*/false, @@ -470,6 +478,7 @@ // Insert the method declarations. bool isOpInterface = isa(interface); for (auto &method : interface.getMethods()) { + emitInterfaceMethodDoc(method, os, " "); emitCPPType(method.getReturnType(), os << " "); emitMethodNameAndArgs(method, os, valueType, /*addThisArg=*/false, /*addConst=*/!isOpInterface);