Implement register/call native API with raw (unextracted) arguments (#222)
This commit is contained in:
@ -33,6 +33,11 @@ typedef struct WASMExecEnv {
|
||||
uint32 *argv_buf;
|
||||
#endif
|
||||
|
||||
/* attachment for native function */
|
||||
void *attachment;
|
||||
|
||||
void *user_data;
|
||||
|
||||
/* Current interpreter frame of current thread */
|
||||
struct WASMInterpFrame *cur_frame;
|
||||
|
||||
|
||||
@ -110,7 +110,7 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
|
||||
|
||||
static void *
|
||||
lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||
const char *symbol, const char **p_signature)
|
||||
const char *symbol, const char **p_signature, void **p_attachment)
|
||||
{
|
||||
int low = 0, mid, ret;
|
||||
int high = n_native_symbols - 1;
|
||||
@ -120,6 +120,7 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||
ret = strcmp(symbol, native_symbols[mid].symbol);
|
||||
if (ret == 0) {
|
||||
*p_signature = native_symbols[mid].signature;
|
||||
*p_attachment = native_symbols[mid].attachment;
|
||||
return native_symbols[mid].func_ptr;
|
||||
}
|
||||
else if (ret < 0)
|
||||
@ -133,11 +134,12 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||
|
||||
void*
|
||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
const WASMType *func_type, const char **p_signature)
|
||||
const WASMType *func_type, const char **p_signature,
|
||||
void **p_attachment, bool *p_call_conv_raw)
|
||||
{
|
||||
NativeSymbolsNode *node, *node_next;
|
||||
const char *signature = NULL;
|
||||
void *func_ptr = NULL;
|
||||
void *func_ptr = NULL, *attachment;
|
||||
|
||||
node = g_native_symbols_list;
|
||||
while (node) {
|
||||
@ -145,11 +147,12 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
if (!strcmp(node->module_name, module_name)) {
|
||||
if ((func_ptr = lookup_symbol(node->native_symbols,
|
||||
node->n_native_symbols,
|
||||
field_name, &signature))
|
||||
field_name, &signature, &attachment))
|
||||
|| (field_name[0] == '_'
|
||||
&& (func_ptr = lookup_symbol(node->native_symbols,
|
||||
node->n_native_symbols,
|
||||
field_name + 1, &signature))))
|
||||
field_name + 1,
|
||||
&signature, &attachment))))
|
||||
break;
|
||||
}
|
||||
node = node_next;
|
||||
@ -172,15 +175,19 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
else
|
||||
/* signature is empty */
|
||||
*p_signature = NULL;
|
||||
|
||||
*p_attachment = attachment;
|
||||
*p_call_conv_raw = node->call_conv_raw;
|
||||
}
|
||||
|
||||
return func_ptr;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_native_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols)
|
||||
static bool
|
||||
register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols,
|
||||
bool call_conv_raw)
|
||||
{
|
||||
NativeSymbolsNode *node;
|
||||
|
||||
@ -190,6 +197,7 @@ wasm_native_register_natives(const char *module_name,
|
||||
node->module_name = module_name;
|
||||
node->native_symbols = native_symbols;
|
||||
node->n_native_symbols = n_native_symbols;
|
||||
node->call_conv_raw = call_conv_raw;
|
||||
node->next = NULL;
|
||||
|
||||
if (g_native_symbols_list_end) {
|
||||
@ -204,6 +212,22 @@ wasm_native_register_natives(const char *module_name,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_native_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols)
|
||||
{
|
||||
return register_natives(module_name, native_symbols, n_native_symbols, false);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_native_register_natives_raw(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols)
|
||||
{
|
||||
return register_natives(module_name, native_symbols, n_native_symbols, true);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_native_init()
|
||||
{
|
||||
|
||||
@ -19,6 +19,7 @@ typedef struct NativeSymbolsNode {
|
||||
const char *module_name;
|
||||
NativeSymbol *native_symbols;
|
||||
uint32 n_native_symbols;
|
||||
bool call_conv_raw;
|
||||
} NativeSymbolsNode, *NativeSymbolsList;
|
||||
|
||||
/**
|
||||
@ -50,13 +51,19 @@ wasm_native_lookup_libc_builtin_global(const char *module_name,
|
||||
*/
|
||||
void*
|
||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
const WASMType *func_type, const char **p_signature);
|
||||
const WASMType *func_type, const char **p_signature,
|
||||
void **p_attachment, bool *p_call_conv_raw);
|
||||
|
||||
bool
|
||||
wasm_native_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
bool
|
||||
wasm_native_register_natives_raw(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
bool
|
||||
wasm_native_init();
|
||||
|
||||
|
||||
@ -233,6 +233,24 @@ wasm_runtime_get_module_inst(WASMExecEnv *exec_env)
|
||||
return wasm_exec_env_get_module_inst(exec_env);
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_get_function_attachment(WASMExecEnv *exec_env)
|
||||
{
|
||||
return exec_env->attachment;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data)
|
||||
{
|
||||
exec_env->user_data = user_data;
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_get_user_data(WASMExecEnv *exec_env)
|
||||
{
|
||||
return exec_env->user_data;
|
||||
}
|
||||
|
||||
WASMFunctionInstanceCommon *
|
||||
wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst,
|
||||
const char *name,
|
||||
@ -1421,6 +1439,120 @@ wasm_runtime_register_natives(const char *module_name,
|
||||
native_symbols, n_native_symbols);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_register_natives_raw(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols)
|
||||
{
|
||||
return wasm_native_register_natives_raw(module_name,
|
||||
native_symbols, n_native_symbols);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
typedef void (*NativeRawFuncPtr)(WASMExecEnv*, uint64*);
|
||||
NativeRawFuncPtr invokeNativeRaw = (NativeRawFuncPtr)func_ptr;
|
||||
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size;
|
||||
uint32 *argv_src = argv, i, argc1, ptr_len;
|
||||
int32 arg_i32;
|
||||
bool ret = false;
|
||||
|
||||
argc1 = func_type->param_count;
|
||||
if (argc1 > sizeof(argv_buf) / sizeof(uint64)) {
|
||||
size = sizeof(uint64) * (uint64)argc1;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(argv1 = wasm_runtime_malloc((uint32)size))) {
|
||||
wasm_runtime_set_exception(exec_env->module_inst,
|
||||
"allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
memset(argv1, 0, (uint32)size);
|
||||
}
|
||||
|
||||
argv_dst = argv1;
|
||||
|
||||
/* Traverse secondly to fill in each argument */
|
||||
for (i = 0; i < func_type->param_count; i++, argv_dst++) {
|
||||
switch (func_type->types[i]) {
|
||||
case VALUE_TYPE_I32:
|
||||
{
|
||||
*(int32*)argv_dst = arg_i32 = (int32)*argv_src++;
|
||||
if (signature) {
|
||||
if (signature[i + 1] == '*') {
|
||||
/* param is a pointer */
|
||||
if (signature[i + 2] == '~')
|
||||
/* pointer with length followed */
|
||||
ptr_len = *argv_src;
|
||||
else
|
||||
/* pointer without length followed */
|
||||
ptr_len = 1;
|
||||
|
||||
if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len))
|
||||
goto fail;
|
||||
|
||||
*(uintptr_t*)argv_dst = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
else if (signature[i + 1] == '$') {
|
||||
/* param is a string */
|
||||
if (!wasm_runtime_validate_app_str_addr(module, arg_i32))
|
||||
goto fail;
|
||||
|
||||
*(uintptr_t*)argv_dst = (uintptr_t)
|
||||
wasm_runtime_addr_app_to_native(module, arg_i32);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, sizeof(uint32) * 2);
|
||||
argv_src += 2;
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(float32*)argv_dst = *(float32*)argv_src++;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exec_env->attachment = attachment;
|
||||
invokeNativeRaw(exec_env, argv1);
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
if (func_type->result_count > 0) {
|
||||
switch (func_type->types[func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
argv_ret[0] = *(uint32*)argv1;
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(float32*)argv_ret = *(float32*)argv1;
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1, sizeof(uint64));
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
wasm_runtime_free(argv1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of wasm_runtime_invoke_native()
|
||||
*/
|
||||
@ -1469,6 +1601,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
|
||||
bool
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
@ -1634,6 +1767,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
exec_env->attachment = attachment;
|
||||
if (func_type->result_count == 0) {
|
||||
invokeNative_Void(func_ptr, argv1, n_stacks);
|
||||
}
|
||||
@ -1656,6 +1790,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
break;
|
||||
}
|
||||
}
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
ret = true;
|
||||
|
||||
@ -1689,6 +1824,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
|
||||
bool
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
@ -1774,6 +1910,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
}
|
||||
|
||||
argc1 = j;
|
||||
exec_env->attachment = attachment;
|
||||
if (func_type->result_count == 0) {
|
||||
invokeNative_Void(func_ptr, argv1, argc1);
|
||||
}
|
||||
@ -1796,6 +1933,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
break;
|
||||
}
|
||||
}
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
ret = true;
|
||||
|
||||
@ -1844,6 +1982,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative;
|
||||
bool
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *argv_ret)
|
||||
{
|
||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||
@ -1938,6 +2077,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
exec_env->attachment = attachment;
|
||||
if (func_type->result_count == 0) {
|
||||
invokeNative_Void(func_ptr, argv1, n_stacks);
|
||||
}
|
||||
@ -1960,6 +2100,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
break;
|
||||
}
|
||||
}
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
ret = true;
|
||||
fail:
|
||||
|
||||
@ -113,6 +113,18 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_runtime_get_module_inst(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
||||
@ -275,11 +287,24 @@ wasm_runtime_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_register_natives_raw(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *ret);
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *ret);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user