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-ffi.git
The following commit(s) were added to refs/heads/main by this push:
new 583e4b7 [misc] support various arg types (#229)
583e4b7 is described below
commit 583e4b73c11aa3257e7be862834b98f33c39a6dd
Author: DarkSharpness <[email protected]>
AuthorDate: Mon Nov 10 07:03:44 2025 +0800
[misc] support various arg types (#229)
Related PR #228.
We now support all kinds of argument type (T, const T, T&, const T&,
T&&, const T&& have been tested) in C++ exported functions.
---
include/tvm/ffi/function_details.h | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/include/tvm/ffi/function_details.h
b/include/tvm/ffi/function_details.h
index e7db063..4cd67aa 100644
--- a/include/tvm/ffi/function_details.h
+++ b/include/tvm/ffi/function_details.h
@@ -53,11 +53,19 @@ struct Arg2Str {
}
};
+/// NOTE: We only support `T`, `const T`, `const T&` and `T&&` as argument
types.
+template <typename T>
+static constexpr bool ArgTypeSupported =
+ (!std::is_reference_v<T>) ||
+ (std::is_const_v<std::remove_reference_t<T>> &&
std::is_lvalue_reference_v<T>) ||
+ (!std::is_const_v<std::remove_reference_t<T>> &&
std::is_rvalue_reference_v<T>);
+
template <typename T>
static constexpr bool ArgSupported =
- (std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, Any> ||
- std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, AnyView>
||
- TypeTraitsNoCR<T>::convert_enabled);
+ (ArgTypeSupported<T> &&
+ (std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, Any> ||
+ std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, AnyView>
||
+ TypeTraitsNoCR<T>::convert_enabled));
// NOTE: return type can only support non-reference managed returns
template <typename T>
@@ -136,9 +144,19 @@ using FGetFuncSignature = std::string (*)();
/*!
* \brief Auxilary argument value with context for error reporting
+ * \tparam Type The expected type of the argument.
+ * \note We use a template class with non-template operator conversion
+ * instead of a non-template class with template operator conversion.
+ * This is because template operator conversion doesn't play well with
+ * classes with template constructors.
+ * In this case, it may lead to some unintended compiler errors.
+ * An example of class can be `std::optional<T>`.
*/
+template <typename Type>
class ArgValueWithContext {
public:
+ using TypeWithoutCR = std::remove_const_t<std::remove_reference_t<Type>>;
+
/*!
* \brief move constructor from another return value.
* \param args The argument list
@@ -151,16 +169,13 @@ class ArgValueWithContext {
const std::string* optional_name,
FGetFuncSignature f_sig)
: args_(args), arg_index_(arg_index), optional_name_(optional_name),
f_sig_(f_sig) {}
- template <typename Type>
- TVM_FFI_INLINE operator Type() { // NOLINT(google-explicit-constructor)
- using TypeWithoutCR = std::remove_const_t<std::remove_reference_t<Type>>;
-
+ TVM_FFI_INLINE operator TypeWithoutCR() { //
NOLINT(google-explicit-constructor)
if constexpr (std::is_same_v<TypeWithoutCR, AnyView>) {
return args_[arg_index_];
} else if constexpr (std::is_same_v<TypeWithoutCR, Any>) {
return Any(args_[arg_index_]);
} else {
- std::optional<TypeWithoutCR> opt =
args_[arg_index_].try_cast<TypeWithoutCR>();
+ std::optional<TypeWithoutCR> opt = args_[arg_index_].template
try_cast<TypeWithoutCR>();
if (!opt.has_value()) {
TVMFFIAny any_data = args_[arg_index_].CopyToTVMFFIAny();
TVM_FFI_THROW(TypeError) << "Mismatched type on argument #" <<
arg_index_
@@ -187,6 +202,7 @@ TVM_FFI_INLINE void unpack_call(std::index_sequence<Is...>,
const std::string* o
const F& f, [[maybe_unused]] const AnyView*
args,
[[maybe_unused]] int32_t num_args,
[[maybe_unused]] Any* rv) {
using FuncInfo = FunctionInfo<F>;
+ using PackedArgs = typename FuncInfo::ArgType;
FGetFuncSignature f_sig = FuncInfo::Sig;
// somehow MSVC does not support the static constexpr member in this case,
function is fine
@@ -202,9 +218,10 @@ TVM_FFI_INLINE void
unpack_call(std::index_sequence<Is...>, const std::string* o
}
// use index sequence to do recursive-less unpacking
if constexpr (std::is_same_v<R, void>) {
- f(ArgValueWithContext(args, Is, optional_name, f_sig)...);
+ f(ArgValueWithContext<std::tuple_element_t<Is, PackedArgs>>{args, Is,
optional_name, f_sig}...);
} else {
- *rv = R(f(ArgValueWithContext(args, Is, optional_name, f_sig)...));
+ *rv = R(f(ArgValueWithContext<std::tuple_element_t<Is, PackedArgs>>{args,
Is, optional_name,
+
f_sig}...));
}
}