Skip to content

Commit f091848

Browse files
authored
Add support for enum doc gen (#98885)
1 parent 4eb30cf commit f091848

File tree

2 files changed

+86
-9
lines changed

2 files changed

+86
-9
lines changed

mlir/test/mlir-tblgen/gen-dialect-doc.td

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
include "mlir/IR/OpBase.td"
55
include "mlir/IR/AttrTypeBase.td"
6+
include "mlir/IR/EnumAttr.td"
67
include "mlir/Interfaces/SideEffectInterfaces.td"
78

89
def Test_Dialect : Dialect {
@@ -69,6 +70,16 @@ def TestTypeDefParams : TypeDef<Test_Dialect, "TestTypeDefParams"> {
6970
let assemblyFormat = "`<` $value `>`";
7071
}
7172

73+
def TestEnum :
74+
I32EnumAttr<"TestEnum",
75+
"enum summary", [
76+
I32EnumAttrCase<"First", 0, "first">,
77+
I32EnumAttrCase<"Second", 1, "second">,
78+
I32EnumAttrCase<"Third", 2, "third">]> {
79+
let genSpecializedAttr = 1;
80+
let cppNamespace = "NS";
81+
}
82+
7283
// CHECK: Dialect without a [TOC] here.
7384
// CHECK: TOC added by tool.
7485
// CHECK: [TOC]
@@ -109,6 +120,16 @@ def TestTypeDefParams : TypeDef<Test_Dialect, "TestTypeDefParams"> {
109120
// CHECK: Syntax:
110121
// CHECK: !test.test_type_def_params
111122

123+
// CHECK: ## Enums
124+
// CHECK: ### TestEnum
125+
// CHECK: enum summary
126+
// CHECK: #### Cases:
127+
// CHECK: | Symbol | Value | String |
128+
// CHECK: | :----: | :---: | ------ |
129+
// CHECK: | First | `0` | first |
130+
// CHECK: | Second | `1` | second |
131+
// CHECK: | Third | `2` | third |
132+
112133
def Toc_Dialect : Dialect {
113134
let name = "test_toc";
114135
let summary = "Dialect of ops to test";

mlir/tools/mlir-tblgen/OpDocGen.cpp

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "OpGenHelpers.h"
1717
#include "mlir/Support/IndentedOstream.h"
1818
#include "mlir/TableGen/AttrOrTypeDef.h"
19+
#include "mlir/TableGen/Attribute.h"
1920
#include "mlir/TableGen/GenInfo.h"
2021
#include "mlir/TableGen/Operator.h"
2122
#include "llvm/ADT/DenseMap.h"
@@ -37,7 +38,7 @@
3738
// Commandline Options
3839
//===----------------------------------------------------------------------===//
3940
static llvm::cl::OptionCategory
40-
docCat("Options for -gen-(attrdef|typedef|op|dialect)-doc");
41+
docCat("Options for -gen-(attrdef|typedef|enum|op|dialect)-doc");
4142
llvm::cl::opt<std::string>
4243
stripPrefix("strip-prefix",
4344
llvm::cl::desc("Strip prefix of the fully qualified names"),
@@ -228,8 +229,7 @@ static void emitOpDoc(const Operator &op, raw_ostream &os) {
228229
// Expandable description.
229230
// This appears as just the summary, but when clicked shows the full
230231
// description.
231-
os << "<details>"
232-
<< "<summary>" << it.attr.getSummary() << "</summary>"
232+
os << "<details>" << "<summary>" << it.attr.getSummary() << "</summary>"
233233
<< "{{% markdown %}}" << description << "{{% /markdown %}}"
234234
<< "</details>";
235235
} else {
@@ -381,6 +381,39 @@ static void emitAttrOrTypeDefDoc(const RecordKeeper &recordKeeper,
381381
emitAttrOrTypeDefDoc(AttrOrTypeDef(def), os);
382382
}
383383

384+
//===----------------------------------------------------------------------===//
385+
// Enum Documentation
386+
//===----------------------------------------------------------------------===//
387+
388+
static void emitEnumDoc(const EnumAttr &def, raw_ostream &os) {
389+
os << llvm::formatv("### {0}\n", def.getEnumClassName());
390+
391+
// Emit the summary if present.
392+
if (!def.getSummary().empty())
393+
os << "\n" << def.getSummary() << "\n";
394+
395+
// Emit case documentation.
396+
std::vector<EnumAttrCase> cases = def.getAllCases();
397+
os << "\n#### Cases:\n\n";
398+
os << "| Symbol | Value | String |\n"
399+
<< "| :----: | :---: | ------ |\n";
400+
for (const auto &it : cases) {
401+
os << "| " << it.getSymbol() << " | `" << it.getValue() << "` | "
402+
<< it.getStr() << " |\n";
403+
}
404+
405+
os << "\n";
406+
}
407+
408+
static void emitEnumDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
409+
std::vector<llvm::Record *> defs =
410+
recordKeeper.getAllDerivedDefinitions("EnumAttr");
411+
412+
os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
413+
for (const llvm::Record *def : defs)
414+
emitEnumDoc(EnumAttr(def), os);
415+
}
416+
384417
//===----------------------------------------------------------------------===//
385418
// Dialect Documentation
386419
//===----------------------------------------------------------------------===//
@@ -413,7 +446,7 @@ static void maybeNest(bool nest, llvm::function_ref<void(raw_ostream &os)> fn,
413446
static void emitBlock(ArrayRef<Attribute> attributes, StringRef inputFilename,
414447
ArrayRef<AttrDef> attrDefs, ArrayRef<OpDocGroup> ops,
415448
ArrayRef<Type> types, ArrayRef<TypeDef> typeDefs,
416-
raw_ostream &os) {
449+
ArrayRef<EnumAttr> enums, raw_ostream &os) {
417450
if (!ops.empty()) {
418451
os << "## Operations\n\n";
419452
emitSourceLink(inputFilename, os);
@@ -459,13 +492,19 @@ static void emitBlock(ArrayRef<Attribute> attributes, StringRef inputFilename,
459492
for (const TypeDef &def : typeDefs)
460493
emitAttrOrTypeDefDoc(def, os);
461494
}
495+
496+
if (!enums.empty()) {
497+
os << "## Enums\n\n";
498+
for (const EnumAttr &def : enums)
499+
emitEnumDoc(def, os);
500+
}
462501
}
463502

464503
static void emitDialectDoc(const Dialect &dialect, StringRef inputFilename,
465504
ArrayRef<Attribute> attributes,
466505
ArrayRef<AttrDef> attrDefs, ArrayRef<OpDocGroup> ops,
467506
ArrayRef<Type> types, ArrayRef<TypeDef> typeDefs,
468-
raw_ostream &os) {
507+
ArrayRef<EnumAttr> enums, raw_ostream &os) {
469508
os << "# '" << dialect.getName() << "' Dialect\n\n";
470509
emitIfNotEmpty(dialect.getSummary(), os);
471510
emitIfNotEmpty(dialect.getDescription(), os);
@@ -475,7 +514,8 @@ static void emitDialectDoc(const Dialect &dialect, StringRef inputFilename,
475514
if (!r.match(dialect.getDescription()))
476515
os << "[TOC]\n\n";
477516

478-
emitBlock(attributes, inputFilename, attrDefs, ops, types, typeDefs, os);
517+
emitBlock(attributes, inputFilename, attrDefs, ops, types, typeDefs, enums,
518+
os);
479519
}
480520

481521
static bool emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
@@ -495,21 +535,27 @@ static bool emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
495535
recordKeeper.getAllDerivedDefinitionsIfDefined("TypeDef");
496536
std::vector<Record *> attrDefDefs =
497537
recordKeeper.getAllDerivedDefinitionsIfDefined("AttrDef");
538+
std::vector<Record *> enumDefs =
539+
recordKeeper.getAllDerivedDefinitionsIfDefined("EnumAttrInfo");
498540

499541
std::vector<Attribute> dialectAttrs;
500542
std::vector<AttrDef> dialectAttrDefs;
501543
std::vector<OpDocGroup> dialectOps;
502544
std::vector<Type> dialectTypes;
503545
std::vector<TypeDef> dialectTypeDefs;
546+
std::vector<EnumAttr> dialectEnums;
504547

505548
llvm::SmallDenseSet<Record *> seen;
506-
auto addIfInDialect = [&](llvm::Record *record, const auto &def, auto &vec) {
507-
if (seen.insert(record).second && def.getDialect() == *dialect) {
549+
auto addIfNotSeen = [&](llvm::Record *record, const auto &def, auto &vec) {
550+
if (seen.insert(record).second) {
508551
vec.push_back(def);
509552
return true;
510553
}
511554
return false;
512555
};
556+
auto addIfInDialect = [&](llvm::Record *record, const auto &def, auto &vec) {
557+
return def.getDialect() == *dialect && addIfNotSeen(record, def, vec);
558+
};
513559

514560
SmallDenseMap<Record *, OpDocGroup> opDocGroup;
515561

@@ -539,6 +585,9 @@ static bool emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
539585
addIfInDialect(def, TypeDef(def), dialectTypeDefs);
540586
for (Record *def : typeDefs)
541587
addIfInDialect(def, Type(def), dialectTypes);
588+
dialectEnums.reserve(enumDefs.size());
589+
for (Record *def : enumDefs)
590+
addIfNotSeen(def, EnumAttr(def), dialectEnums);
542591

543592
// Sort alphabetically ignorning dialect for ops and section name for
544593
// sections.
@@ -557,7 +606,7 @@ static bool emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
557606
os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
558607
emitDialectDoc(*dialect, recordKeeper.getInputFilename(), dialectAttrs,
559608
dialectAttrDefs, dialectOps, dialectTypes, dialectTypeDefs,
560-
os);
609+
dialectEnums, os);
561610
return false;
562611
}
563612

@@ -587,6 +636,13 @@ static mlir::GenRegistration
587636
return false;
588637
});
589638

639+
static mlir::GenRegistration
640+
genEnumRegister("gen-enum-doc", "Generate dialect enum documentation",
641+
[](const RecordKeeper &records, raw_ostream &os) {
642+
emitEnumDoc(records, os);
643+
return false;
644+
});
645+
590646
static mlir::GenRegistration
591647
genRegister("gen-dialect-doc", "Generate dialect documentation",
592648
[](const RecordKeeper &records, raw_ostream &os) {

0 commit comments

Comments
 (0)