Skip to content

[REFACTOR][SCRIPT] tvmscript streamline: lift printer.h, restore one-way dep, migrate dialect config to extra_config#19631

Merged
tlopex merged 5 commits into
apache:mainfrom
tqchen:tvm-tvmscript-streamline
May 28, 2026
Merged

[REFACTOR][SCRIPT] tvmscript streamline: lift printer.h, restore one-way dep, migrate dialect config to extra_config#19631
tlopex merged 5 commits into
apache:mainfrom
tqchen:tvm-tvmscript-streamline

Conversation

@tqchen
Copy link
Copy Markdown
Member

@tqchen tqchen commented May 27, 2026

Background

The tvm::ir layer previously had a reverse dependency on tvm::script, injected via the TVM_OBJECT_ENABLE_SCRIPT_PRINTER() macro that added a Script() member method to IR node types (IRModule, PrimExpr, Buffer, PrimFunc, Stmt). This violated the intended one-way dependency: script should depend on ir, never the other way around.

Additionally, PrinterConfigNode accumulated dialect-specific fields (tir_prefix, tir_import_module, tirx_prefix, relax_prefix) that created leakage between the generic printer infrastructure and dialect internals.

Changes

This PR restores the clean dependency direction and encapsulates dialect config properly, in 5 commits:

  1. Lift TVMScript entry point into script/printer/printer.h: New header include/tvm/script/printer/printer.h introduces:

    • tvm::Script() free function replacing TVMScriptPrinter::Script() static method
    • TVMScriptPrinter class with vtable (NodeFunctor<std::string(...)>)
    • TVM_REGISTER_SCRIPT_AS_REPR macro for registering per-type repr callbacks
  2. Drop TVM_OBJECT_ENABLE_SCRIPT_PRINTER macro: Remove the macro from all IR headers (ir/expr.h, ir/module.h, tirx/buffer.h, tirx/function.h, tirx/stmt.h), eliminating the reverse irscript dependency. All call sites of .Script() member methods updated to use tvm::Script().

  3. Move dialect-specific PrinterConfig fields to extra_config: Remove tir_prefix, tir_import_module, tirx_prefix, relax_prefix from PrinterConfigNode. Dialect internals now read their config via GetExtraConfig<T>(key, fallback) with dotted keys (e.g., "tirx.prefix"). buffer_dtype is kept as a top-level field alongside int_dtype/float_dtype since it is a shared scalar-literal default, not a dialect-specific knob.

  4. Python: drop dialect kwargs, expose extra_config: Update PrinterConfig, Scriptable.script(), Scriptable.show(), Scriptable._relax_script(), and BasePyModule.script() to use extra_config: dict | None = None instead of individual dialect kwargs. The tirx auto-switch logic is preserved.

  5. Fix transitive include breakage: Explicitly add direct includes for config.h and node_functor.h where headers previously relied on transitive paths through expr.h/module.h.

Testing

  • C++ unit tests: 118/118 pass
  • TVMScript printer tests: 771 passed, 1 skipped, 1 xfailed
  • TIR namespace tests (tests/python/tirx/test_printer_tir_namespaces.py): 13/13 pass
  • Relax AST printer tests: 24/24 pass
  • Minimal platform tests: 37/37 pass
  • Pre-commit (ASF headers, ruff, clang-format): all clean

tqchen added 4 commits May 27, 2026 23:09
…nter.h

Add a new public header `include/tvm/script/printer/printer.h` that
declares the free function `tvm::Script(node, optional_config)` plus
the dispatch vtable used by per-dialect printers. `PrinterConfig` and
related dataclass helpers stay in `config.h`; `printer.h` is the
entry-point header that callers include to invoke printing.

The `TVMScriptPrinter::Script(...)` static method body moves to the
free function `tvm::Script(...)` in `src/script/printer/script_printer.cc`.
`TVMScriptPrinter` class and `TVM_REGISTER_SCRIPT_AS_REPR` macro move
from `config.h` to `printer.h`.

