[clang] [CIR][Docs][www] Generate and publish the CIR dialect reference docs (PR #232912)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 16 12:58:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Bruno Cardoso Lopes (bcardosolopes)
<details>
<summary>Changes</summary>
Wire up a consolidated CIR dialect reference page: the existing -gen-dialect-doc output (operations, types, attributes, enums) plus a passes section generated from Passes.td (-gen-pass-doc), merged ahead of the other sections with an explicit index of the page sections.
The landing page grows a "CIR Dialect Reference" section right after "Using ClangIR", showing an index into the reference page.
Also fix the doc tablegen include roots: the MLIR_*_INCLUDE_DIR variables are still empty when Clang configures (MLIR configures later), so derive the same roots from LLVM dirs instead; without this the tablegen cannot find mlir/*.td.
---
Full diff: https://github.com/llvm/llvm-project/pull/232912.diff
2 Files Affected:
- (modified) clang/docs/CIR/_raw/PostProcessCIRDocs.py (+72-19)
- (modified) clang/include/clang/CIR/Dialect/CMakeLists.txt (+7-1)
``````````diff
diff --git a/clang/docs/CIR/_raw/PostProcessCIRDocs.py b/clang/docs/CIR/_raw/PostProcessCIRDocs.py
index ca49e00773b96e..593032ec549ace 100644
--- a/clang/docs/CIR/_raw/PostProcessCIRDocs.py
+++ b/clang/docs/CIR/_raw/PostProcessCIRDocs.py
@@ -1,13 +1,18 @@
-# This script embeds MLIR generated documentations (in Markdown format) into
-# CIRLangRef_Template.md to generate CIRLangRef.md
+# This script post-processes the MLIR-generated CIR documentation (in Markdown
+# format) for the Sphinx build: it merges the passes reference into
+# CIRDialect.md ahead of the other sections, converts the [TOC] marker into
+# an index of the page sections, and appends a toctree entry to the build
+# directory copy of index.md.
import os
+import re
import sys
docs_src_dir = sys.argv[1]
docs_bin_dir = sys.argv[2]
DIALECT_DOC_PATH = os.path.join(docs_bin_dir, "CIR", "_raw", "CIRDialect.md")
+PASSES_DOC_PATH = os.path.join(docs_bin_dir, "CIR", "_raw", "CIRPasses.md")
DIALECT_DOC_OUTPUT_PATH = os.path.join(docs_bin_dir, "CIR", "CIRDialect.md")
INDEX_PATH = os.path.join(docs_src_dir, "CIR", "index.md")
@@ -18,35 +23,83 @@
# ===============================================
# Post-process CIRDialect.md
# ===============================================
+def _slugify(title):
+ slug = title.strip().lower()
+ slug = re.sub(r"\s+", "-", slug)
+ slug = re.sub(r"[^a-z0-9_-]", "", slug)
+ return slug
+
+
if os.path.exists(DIALECT_DOC_PATH):
cir_docs_toctree.append("CIRDialect")
with open(DIALECT_DOC_PATH, encoding="utf-8") as fp:
dialect_doc = fp.read()
- dialect_doc = dialect_doc.replace(
- "[TOC]",
- """
-```{contents}
----
-local:
-depth: 2
----
-```""".strip(),
- )
+ # Retitle the page: tblgen emits "# 'cir' Dialect" as the top heading.
+ dialect_doc = dialect_doc.replace("# 'cir' Dialect", "# CIR Dialect Reference", 1)
+ if os.path.exists(PASSES_DOC_PATH):
+ with open(PASSES_DOC_PATH, encoding="utf-8") as fp:
+ passes_doc = fp.read()
+ passes_doc = passes_doc.replace(
+ "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n", ""
+ )
+ insert = "\n## Passes\n" + passes_doc.strip() + "\n"
+ head, sep, rest = dialect_doc.partition("\n## ")
+ if sep:
+ dialect_doc = head.rstrip("\n") + "\n" + insert + sep + rest
+ else:
+ dialect_doc = dialect_doc.rstrip("\n") + "\n" + insert
+ # Replace the [TOC] marker with an index of the page sections so the
+ # (very long) single page stays navigable. Plain <a> links are used
+ # instead of [text](#anchor): MyST would treat the latter as
+ # cross-references and warn that the targets don't exist.
+ # Scan headings outside fenced code blocks so that ``` examples in op
+ # descriptions can never contribute bogus index entries.
+ doc_no_fences = re.sub(r"```.*?```", "", dialect_doc, flags=re.S)
+ sections = re.findall(r"^## (\S.*?)\s*$", doc_no_fences, re.M)
+ index = "\n".join(f'- <a href="#{_slugify(t)}">{t}</a>' for t in sections)
+ dialect_doc = dialect_doc.replace("[TOC]", index)
with open(DIALECT_DOC_OUTPUT_PATH, "w", encoding="utf-8") as fp:
fp.write(dialect_doc)
# ===============================================
-# Add toctree to index.md if CIR docs are generated
+# Add CIR Dialect Reference section to index.md if CIR docs are generated
# ===============================================
if len(cir_docs_toctree) > 0:
with open(INDEX_PATH, encoding="utf-8") as fp:
index_content = fp.read()
- index_content += (
- "\n\n"
- "## CIR Dialect Reference\n\n"
- "```{toctree}\n"
- ":numbered: true\n"
- ":maxdepth: 1\n\n" + "\n".join(cir_docs_toctree) + "\n```\n"
+ # Visible index into the reference page sections. Plain <a> links are
+ # used instead of [text](page#anchor): MyST would treat the latter as
+ # cross-references and warn that the targets don't exist.
+ ref_index = "\n".join(
+ f'- <a href="{page}.html#{_slugify(t)}">{t}</a>'
+ for page in cir_docs_toctree
+ for t in sections
+ )
+ # The toctree entry itself stays (Sphinx requires every document to be
+ # in a toctree) but hidden: the index above replaces the visible
+ # numbered link.
+ new_section = (
+ "CIR Dialect Reference\n\n"
+ + ref_index
+ + "\n\n```{toctree}\n:hidden:\n:maxdepth: 1\n\n"
+ + "\n".join(cir_docs_toctree)
+ + "\n```\n"
+ )
+ # Place the section right after "Using ClangIR"; fall back to appending
+ # at the end if index.md is ever restructured.
+ chunks = index_content.split("\n## ")
+ idx = next(
+ (
+ i
+ for i, c in enumerate(chunks)
+ if c == "Using ClangIR" or c.startswith("Using ClangIR\n")
+ ),
+ None,
)
+ if idx is None:
+ index_content = index_content.rstrip("\n") + "\n\n## " + new_section
+ else:
+ chunks.insert(idx + 1, new_section)
+ index_content = "\n## ".join(chunks)
with open(INDEX_OUTPUT_PATH, "w", encoding="utf-8") as fp:
fp.write(index_content)
diff --git a/clang/include/clang/CIR/Dialect/CMakeLists.txt b/clang/include/clang/CIR/Dialect/CMakeLists.txt
index bb28b7a5e81dcb..9539269cd78ee5 100644
--- a/clang/include/clang/CIR/Dialect/CMakeLists.txt
+++ b/clang/include/clang/CIR/Dialect/CMakeLists.txt
@@ -5,8 +5,12 @@ add_custom_target(clang-cir-doc)
# which is not the case for CIR (and also FIR, both have similar workarounds).
function(add_clang_mlir_doc doc_filename output_file output_directory command)
set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td)
+ # NB: MLIR_*_INCLUDE_DIR variables cannot be used here: MLIR configures
+ # after Clang, so they are still empty at this point. Derive the same
+ # roots from LLVM dirs instead (as CIR/CMakeLists.txt already does).
tablegen(MLIR ${output_file}.md ${command} ${ARGN}
- EXTRA_INCLUDES ${MLIR_MAIN_SRC_DIR} ${MLIR_INCLUDE_DIR})
+ EXTRA_INCLUDES ${LLVM_MAIN_SRC_DIR}/../mlir/include
+ ${CMAKE_BINARY_DIR}/tools/mlir/include)
set(GEN_DOC_FILE ${CLANG_BINARY_DIR}/docs/CIR/_raw/${output_directory}${output_file}.md)
add_custom_command(
OUTPUT ${GEN_DOC_FILE}
@@ -25,3 +29,5 @@ mlir_tablegen(Passes.h.inc -gen-pass-decls -name CIR)
mlir_tablegen(Passes.capi.h.inc -gen-pass-capi-header --prefix CIR)
mlir_tablegen(Passes.capi.cpp.inc -gen-pass-capi-impl --prefix CIR)
add_public_tablegen_target(MLIRCIRPassIncGen)
+
+add_clang_mlir_doc(Passes CIRPasses ./ -gen-pass-doc)
``````````
</details>
https://github.com/llvm/llvm-project/pull/232912
More information about the cfe-commits
mailing list