This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 11ac2ad97c [REFACTOR][NODE] Use fn_repr inside kRepr lambdas, not
ffi::ReprPrint (#19462)
11ac2ad97c is described below
commit 11ac2ad97c84fdc6ca14690a6221e9f3d1631955
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Apr 27 20:27:20 2026 -0400
[REFACTOR][NODE] Use fn_repr inside kRepr lambdas, not ffi::ReprPrint
(#19462)
---
src/relax/ir/dataflow_pattern.cc | 29 +++++++++++++++++------------
src/s_tir/meta_schedule/arg_info.cc | 2 +-
src/target/virtual_device.cc | 4 ++--
3 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/src/relax/ir/dataflow_pattern.cc b/src/relax/ir/dataflow_pattern.cc
index 90a8379236..ed400b82bf 100644
--- a/src/relax/ir/dataflow_pattern.cc
+++ b/src/relax/ir/dataflow_pattern.cc
@@ -62,22 +62,27 @@ TVM_FFI_STATIC_INIT_BLOCK() {
// Helper used inside RELAX_PATTERN_PRINTER_DEF lambdas.
// Mimics the ReprPrinter interface (p->stream, p->Print) so that existing
// REPR_LAMBDA bodies compile without modification.
+// fn_repr is the canonical dispatch callback from the kRepr machinery; Print
+// routes through it rather than calling ffi::ReprPrint directly so that any
+// recursion context threaded by the printer is preserved.
struct PatternReprPrinterHelper {
std::ostringstream stream;
- void Print(const ObjectRef& x) { stream << ffi::ReprPrint(ffi::Any(x)); }
+ ffi::Function fn_repr;
+ explicit PatternReprPrinterHelper(ffi::Function fn_repr_) :
fn_repr(std::move(fn_repr_)) {}
+ void Print(const ObjectRef& x) { stream <<
fn_repr(ffi::AnyView(x)).cast<ffi::String>(); }
};
-#define RELAX_PATTERN_PRINTER_DEF(NODE_TYPE, REPR_LAMBDA)
\
- TVM_FFI_STATIC_INIT_BLOCK() {
\
- namespace refl = tvm::ffi::reflection;
\
- refl::TypeAttrDef<NODE_TYPE>().def(refl::type_attr::kRepr,
\
- [](ffi::ObjectRef ref, ffi::Function)
-> ffi::String { \
- auto* node = static_cast<const
NODE_TYPE*>(ref.get()); \
- PatternReprPrinterHelper printer;
\
- auto* p = &printer;
\
- REPR_LAMBDA(p, node);
\
- return printer.stream.str();
\
- });
\
+#define RELAX_PATTERN_PRINTER_DEF(NODE_TYPE, REPR_LAMBDA)
\
+ TVM_FFI_STATIC_INIT_BLOCK() {
\
+ namespace refl = tvm::ffi::reflection;
\
+ refl::TypeAttrDef<NODE_TYPE>().def(
\
+ refl::type_attr::kRepr, [](ffi::ObjectRef ref, ffi::Function fn_repr)
-> ffi::String { \
+ auto* node = static_cast<const NODE_TYPE*>(ref.get());
\
+ PatternReprPrinterHelper printer(fn_repr);
\
+ auto* p = &printer;
\
+ REPR_LAMBDA(p, node);
\
+ return printer.stream.str();
\
+ });
\
}
ExternFuncPattern::ExternFuncPattern(ffi::String global_symbol) {
diff --git a/src/s_tir/meta_schedule/arg_info.cc
b/src/s_tir/meta_schedule/arg_info.cc
index bcb2fd81c6..8d31146a80 100644
--- a/src/s_tir/meta_schedule/arg_info.cc
+++ b/src/s_tir/meta_schedule/arg_info.cc
@@ -158,7 +158,7 @@ TensorInfo TensorInfo::FromJSON(const ObjectRef& json_obj) {
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::TypeAttrDef<TensorInfoNode>().def(refl::type_attr::kRepr,
- [](TensorInfo ti, ffi::Function) ->
ffi::String {
+ [](TensorInfo ti, ffi::Function
fn_repr) -> ffi::String {
std::ostringstream os;
os << "TensorInfo(\"" << ti->dtype
<< "\", [";
bool first = true;
diff --git a/src/target/virtual_device.cc b/src/target/virtual_device.cc
index c17298fdfd..c7357d7f14 100644
--- a/src/target/virtual_device.cc
+++ b/src/target/virtual_device.cc
@@ -35,7 +35,7 @@ TVM_FFI_STATIC_INIT_BLOCK() {
VirtualDeviceNode::RegisterReflection(); }
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::TypeAttrDef<VirtualDeviceNode>().def(
- refl::type_attr::kRepr, [](VirtualDevice vd, ffi::Function) ->
ffi::String {
+ refl::type_attr::kRepr, [](VirtualDevice vd, ffi::Function fn_repr) ->
ffi::String {
auto* node = vd.get();
std::ostringstream os;
os << "VirtualDevice(";
@@ -54,7 +54,7 @@ TVM_FFI_STATIC_INIT_BLOCK() {
}
if (node->target.defined()) {
if (need_sep) os << ", ";
- os << "target=" << node->target->str();
+ os << "target=" <<
fn_repr(ffi::AnyView(node->target)).cast<ffi::String>();
need_sep = true;
}
if (!node->memory_scope.empty()) {