This is an automated email from the ASF dual-hosted git repository.

wuwei 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 94a44d7d62 [QoL][Relax] Return well-formed IR from 
relax::Function::CreateEmpty (#16861)
94a44d7d62 is described below

commit 94a44d7d62206849b891c1c262843d88bfb54c3b
Author: Eric Lunderberg <lunderb...@users.noreply.github.com>
AuthorDate: Tue Apr 16 16:26:54 2024 -0500

    [QoL][Relax] Return well-formed IR from relax::Function::CreateEmpty 
(#16861)
    
    Prior to this commit, the static method `relax::Function::CreateEmpty`
    returned a function with a nullptr as the body.  While only intended for 
use in
    bookkeeping for TVMScript, allowing nullptr in this location can cause
    unexpected segfaults while debugging.  For example, adding a print
    statement
    
    This commit updates the `relax::Function::CreateEmpty` function to
    contain a placeholder body, consistent with the `ret_struct_info`
    argument provided.
---
 include/tvm/relax/expr.h |  2 ++
 src/relax/ir/expr.cc     | 24 +++++++++++++++++++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/include/tvm/relax/expr.h b/include/tvm/relax/expr.h
index 40707675fe..e2176cf720 100644
--- a/include/tvm/relax/expr.h
+++ b/include/tvm/relax/expr.h
@@ -1045,6 +1045,8 @@ class ExternFuncNode : public BaseFuncNode {
 class ExternFunc : public BaseFunc {
  public:
   TVM_DLL ExternFunc(String global_symbol, Span span = Span());
+  TVM_DLL ExternFunc(String global_symbol, StructInfo struct_info, Span span = 
Span());
+
   TVM_DEFINE_OBJECT_REF_METHODS(ExternFunc, BaseFunc, ExternFuncNode);
   TVM_DEFINE_OBJECT_REF_COW_METHOD(ExternFuncNode);
 };
diff --git a/src/relax/ir/expr.cc b/src/relax/ir/expr.cc
index 1b5551e509..0530bb770b 100644
--- a/src/relax/ir/expr.cc
+++ b/src/relax/ir/expr.cc
@@ -559,10 +559,18 @@ Function Function::CreateEmpty(Array<Var> params, 
StructInfo ret_struct_info, bo
 
   FuncStructInfo finfo(param_sinfo, ret_struct_info, is_pure);
 
+  // A dummy body, to ensure that the empty function is still well-formed.
+  Expr body = [&]() -> Expr {
+    Var output("output", ret_struct_info);
+    Call expr(ExternFunc("_dummy_function", FuncStructInfo({}, 
ret_struct_info)), {});
+
+    return SeqExpr({BindingBlock({VarBinding(output, expr)})}, output);
+  }();
+
   // set the fields
   ObjectPtr<FunctionNode> n = make_object<FunctionNode>();
   n->params = std::move(params);
-  n->body = Expr();
+  n->body = std::move(body);
   n->is_pure = is_pure;
   n->checked_type_ = GetStaticType(finfo);
   n->struct_info_ = std::move(finfo);
@@ -602,13 +610,19 @@ FuncStructInfo GetExternFuncStructInfo() {
 
 TVM_REGISTER_NODE_TYPE(ExternFuncNode);
 
-ExternFunc::ExternFunc(String global_symbol, Span span) {
+ExternFunc::ExternFunc(String global_symbol, Span span)
+    : ExternFunc(global_symbol, GetExternFuncStructInfo(), span) {}
+
+ExternFunc::ExternFunc(String global_symbol, StructInfo struct_info, Span 
span) {
+  CHECK(struct_info.as<FuncStructInfoNode>())
+      << "ExternFunc must have FuncStructInfo, "
+      << "but declaration of '" << global_symbol << "' received " << 
struct_info;
+
   ObjectPtr<ExternFuncNode> n = make_object<ExternFuncNode>();
   n->global_symbol = std::move(global_symbol);
   n->span = span;
-  static auto sinfo = GetExternFuncStructInfo();
-  n->struct_info_ = sinfo;
-  n->checked_type_ = GetStaticType(sinfo);
+  n->struct_info_ = struct_info;
+  n->checked_type_ = GetStaticType(struct_info);
   data_ = std::move(n);
 }
 

Reply via email to