forked from OSchip/llvm-project
Enable emitting dialect summary & description during op generation
Sort ops per dialect and emit summary & description (if provided) of each dialect before emitting the ops of the dialect. PiperOrigin-RevId: 273077138
This commit is contained in:
parent
18db4ce493
commit
77672c9777
|
@ -41,6 +41,20 @@ public:
|
|||
// Returns the C++ namespaces that ops of this dialect should be placed into.
|
||||
StringRef getCppNamespace() const;
|
||||
|
||||
// Returns the summary description of the dialect. Returns empty string if
|
||||
// none.
|
||||
StringRef getSummary() const;
|
||||
|
||||
// Returns the description of the dialect. Returns empty string if none.
|
||||
StringRef getDescription() const;
|
||||
|
||||
// Returns whether two dialects are equal by checking the equality of the
|
||||
// underlying record.
|
||||
bool operator==(const Dialect &other) const;
|
||||
|
||||
// Compares two dialects by comparing the names of the dialects.
|
||||
bool operator<(const Dialect &other) const;
|
||||
|
||||
private:
|
||||
const llvm::Record &def;
|
||||
};
|
||||
|
|
|
@ -161,6 +161,9 @@ public:
|
|||
// not provide enough methods.
|
||||
const llvm::Record &getDef() const;
|
||||
|
||||
// Returns the dialect of the op.
|
||||
const Dialect &getDialect() const { return dialect; }
|
||||
|
||||
private:
|
||||
// Populates the vectors containing operands, attributes, results and traits.
|
||||
void populateOpStructure();
|
||||
|
|
|
@ -33,5 +33,31 @@ StringRef tblgen::Dialect::getCppNamespace() const {
|
|||
return def.getValueAsString("cppNamespace");
|
||||
}
|
||||
|
||||
static StringRef getAsStringOrEmpty(const llvm::Record &record,
|
||||
StringRef fieldName) {
|
||||
if (auto valueInit = record.getValueInit(fieldName)) {
|
||||
if (llvm::isa<llvm::CodeInit>(valueInit) ||
|
||||
llvm::isa<llvm::StringInit>(valueInit))
|
||||
return record.getValueAsString(fieldName);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
StringRef tblgen::Dialect::getSummary() const {
|
||||
return getAsStringOrEmpty(def, "summary");
|
||||
}
|
||||
|
||||
StringRef tblgen::Dialect::getDescription() const {
|
||||
return getAsStringOrEmpty(def, "description");
|
||||
}
|
||||
|
||||
bool Dialect::operator==(const Dialect &other) const {
|
||||
return &def == &other.def;
|
||||
}
|
||||
|
||||
bool Dialect::operator<(const Dialect &other) const {
|
||||
return getName() < other.getName();
|
||||
}
|
||||
|
||||
} // end namespace tblgen
|
||||
} // end namespace mlir
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "DocGenUtilities.h"
|
||||
#include "mlir/TableGen/GenInfo.h"
|
||||
#include "mlir/TableGen/Operator.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
|
@ -32,6 +33,7 @@
|
|||
|
||||
using namespace llvm;
|
||||
using namespace mlir;
|
||||
using namespace mlir::tblgen;
|
||||
|
||||
using mlir::tblgen::Operator;
|
||||
|
||||
|
@ -77,29 +79,39 @@ void mlir::tblgen::emitDescription(StringRef description, raw_ostream &os) {
|
|||
}
|
||||
}
|
||||
|
||||
static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
|
||||
const auto &defs = recordKeeper.getAllDerivedDefinitions("Op");
|
||||
os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
|
||||
// Emits `str` with trailing newline if not empty.
|
||||
static void emitIfNotEmpty(StringRef str, raw_ostream &os) {
|
||||
if (!str.empty()) {
|
||||
emitDescription(str, os);
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Group by dialect.
|
||||
// TODO: Add docs for types used (maybe dialect specific ones?) and link
|
||||
// between use and def.
|
||||
os << "# Operation definition\n";
|
||||
for (auto *def : defs) {
|
||||
Operator op(def);
|
||||
os << "## " << op.getOperationName() << " (" << op.getQualCppClassName()
|
||||
static void emitOpDocForDialect(const Dialect &dialect,
|
||||
const std::vector<Operator> &ops,
|
||||
raw_ostream &os) {
|
||||
os << "# Dialect '" << dialect.getName() << "' definition\n";
|
||||
emitIfNotEmpty(dialect.getSummary(), os);
|
||||
emitIfNotEmpty(dialect.getDescription(), os);
|
||||
|
||||
// TODO(antiagainst): Add docs for types used (maybe dialect specific ones?)
|
||||
// and link between use and def.
|
||||
|
||||
os << "## Operation definition\n";
|
||||
for (auto op : ops) {
|
||||
os << "### " << op.getOperationName() << " (" << op.getQualCppClassName()
|
||||
<< ")";
|
||||
|
||||
// Emit summary & description of operator.
|
||||
if (op.hasSummary())
|
||||
os << "\n" << op.getSummary() << "\n";
|
||||
os << "\n### Description:\n";
|
||||
os << "\n#### Description:\n";
|
||||
if (op.hasDescription())
|
||||
mlir::tblgen::emitDescription(op.getDescription(), os);
|
||||
|
||||
// Emit operands & type of operand. All operands are numbered, some may be
|
||||
// named too.
|
||||
os << "\n### Operands:\n";
|
||||
os << "\n#### Operands:\n";
|
||||
for (const auto &operand : op.getOperands()) {
|
||||
os << "1. ";
|
||||
if (!operand.name.empty())
|
||||
|
@ -112,7 +124,7 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
|
|||
// Emit attributes.
|
||||
// TODO: Attributes are only documented by TableGen name, with no further
|
||||
// info. This should be improved.
|
||||
os << "\n### Attributes:\n";
|
||||
os << "\n#### Attributes:\n";
|
||||
if (op.getNumAttributes() > 0) {
|
||||
os << "| Attribute | MLIR Type | Description |\n"
|
||||
<< "| :-------: | :-------: | ----------- |\n";
|
||||
|
@ -124,7 +136,7 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
|
|||
}
|
||||
|
||||
// Emit results.
|
||||
os << "\n### Results:\n";
|
||||
os << "\n#### Results:\n";
|
||||
for (unsigned i = 0, e = op.getNumResults(); i < e; ++i) {
|
||||
os << "1. ";
|
||||
auto name = op.getResultName(i);
|
||||
|
@ -139,6 +151,19 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
|
|||
}
|
||||
}
|
||||
|
||||
static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
|
||||
const auto &defs = recordKeeper.getAllDerivedDefinitions("Op");
|
||||
os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
|
||||
|
||||
std::map<Dialect, std::vector<Operator>> dialectOps;
|
||||
for (auto *def : defs) {
|
||||
Operator op(def);
|
||||
dialectOps[op.getDialect()].push_back(op);
|
||||
}
|
||||
for (auto dialectWithOps : dialectOps)
|
||||
emitOpDocForDialect(dialectWithOps.first, dialectWithOps.second, os);
|
||||
}
|
||||
|
||||
static mlir::GenRegistration
|
||||
genRegister("gen-op-doc", "Generate operation documentation",
|
||||
[](const RecordKeeper &records, raw_ostream &os) {
|
||||
|
|
Loading…
Reference in New Issue