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

tqchen pushed a commit to branch refactor-s2
in repository https://gitbox.apache.org/repos/asf/tvm.git

commit aa7b897f2929a40196c3b1aaf91e475a308e310c
Author: tqchen <[email protected]>
AuthorDate: Sun Apr 20 20:49:10 2025 -0400

    Upgrade error reporting mechanism ABI to new FFI.
---
 src/runtime/library_module.cc                    |  2 +-
 src/runtime/thread_pool.cc                       | 16 ++++++----
 src/target/llvm/codegen_cpu.cc                   | 38 ++++++++++++------------
 src/target/llvm/codegen_cpu.h                    | 12 ++++----
 tests/python/codegen/test_target_codegen_llvm.py | 19 ++++++++++++
 5 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/src/runtime/library_module.cc b/src/runtime/library_module.cc
index a8a66b21cb..4d1520f7a2 100644
--- a/src/runtime/library_module.cc
+++ b/src/runtime/library_module.cc
@@ -83,7 +83,7 @@ void InitContextFunctions(std::function<void*(const char*)> 
fgetsymbol) {
   }
   // Initialize the functions
   TVM_INIT_CONTEXT_FUNC(TVMFFIFuncCall);
-  TVM_INIT_CONTEXT_FUNC(TVMAPISetLastError);
+  TVM_INIT_CONTEXT_FUNC(TVMFFISetLastErrorCStr);
   TVM_INIT_CONTEXT_FUNC(TVMBackendGetFuncFromEnv);
   TVM_INIT_CONTEXT_FUNC(TVMBackendAllocWorkspace);
   TVM_INIT_CONTEXT_FUNC(TVMBackendFreeWorkspace);