Existing direct callers in s_tir/schedule/error.cc, script/printer/config.cc,
and script/printer/utils.h are rewritten to the new entry point.
The macro injected a `Script()` member method on IR Object types and
forced those headers to reverse-include the script printer's config.
The IR layer should not depend on the script layer; script depends on
ir.

Remove the macro from include/tvm/script/printer/config.h and drop
its 5 usages (PrimExprNode, IRModuleNode, tirx Buffer/PrimFunc/Stmt
nodes). The single C++ caller of `mod->Script()` in
src/s_tir/meta_schedule/database/json_database.cc switches to the
explicit `tvm::Script(...)` free function from
include/tvm/script/printer/printer.h.

The reverse-include of script/printer/config.h is dropped from the
five IR/tirx headers, restoring one-way dependency: script depends on
ir, never the other way.
…a_config

PrinterConfig currently has 5 dialect-specific fields (tir_prefix,
tir_import_module, tirx_prefix, relax_prefix, buffer_dtype). The first
four have zero in-tree readers and are removed entirely. The fifth,
buffer_dtype, has a single reader in src/tirx/script/printer/buffer.cc
which is rewritten to look up the value from PrinterConfig::extra_config
under the key "tirx.buffer_dtype".

After this commit, PrinterConfig's core schema is dialect-agnostic;
per-dialect customizations live in the extra_config ffi::Map.
Following the C++ PrinterConfig cleanup, drop the four dialect-specific
keyword arguments from the Python script entry points (Scriptable.script,
_relax_script, show, BasePyModule.script): tir_prefix, tir_import_module,
tirx_prefix, relax_prefix, buffer_dtype. Add a generic
extra_config: dict | None = None kwarg that maps directly to the C++
PrinterConfig.extra_config.

The auto-switch logic in Scriptable.script that detects tirx PrimFunc /
IRModule and switches to "Tx" prefix is preserved; it now stamps
extra_config["tirx.prefix"] instead of the removed tir_prefix kwarg.
Callers can suppress auto-switch or override the prefix via
extra_config={"tirx.prefix": "..."}.

Update six call sites in tests/python/tirx/ that previously passed
dialect kwargs to use extra_config={"tirx.prefix": "Tx"} instead.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the TVMScript printer configuration by removing dialect-specific fields (such as tir_prefix, relax_prefix, and buffer_dtype) from the core PrinterConfig class and introducing a generic extra_config dictionary. It also replaces the static TVMScriptPrinter::Script method with a free function tvm::Script defined in a new entry-point header. One critical issue was identified in python/tvm/runtime/script_printer.py where passing "tirx.buffer_dtype" as a string inside extra_config will cause a runtime type mismatch in C++ when downcasting to DataType. A code suggestion is provided to intercept and promote this key to the top level of the configuration dictionary so that the C++ side can parse it correctly.

Comment thread python/tvm/runtime/script_printer.py
Removing #include <tvm/script/printer/config.h> from ir/expr.h and
ir/module.h (in the macro-drop commit) broke three headers and one test
that relied on those transitively pulling in PrinterConfig and
NodeFunctor:

- include/tvm/script/printer/doc.h: add config.h (uses PrinterConfig
  in DocToPythonScript declaration)
- include/tvm/script/printer/ir_docsifier.h: add config.h (PrinterConfig
  member on IRDocsifierNode arrived via module.h → config.h)
- include/tvm/script/ir_builder/base.h: add node_functor.h (NodeFunctor
  arrived via expr.h → config.h → node_functor.h)
- tests/cpp/tir_scalable_datatype.cc: rewrite call->Script() to
  tvm::Script(call) since the Script() member was removed with
  TVM_OBJECT_ENABLE_SCRIPT_PRINTER
@tqchen tqchen force-pushed the tvm-tvmscript-streamline branch from c1fd97f to e42381b Compare May 28, 2026 15:57
@tlopex tlopex merged commit d26ea6f into apache:main May 28, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants