[Mlir-commits] [mlir] [mlir-tblgen] Render enum keyword alternatives in generated attr/type docs (PR #203677)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Jun 12 23:40:09 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-ods
@llvm/pr-subscribers-mlir
Author: Maksim Levental (makslevental)
<details>
<summary>Changes</summary>
When mlir-tblgen generates documentation for AttrDefs/TypeDefs that have EnumParameter fields, it previously rendered the raw C++ type (e.g. `::mlir::BufferAccess`) in the syntax block. This was unhelpful for users who need to know the valid keyword values.
This patch:
1. Adds an `EnumInfo enum = enumInfo;` field to the `EnumParameter` TableGen class, persisting the enum record for tooling to inspect.
2. Modifies `emitAttrOrTypeDefAssemblyFormat` in OpDocGen.cpp to detect EnumParameter fields and render their cases as backtick-quoted alternatives (e.g. `` `read` | `read_write` ``).
3. Adds a test case to gen-dialect-doc.td verifying the new behavior.
Before:
```
#kernel_arg<
int32_t, # index
::mlir::BufferAccess, # access
>
```
After:
```
#kernel_arg<
int32_t, # index
`read` | `read_write`, # access
>
```
Co-Authored-By: Claude Opus 4.6
---
Full diff: https://github.com/llvm/llvm-project/pull/203677.diff
3 Files Affected:
- (modified) mlir/include/mlir/IR/EnumAttr.td (+3)
- (modified) mlir/test/mlir-tblgen/gen-dialect-doc.td (+25)
- (modified) mlir/tools/mlir-tblgen/OpDocGen.cpp (+23-1)
``````````diff
diff --git a/mlir/include/mlir/IR/EnumAttr.td b/mlir/include/mlir/IR/EnumAttr.td
index 6eef5075fe18a..5f3384e95ba79 100644
--- a/mlir/include/mlir/IR/EnumAttr.td
+++ b/mlir/include/mlir/IR/EnumAttr.td
@@ -503,6 +503,9 @@ class I64BitEnumAttr<string name, string summary,
class EnumParameter<EnumInfo enumInfo>
: AttrParameter<enumInfo.cppNamespace # "::" # enumInfo.className,
"an enum of type " # enumInfo.className> {
+ // Store the enum info so that tooling (e.g. doc generation) can inspect the
+ // enum cases without re-parsing the C++ type string.
+ EnumInfo enum = enumInfo;
let parser = !if(!isa<EnumAttrInfo>(enumInfo),
!cast<EnumAttrInfo>(enumInfo).parameterParser, ?);
let printer = !if(!isa<EnumAttrInfo>(enumInfo),
diff --git a/mlir/test/mlir-tblgen/gen-dialect-doc.td b/mlir/test/mlir-tblgen/gen-dialect-doc.td
index 72916704369ee..c373f3fb6801b 100644
--- a/mlir/test/mlir-tblgen/gen-dialect-doc.td
+++ b/mlir/test/mlir-tblgen/gen-dialect-doc.td
@@ -67,6 +67,24 @@ def TestAttrDefParams : AttrDef<Test_Dialect, "TestAttrDefParams"> {
let assemblyFormat = "`<` $value `>`";
}
+def TestEnumForParam :
+ I32EnumAttr<"TestEnumForParam",
+ "enum for param test", [
+ I32EnumAttrCase<"Alpha", 0, "alpha">,
+ I32EnumAttrCase<"Beta", 1, "beta">]> {
+ let genSpecializedAttr = 0;
+ let cppNamespace = "NS";
+}
+
+def TestAttrWithEnum : AttrDef<Test_Dialect, "TestAttrWithEnum"> {
+ let mnemonic = "with_enum";
+ let parameters = (ins
+ "int":$value,
+ EnumParameter<TestEnumForParam>:$mode
+ );
+ let assemblyFormat = "`<` $value `,` $mode `>`";
+}
+
def TestTypeDef : TypeDef<Test_Dialect, "TestTypeDef"> {
let mnemonic = "test_type_def";
}
@@ -140,6 +158,13 @@ def TestEnum :
// CHECK: Syntax:
// CHECK: #test.test_attr_def_params
+// CHECK: TestAttrWithEnumAttr
+// CHECK: Syntax:
+// CHECK: #test.with_enum<
+// CHECK-NEXT: int, # value
+// CHECK-NEXT: `alpha` | `beta` # mode
+// CHECK-NEXT: >
+
// CHECK: ## Type constraints
// CHECK: ### type summary
// CHECK: type description
diff --git a/mlir/tools/mlir-tblgen/OpDocGen.cpp b/mlir/tools/mlir-tblgen/OpDocGen.cpp
index 5e3cf302ed3ea..7c050dbb08a3b 100644
--- a/mlir/tools/mlir-tblgen/OpDocGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDocGen.cpp
@@ -384,6 +384,25 @@ static void emitTypeDoc(const Type &type, raw_ostream &os) {
// TypeDef Documentation
//===----------------------------------------------------------------------===//
+/// If \p param is an EnumParameter, return a string listing the enum's keyword
+/// alternatives (e.g. "`read` | `read_write`"). Otherwise return std::nullopt.
+static std::optional<std::string>
+getEnumParameterDocSyntax(const AttrOrTypeParameter ¶m) {
+ const auto *paramDef = dyn_cast<DefInit>(param.getDef());
+ if (!paramDef || !paramDef->getDef()->isSubClassOf("EnumParameter"))
+ return std::nullopt;
+ const Record *enumRec = paramDef->getDef()->getValueAsDef("enum");
+ EnumInfo enumInfo(enumRec);
+ std::vector<EnumCase> cases = enumInfo.getAllCases();
+ std::string result;
+ for (const auto &caseIt : llvm::enumerate(cases)) {
+ if (caseIt.index() > 0)
+ result += " | ";
+ result += (llvm::Twine("`") + caseIt.value().getStr() + "`").str();
+ }
+ return result;
+}
+
static void emitAttrOrTypeDefAssemblyFormat(const AttrOrTypeDef &def,
raw_ostream &os) {
ArrayRef<AttrOrTypeParameter> parameters = def.getParameters();
@@ -399,7 +418,10 @@ static void emitAttrOrTypeDefAssemblyFormat(const AttrOrTypeDef &def,
<< "<\n";
for (const auto &it : llvm::enumerate(parameters)) {
const AttrOrTypeParameter ¶m = it.value();
- os << " " << param.getSyntax();
+ if (auto enumSyntax = getEnumParameterDocSyntax(param))
+ os << " " << *enumSyntax;
+ else
+ os << " " << param.getSyntax();
if (it.index() < (parameters.size() - 1))
os << ",";
os << " # " << param.getName() << "\n";
``````````
</details>
https://github.com/llvm/llvm-project/pull/203677
More information about the Mlir-commits
mailing list