diff --git a/src/runtime/thread_pool.cc b/src/runtime/thread_pool.cc
index 74f87934e7..40bfdc9d11 100644
--- a/src/runtime/thread_pool.cc
+++ b/src/runtime/thread_pool.cc
@@ -103,18 +103,22 @@ class ParallelLauncher {
     if (!has_error_.load()) return 0;
     std::ostringstream os;
     for (size_t i = 0; i < par_errors_.size(); ++i) {
-      if (par_errors_[i].length() != 0) {
-        os << "Task " << i << " error: " << par_errors_[i] << '\n';
-        par_errors_[i].clear();
+      if (par_errors_[i] != nullptr) {
+        if (std::optional<tvm::ffi::Error> error = 
par_errors_[i].as<tvm::ffi::Error>()) {
+          os << "Task " << i << " error: " << (*error).what();
+        } else {
+          os << "Task " << i << " RuntimeError";
+        }
+        par_errors_[i] = nullptr;
       }
     }
-    TVMAPISetLastError(os.str().c_str());
+    TVMFFISetLastErrorCStr("RuntimeError", os.str().c_str());
     return -1;
   }
   // Signal that one job has finished.
   void SignalJobError(int task_id) {
     num_pending_.fetch_sub(1);
-    par_errors_[task_id] = TVMGetLastError();
+    
TVMFFIMoveFromLastError(reinterpret_cast<TVMFFIAny*>(&par_errors_[task_id]));
     has_error_.store(true);
   }
   // Signal that one job has finished.
@@ -139,7 +143,7 @@ class ParallelLauncher {
   // The counter page.
   std::atomic<int32_t>* sync_counter_{nullptr};
   // The error message
-  std::vector<std::string> par_errors_;
+  std::vector<Any> par_errors_;
 };
 
 /*! \brief Lock-free single-producer-single-consumer queue for each thread */
diff --git a/src/target/llvm/codegen_cpu.cc b/src/target/llvm/codegen_cpu.cc
index 83b07b14e9..b9941ff904 100644
--- a/src/target/llvm/codegen_cpu.cc
+++ b/src/target/llvm/codegen_cpu.cc
@@ -120,15 +120,15 @@ void CodeGenCPU::Init(const std::string& module_name, 
LLVMTarget* llvm_target,
   // int TVMFFIFuncCall(TVMFunctionHandle func, TVMFFIAny* args, int32_t 
num_args,
   //                    TVMFFIAny* result);
   ftype_tvm_ffi_func_call_ = ftype_tvm_ffi_c_func_;
+  // Defined in include/tvm/ffi/c_api.h:
+  // void TVMFFISetLastErrorCStr(const char *kind, const char* msg);
+  ftype_tvm_ffi_set_last_error_c_str_ = llvm::FunctionType::get(
+      t_void_, {llvmGetPointerTo(t_char_, 0), llvmGetPointerTo(t_char_, 0)}, 
false);
   // Defined in include/tvm/runtime/c_backend_api.h:
   // int TVMBackendGetFuncFromEnv(void* mod_node, const char* func_name, 
TVMFunctionHandle* out);
   ftype_tvm_get_func_from_env_ = llvm::FunctionType::get(
       t_int_, {t_void_p_, llvmGetPointerTo(t_char_, 0), 
llvmGetPointerTo(t_tvm_func_handle_, 0)},
       false);
-  // Defined in include/tvm/runtime/c_runtime_api.h:
-  // void TVMAPISetLastError(const char* msg);
-  ftype_tvm_api_set_last_error_ =
-      llvm::FunctionType::get(t_void_, {llvmGetPointerTo(t_char_, 0)}, false);
   // Defined in include/tvm/runtime/c_backend_api.h:
   // int TVMBackendParallelLaunch(FTVMParallelLambda flambda, void* cdata, int 
num_task);
   ftype_tvm_parallel_launch_ = llvm::FunctionType::get(
@@ -157,9 +157,9 @@ void CodeGenCPU::Init(const std::string& module_name, 
LLVMTarget* llvm_target,
   if (dynamic_lookup || system_lib_prefix_.defined()) {
     f_tvm_ffi_func_call_ = llvm::Function::Create(
         ftype_tvm_ffi_func_call_, llvm::Function::ExternalLinkage, 
"TVMFFIFuncCall", module_.get());
-    f_tvm_api_set_last_error_ =
-        llvm::Function::Create(ftype_tvm_api_set_last_error_, 
llvm::Function::ExternalLinkage,
-                               "TVMAPISetLastError", module_.get());
+    f_tvm_ffi_set_last_error_c_str_ =
+        llvm::Function::Create(ftype_tvm_ffi_set_last_error_c_str_, 
llvm::Function::ExternalLinkage,
+                               "TVMFFISetLastErrorCStr", module_.get());
     f_tvm_get_func_from_env_ =
         llvm::Function::Create(ftype_tvm_get_func_from_env_, 
llvm::Function::ExternalLinkage,
                                "TVMBackendGetFuncFromEnv", module_.get());
@@ -443,12 +443,12 @@ void CodeGenCPU::InitGlobalContext(bool dynamic_lookup) {
     export_system_symbols_.emplace_back(std::make_pair(ctx_symbol, 
gv_mod_ctx_));
   } else {
     if (!dynamic_lookup) {
-      gv_tvm_func_call_ =
+      gv_tvm_ffi_func_call_ =
           InitContextPtr(llvmGetPointerTo(ftype_tvm_ffi_func_call_, 0), 
"__TVMFFIFuncCall");
       gv_tvm_get_func_from_env_ = 
InitContextPtr(llvmGetPointerTo(ftype_tvm_get_func_from_env_, 0),
                                                  "__TVMBackendGetFuncFromEnv");
-      gv_tvm_api_set_last_error_ = InitContextPtr(
-          llvmGetPointerTo(ftype_tvm_api_set_last_error_, 0), 
"__TVMAPISetLastError");
+      gv_tvm_ffi_set_last_error_c_str_ = InitContextPtr(
+          llvmGetPointerTo(ftype_tvm_ffi_set_last_error_c_str_, 0), 
"__TVMFFISetLastErrorCStr");
       gv_tvm_parallel_launch_ = 
InitContextPtr(llvmGetPointerTo(ftype_tvm_parallel_launch_, 0),
                                                "__TVMBackendParallelLaunch");
       gv_tvm_parallel_barrier_ = 
InitContextPtr(llvmGetPointerTo(ftype_tvm_parallel_barrier_, 0),
@@ -833,7 +833,7 @@ CodeGenCPU::PackedCall 
CodeGenCPU::MakeCallPackedLowered(const Array<PrimExpr>&
 
   if (use_env_lookup) {
     callee_ftype = ftype_tvm_ffi_func_call_;
-    callee_value = RuntimeTVMFuncCall();
+    callee_value = RuntimeTVMFFIFuncCall();
     call_args.push_back(GetPackedFuncHandle(func_name));
     call_args.insert(call_args.end(), {packed_args, ConstInt32(nargs), 
result});
   } else {
@@ -927,18 +927,18 @@ llvm::Value* CodeGenCPU::CreateCallTracePacked(const 
CallNode* op) {
   return phi_rvalue;
 }
 
-llvm::Value* CodeGenCPU::RuntimeTVMFuncCall() {
+llvm::Value* CodeGenCPU::RuntimeTVMFFIFuncCall() {
   if (f_tvm_ffi_func_call_ != nullptr) return f_tvm_ffi_func_call_;
-  return GetContextPtr(gv_tvm_func_call_);
+  return GetContextPtr(gv_tvm_ffi_func_call_);
 }
 
 llvm::Value* CodeGenCPU::RuntimeTVMGetFuncFromEnv() {
   if (f_tvm_get_func_from_env_ != nullptr) return f_tvm_get_func_from_env_;
   return GetContextPtr(gv_tvm_get_func_from_env_);
 }
-llvm::Value* CodeGenCPU::RuntimeTVMAPISetLastError() {
-  if (f_tvm_api_set_last_error_ != nullptr) return f_tvm_api_set_last_error_;
-  return GetContextPtr(gv_tvm_api_set_last_error_);
+llvm::Value* CodeGenCPU::RuntimeTVMFFISetLastErrorCStr() {
+  if (f_tvm_ffi_set_last_error_c_str_ != nullptr) return 
f_tvm_ffi_set_last_error_c_str_;
+  return GetContextPtr(gv_tvm_ffi_set_last_error_c_str_);
 }
 llvm::Value* CodeGenCPU::RuntimeTVMParallelLaunch() {
   if (f_tvm_parallel_launch_ != nullptr) return f_tvm_parallel_launch_;
@@ -1063,11 +1063,11 @@ void CodeGenCPU::VisitStmt_(const AssertStmtNode* op) {
 
 #if TVM_LLVM_VERSION >= 90
   auto err_callee =
-      llvm::FunctionCallee(ftype_tvm_api_set_last_error_, 
RuntimeTVMAPISetLastError());
+      llvm::FunctionCallee(ftype_tvm_ffi_set_last_error_c_str_, 
RuntimeTVMFFISetLastErrorCStr());
 #else
-  auto err_callee = RuntimeTVMAPISetLastError();
+  auto err_callee = RuntimeTVMFFISetLastErrorCStr();
 #endif
-  builder_->CreateCall(err_callee, {msg});
+  builder_->CreateCall(err_callee, {GetConstString("RuntimeError"), msg});
   builder_->CreateRet(ConstInt32(-1));
   // otherwise set it to be new end.
   builder_->SetInsertPoint(end_block);
diff --git a/src/target/llvm/codegen_cpu.h b/src/target/llvm/codegen_cpu.h
index 03a0ad966e..760ce65b4b 100644
--- a/src/target/llvm/codegen_cpu.h
+++ b/src/target/llvm/codegen_cpu.h
@@ -93,7 +93,7 @@ class CodeGenCPU : public CodeGenLLVM {
   llvm::FunctionType* ftype_tvm_parallel_lambda_{nullptr};
   llvm::FunctionType* ftype_tvm_ffi_func_call_{nullptr};
   llvm::FunctionType* ftype_tvm_get_func_from_env_{nullptr};
-  llvm::FunctionType* ftype_tvm_api_set_last_error_{nullptr};
+  llvm::FunctionType* ftype_tvm_ffi_set_last_error_c_str_{nullptr};
   llvm::FunctionType* ftype_tvm_parallel_launch_{nullptr};
   llvm::FunctionType* ftype_tvm_parallel_barrier_{nullptr};
   llvm::FunctionType* ftype_tvm_register_system_symbol_{nullptr};
@@ -115,9 +115,9 @@ class CodeGenCPU : public CodeGenLLVM {
   void InitGlobalContext(bool dynamic_lookup);
   llvm::GlobalVariable* InitContextPtr(llvm::Type* type, std::string name);
   llvm::Value* GetContextPtr(llvm::GlobalVariable* gv);
-  llvm::Value* RuntimeTVMFuncCall();
+  llvm::Value* RuntimeTVMFFIFuncCall();
   llvm::Value* RuntimeTVMGetFuncFromEnv();
-  llvm::Value* RuntimeTVMAPISetLastError();
+  llvm::Value* RuntimeTVMFFISetLastErrorCStr();
   llvm::Value* RuntimeTVMParallelLaunch();
   llvm::Value* RuntimeTVMParallelBarrier();
   llvm::Value* CreateStaticHandle();
@@ -156,16 +156,16 @@ class CodeGenCPU : public CodeGenLLVM {
 
   // Context for injection lookup
   llvm::GlobalVariable* gv_mod_ctx_{nullptr};
-  llvm::GlobalVariable* gv_tvm_func_call_{nullptr};
+  llvm::GlobalVariable* gv_tvm_ffi_func_call_{nullptr};
   llvm::GlobalVariable* gv_tvm_get_func_from_env_{nullptr};
-  llvm::GlobalVariable* gv_tvm_api_set_last_error_{nullptr};
+  llvm::GlobalVariable* gv_tvm_ffi_set_last_error_c_str_{nullptr};
   llvm::GlobalVariable* gv_tvm_parallel_launch_{nullptr};
   llvm::GlobalVariable* gv_tvm_parallel_barrier_{nullptr};
   std::unordered_map<String, llvm::GlobalVariable*> gv_func_map_;
   // context for direct dynamic lookup
   llvm::Function* f_tvm_ffi_func_call_{nullptr};
   llvm::Function* f_tvm_get_func_from_env_{nullptr};
-  llvm::Function* f_tvm_api_set_last_error_{nullptr};
+  llvm::Function* f_tvm_ffi_set_last_error_c_str_{nullptr};
   llvm::Function* f_tvm_parallel_launch_{nullptr};
   llvm::Function* f_tvm_parallel_barrier_{nullptr};
   llvm::Function* f_tvm_register_system_symbol_{nullptr};
diff --git a/tests/python/codegen/test_target_codegen_llvm.py 
b/tests/python/codegen/test_target_codegen_llvm.py
index 090bced6cc..b6d501b86b 100644
--- a/tests/python/codegen/test_target_codegen_llvm.py
+++ b/tests/python/codegen/test_target_codegen_llvm.py
@@ -1176,5 +1176,24 @@ def test_bool_return_value():
     assert not built(15)
 
 
+def test_invalid_arguments():
+    """Integers may be passed to functions accepting bool"""
+
+    @T.prim_func
+    def func(a0: T.bool, a1: T.Buffer([10], "float32")) -> T.int32:
+        T.func_attr({"target": T.target("llvm")})
+        return 0
+
+    built = tvm.compile(func)
+    with pytest.raises(RuntimeError):
+        built(1, 1)
+
+    with pytest.raises(RuntimeError):
+        built(1, tvm.nd.empty([10], "int32"))
+
+    with pytest.raises(RuntimeError):
+        built(False, tvm.nd.empty([11], "float32"))
+
+
 if __name__ == "__main__":
     tvm.testing.main()

Reply via email to