You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by tq...@apache.org on 2025/04/21 00:59:38 UTC
(tvm) 02/02: Upgrade error reporting mechanism ABI to new FFI.
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 <ti...@gmail.com>
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()