platforms/cpp: use m3_Call and stack access API (#234)

* cpp: use m3ApiGetArg, m3ApiReturn, m3_GetResults for stack access

Still relies on an internal m3_api_defs.h, but at least less likely
to get broken, and doesn't depend on M3Runtime internals.

* cpp: use m3_Call in function::call, getting rid of string conversions

When function::call was first written, m3_Call did not exist yet, and
the only way to call functions was through m3_CallArgv which takes
arguments as strings. Now that m3_Call is available, string conversion
can be removed.

Closes https://github.com/wasm3/wasm3/issues/219
opam-2.0.0
Ivan Grokhotkov 3 years ago committed by GitHub
parent 87333d8284
commit a6b61a8a71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,8 +11,7 @@
#include <m3_api_defs.h>
#include "wasm3.h"
/* FIXME: remove when there is a public API to get function return value */
#include "m3_env.h"
namespace wasm3 {
/** @cond */
@ -24,19 +23,21 @@ namespace wasm3 {
typedef const void *(*m3_api_raw_fn)(IM3Runtime, uint64_t *, void *);
template<typename T>
void arg_from_stack(T &dest, stack_type &psp, mem_type mem) {
dest = *(T *) (psp);
psp++;
void arg_from_stack(T &dest, stack_type &_sp, mem_type mem) {
m3ApiGetArg(T, tmp);
dest = tmp;
}
template<typename T>
void arg_from_stack(T* &dest, stack_type &psp, mem_type _mem) {
dest = (void*) m3ApiOffsetToPtr(* ((u32 *) (psp++)));
void arg_from_stack(T* &dest, stack_type &_sp, mem_type _mem) {
m3ApiGetArgMem(T*, tmp);
dest = tmp;
};
template<typename T>
void arg_from_stack(const T* &dest, stack_type &psp, mem_type _mem) {
dest = (void*) m3ApiOffsetToPtr(* ((u32 *) (psp++)));
void arg_from_stack(const T* &dest, stack_type &_sp, mem_type _mem) {
m3ApiGetArgMem(const T*, tmp);
dest = tmp;
};
template<char c>
@ -77,13 +78,14 @@ namespace wasm3 {
template <typename Ret, typename ...Args, Ret (*Fn)(Args...)>
struct wrap_helper<Fn> {
static const void *wrap_fn(IM3Runtime rt, IM3ImportContext _ctx, stack_type sp, mem_type mem) {
Ret *ret_ptr = (Ret *) (sp);
static const void *wrap_fn(IM3Runtime rt, IM3ImportContext _ctx, stack_type _sp, mem_type mem) {
std::tuple<Args...> args;
get_args_from_stack(sp, mem, args);
// The order here matters: m3ApiReturnType should go before calling get_args_from_stack,
// since both modify `_sp`, and the return value on the stack is reserved before the arguments.
m3ApiReturnType(Ret);
get_args_from_stack(_sp, mem, args);
Ret r = std::apply(Fn, args);
*ret_ptr = r;
return m3Err_none;
m3ApiReturn(r);
}
};
@ -312,39 +314,25 @@ namespace wasm3 {
M3Result res = m3_CallArgv(m_func, sizeof...(args), argv);
detail::check_error(res);
Ret ret;
/* FIXME: there should be a public API to get the return value */
auto sp = (detail::stack_type) m_runtime->stack;
detail::arg_from_stack(ret, sp, nullptr);
res = m3_GetResults(m_func, 1, &ret);
return ret;
}
/**
* Call the function with the provided arguments (int/float types).
*
* WASM3 only accepts string arguments when calling WASM functions, and automatically converts them
* into the correct type based on the called function signature.
*
* This function provides a way to pass integer/float types, by first converting them to strings,
* and then letting WASM3 do the reverse conversion. This is to be fixed once WASM3 gains an equivalent
* of m3_CallArgv which can accept arbitrary types, not just strings.
*
* Note that the type of the return value must be explicitly specified as a template argument.
*
* @return the return value of the function.
*/
template<typename Ret, typename ... Args>
Ret call(Args... args) {
std::string argv_str[] = {std::to_string(args)...};
const char* argv[sizeof...(Args)];
for (size_t i = 0; i < sizeof...(Args); ++i) {
argv[i] = argv_str[i].c_str();
}
M3Result res = m3_CallArgv(m_func, sizeof...(args), argv);
const void *arg_ptrs[] = { reinterpret_cast<const void*>(&args)... };
M3Result res = m3_Call(m_func, sizeof...(args), arg_ptrs);
detail::check_error(res);
Ret ret;
/* FIXME: there should be a public API to get the return value */
auto sp = (detail::stack_type) m_runtime->stack;
detail::arg_from_stack(ret, sp, nullptr);
const void* ret_ptrs[] = { &ret };
res = m3_GetResults(m_func, 1, ret_ptrs);
return ret;
}

Loading…
Cancel
Save