Hi, @areusch, I have a question regarding TVMFuncCall section.
I’m using the MISRA-C implementation that uses runtime sources code in runtime/crt/common/crt_runtime_api.c instead of the runtime/c_runtime_api.cc. Crt_runtime_api.c has no TVMFuncCreateFromCFunc() defined. The TVMFuncCall() is as below:
int TVMFuncCall(TVMFunctionHandle func_handle, TVMValue* arg_values, int* type_codes, int num_args,
TVMValue* ret_val, int* ret_type_code) {
...
TVMBackendPackedCFunc func;
...
if (TVMFuncRegistry_GetByIndex(registry, function_index, &func) != 0) {
TVMAPIErrorf("invalid function index: %04" PRIx16, function_index);
return -1;
}
...
return func(arg_values, type_codes, num_args, ret_val, ret_type_code, resource_handle);
}
In the end, it calls func() which has signature with the resource_handle argument. However, in https://github.com/apache/tvm/blob/main/include/tvm/runtime/packed_func.h, the exported function macro is as below:
#define TVM_DLL_EXPORT_TYPED_FUNC(ExportName, Function) \
extern "C" { \
TVM_DLL int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
int* out_type_code) { \
...
} \
}
As shown above, the ExportName() function misses the resource_handle argument, otherwise, all other arguments match with func(…) call inside TVMFuncCall(…).
The exported function will eventually be registered into function registery in https://github.com/apache/tvm/blob/969b77a209c24470ddc4e1e93eeb26e8ea74389b/src/runtime/crt/common/func_registry.c#L118:
tvm_crt_error_t TVMMutableFuncRegistry_Set(TVMMutableFuncRegistry* reg, const char* name,
TVMBackendPackedCFunc func, int override) {
...
((TVMBackendPackedCFunc*)reg->registry.funcs)[idx] = func;
((char*)reg->registry.names)[0]++; // increment num_funcs.
return kTvmErrorNoError;
}
It seems we forcefully convert whatever func to be TVMBackendPackedCFunc pointer although the signatures differ.
I tried this and it actually works! But this is dangerous and really hard to debug if there’s any error associated in argument passing. It works only because we always pass in w/o the resource_handle argument.
Am I missing anything here? Thanks.