Skip to content
This repository was archived by the owner on Oct 11, 2025. It is now read-only.

Commit 13b19b3

Browse files
[MLIR][Python] Add docstring for generated python op classes (#158198)
This PR adds support in mlir-tblgen for generating docstrings for each Python class corresponding to an MLIR op. The docstrings are currently derived from the op’s description in ODS, with indentation adjusted to display nicely in Python. This makes it easier for Python users to see the op descriptions directly in their IDE or LSP while coding. In the future, we can extend the docstrings to include explanations for each method, attribute, and so on. This idea was previously discussed in the `#mlir-python` channel on Discord with makslevental and superbobry. --------- Co-authored-by: Maksim Levental <[email protected]>
1 parent 714d0d7 commit 13b19b3

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313

1414
#include "OpGenHelpers.h"
1515

16+
#include "mlir/Support/IndentedOstream.h"
1617
#include "mlir/TableGen/GenInfo.h"
1718
#include "mlir/TableGen/Operator.h"
1819
#include "llvm/ADT/StringSet.h"
1920
#include "llvm/Support/CommandLine.h"
2021
#include "llvm/Support/FormatVariadic.h"
2122
#include "llvm/TableGen/Error.h"
2223
#include "llvm/TableGen/Record.h"
24+
#include <regex>
2325

2426
using namespace mlir;
2527
using namespace mlir::tblgen;
@@ -61,10 +63,11 @@ from ._{0}_ops_gen import _Dialect
6163

6264
/// Template for operation class:
6365
/// {0} is the Python class name;
64-
/// {1} is the operation name.
66+
/// {1} is the operation name;
67+
/// {2} is the docstring for this operation.
6568
constexpr const char *opClassTemplate = R"Py(
6669
@_ods_cext.register_operation(_Dialect)
67-
class {0}(_ods_ir.OpView):
70+
class {0}(_ods_ir.OpView):{2}
6871
OPERATION_NAME = "{1}"
6972
)Py";
7073

@@ -1031,9 +1034,31 @@ static void emitValueBuilder(const Operator &op,
10311034
}
10321035
}
10331036

1037+
/// Retrieve the description of the given op and generate a docstring for it.
1038+
static std::string makeDocStringForOp(const Operator &op) {
1039+
if (!op.hasDescription())
1040+
return "";
1041+
1042+
auto desc = op.getDescription().rtrim(" \t").str();
1043+
// Replace all """ with \"\"\" to avoid early termination of the literal.
1044+
desc = std::regex_replace(desc, std::regex(R"(""")"), R"(\"\"\")");
1045+
1046+
std::string docString = "\n";
1047+
llvm::raw_string_ostream os(docString);
1048+
raw_indented_ostream identedOs(os);
1049+
os << R"( r""")" << "\n";
1050+
identedOs.printReindented(desc, " ");
1051+
if (!StringRef(desc).ends_with("\n"))
1052+
os << "\n";
1053+
os << R"( """)" << "\n";
1054+
1055+
return docString;
1056+
}
1057+
10341058
/// Emits bindings for a specific Op to the given output stream.
10351059
static void emitOpBindings(const Operator &op, raw_ostream &os) {
1036-
os << formatv(opClassTemplate, op.getCppClassName(), op.getOperationName());
1060+
os << formatv(opClassTemplate, op.getCppClassName(), op.getOperationName(),
1061+
makeDocStringForOp(op));
10371062

10381063
// Sized segments.
10391064
if (op.getTrait(attrSizedTraitForKind("operand")) != nullptr) {

0 commit comments

Comments
 (0)