mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2024-11-26 15:32:05 +00:00
Refactor externref related APIs of reference types feature (#971)
Currently when calling wasm_runtime_call_wasm() to invoke wasm function with externref type argument from runtime embedder, developer needs to use wasm_externref_obj2ref() to convert externref obj into an internal ref index firstly, which is not convenient to developer. To align with GC feature in which all the references passed to wasm_runtime_call_wasm() can be object pointers directly, we change the interface of wasm_runtime_call_wasm() to allow to pass object pointer directly for the externref argument, and refactor the related codes, update the related samples and the document.
This commit is contained in:
parent
2c743dbd51
commit
260d36a62d
|
@ -854,6 +854,7 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
|
|
||||||
/* keep sync with aot_emit_table_info() aot_emit_aot_file */
|
/* keep sync with aot_emit_table_info() aot_emit_aot_file */
|
||||||
for (i = 0; i < module->import_table_count; i++, import_table++) {
|
for (i = 0; i < module->import_table_count; i++, import_table++) {
|
||||||
|
read_uint32(buf, buf_end, import_table->elem_type);
|
||||||
read_uint32(buf, buf_end, import_table->table_init_size);
|
read_uint32(buf, buf_end, import_table->table_init_size);
|
||||||
read_uint32(buf, buf_end, import_table->table_max_size);
|
read_uint32(buf, buf_end, import_table->table_max_size);
|
||||||
read_uint32(buf, buf_end, possible_grow);
|
read_uint32(buf, buf_end, possible_grow);
|
||||||
|
|
|
@ -85,7 +85,7 @@ init_global_data(uint8 *global_data, uint8 type, WASMValue *initial_value)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
case VALUE_TYPE_F32:
|
case VALUE_TYPE_F32:
|
||||||
#if WASM_ENABLE_REF_TYPES
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
#endif
|
#endif
|
||||||
|
@ -1572,16 +1572,8 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
wasm_runtime_prepare_call_function(exec_env, func);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = aot_call_function(exec_env, func, argc, argv);
|
ret = aot_call_function(exec_env, func, argc, argv);
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
wasm_runtime_finalize_call_function(exec_env, func, ret, argv);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* don't destroy the exec_env if it's searched from the cluster */
|
/* don't destroy the exec_env if it's searched from the cluster */
|
||||||
if (!existing_exec_env)
|
if (!existing_exec_env)
|
||||||
wasm_exec_env_destroy(exec_env);
|
wasm_exec_env_destroy(exec_env);
|
||||||
|
|
|
@ -82,6 +82,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
|
||||||
{
|
{
|
||||||
WASMFunctionInstanceCommon *func;
|
WASMFunctionInstanceCommon *func;
|
||||||
WASMType *func_type = NULL;
|
WASMType *func_type = NULL;
|
||||||
|
WASMExecEnv *exec_env = NULL;
|
||||||
uint32 argc1 = 0, argv1[2] = { 0 };
|
uint32 argc1 = 0, argv1[2] = { 0 };
|
||||||
uint32 total_argv_size = 0;
|
uint32 total_argv_size = 0;
|
||||||
uint64 total_size;
|
uint64 total_size;
|
||||||
|
@ -91,14 +92,20 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
|
||||||
uint32 *argv_offsets, module_type;
|
uint32 *argv_offsets, module_type;
|
||||||
bool ret, is_import_func = true;
|
bool ret, is_import_func = true;
|
||||||
|
|
||||||
|
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
|
||||||
|
if (!exec_env) {
|
||||||
|
wasm_runtime_set_exception(module_inst,
|
||||||
|
"create singleton exec_env failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_LIBC_WASI != 0
|
#if WASM_ENABLE_LIBC_WASI != 0
|
||||||
/* In wasi mode, we should call the function named "_start"
|
/* In wasi mode, we should call the function named "_start"
|
||||||
which initializes the wasi envrionment and then calls
|
which initializes the wasi envrionment and then calls
|
||||||
the actual main function. Directly calling main function
|
the actual main function. Directly calling main function
|
||||||
may cause exception thrown. */
|
may cause exception thrown. */
|
||||||
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
|
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
|
||||||
return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, 0,
|
return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||||
|
|
||||||
|
@ -179,8 +186,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
|
||||||
(uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
|
(uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1,
|
ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1);
|
||||||
argv1);
|
|
||||||
if (ret && func_type->result_count > 0 && argc > 0 && argv)
|
if (ret && func_type->result_count > 0 && argc > 0 && argv)
|
||||||
/* copy the return value */
|
/* copy the return value */
|
||||||
*(int *)argv = (int)argv1[0];
|
*(int *)argv = (int)argv1[0];
|
||||||
|
@ -345,7 +351,11 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
WASMFunctionInstanceCommon *target_func;
|
WASMFunctionInstanceCommon *target_func;
|
||||||
WASMModuleInstanceCommon *target_inst;
|
WASMModuleInstanceCommon *target_inst;
|
||||||
WASMType *type = NULL;
|
WASMType *type = NULL;
|
||||||
|
WASMExecEnv *exec_env = NULL;
|
||||||
uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
|
uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
uint32 param_size_in_double_world = 0, result_size_in_double_world = 0;
|
||||||
|
#endif
|
||||||
int32 i, p, module_type;
|
int32 i, p, module_type;
|
||||||
uint64 total_size;
|
uint64 total_size;
|
||||||
const char *exception;
|
const char *exception;
|
||||||
|
@ -373,8 +383,23 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
for (i = 0; i < type->param_count; i++) {
|
||||||
|
param_size_in_double_world +=
|
||||||
|
wasm_value_type_cell_num_outside(type->types[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < type->result_count; i++) {
|
||||||
|
result_size_in_double_world += wasm_value_type_cell_num_outside(
|
||||||
|
type->types[type->param_count + i]);
|
||||||
|
}
|
||||||
|
argc1 = param_size_in_double_world;
|
||||||
|
cell_num = (param_size_in_double_world >= result_size_in_double_world)
|
||||||
|
? param_size_in_double_world
|
||||||
|
: result_size_in_double_world;
|
||||||
|
#else
|
||||||
argc1 = type->param_cell_num;
|
argc1 = type->param_cell_num;
|
||||||
cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
|
cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
|
||||||
|
#endif
|
||||||
|
|
||||||
total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
|
total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
|
||||||
if ((!(argv1 = runtime_malloc((uint32)total_size, target_inst, NULL, 0)))) {
|
if ((!(argv1 = runtime_malloc((uint32)total_size, target_inst, NULL, 0)))) {
|
||||||
|
@ -487,9 +512,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
{
|
{
|
||||||
if (strncmp(argv[i], "null", 4) == 0
|
if (strncasecmp(argv[i], "null", 4) == 0) {
|
||||||
|| strncmp(argv[i], "NULL", 4) == 0) {
|
argv1[p++] = (uint32)-1;
|
||||||
argv1[p++] = NULL_REF;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
|
argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
|
||||||
|
@ -498,23 +522,27 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
}
|
}
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
{
|
{
|
||||||
if (strncmp(argv[i], "null", 4) == 0
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|| strncmp(argv[i], "NULL", 4) == 0) {
|
if (strncasecmp(argv[i], "null", 4) == 0) {
|
||||||
argv1[p++] = NULL_REF;
|
argv1[p++] = (uint32)-1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint64 val = strtoull(argv[i], &endptr, 0);
|
argv1[p++] = strtoul(argv[i], &endptr, 0);
|
||||||
void *extern_obj = (void *)(uintptr_t)val;
|
|
||||||
uint32 externref_idx;
|
|
||||||
|
|
||||||
if (!wasm_externref_obj2ref(target_inst, extern_obj,
|
|
||||||
&externref_idx)) {
|
|
||||||
wasm_runtime_set_exception(
|
|
||||||
module_inst, "map extern object to ref failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
argv1[p++] = externref_idx;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
if (strncasecmp(argv[i], "null", 4) == 0) {
|
||||||
|
u.val = (uintptr_t)-1LL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
u.val = strtoull(argv[i], &endptr, 0);
|
||||||
|
}
|
||||||
|
argv1[p++] = u.parts[0];
|
||||||
|
argv1[p++] = u.parts[1];
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* WASM_ENABLE_REF_TYPES */
|
#endif /* WASM_ENABLE_REF_TYPES */
|
||||||
|
@ -529,11 +557,20 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bh_assert(p == (int32)argc1);
|
|
||||||
|
|
||||||
wasm_runtime_set_exception(module_inst, NULL);
|
wasm_runtime_set_exception(module_inst, NULL);
|
||||||
if (!wasm_runtime_create_exec_env_and_call_wasm(target_inst, target_func,
|
#if WASM_ENABLE_REF_TYPES == 0
|
||||||
argc1, argv1)) {
|
bh_assert(p == (int32)argc1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
|
||||||
|
if (!exec_env) {
|
||||||
|
wasm_runtime_set_exception(module_inst,
|
||||||
|
"create singleton exec_env failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasm_runtime_call_wasm(exec_env, target_func, argc1, argv1)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,7 +613,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
os_printf("%.7g:f64", u.val);
|
os_printf("%.7g:f64", u.val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if WASM_ENABLE_REF_TYPES
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
{
|
{
|
||||||
if (argv1[k] != NULL_REF)
|
if (argv1[k] != NULL_REF)
|
||||||
|
@ -588,16 +625,25 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||||
}
|
}
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
{
|
{
|
||||||
if (argv1[k] != NULL_REF) {
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
void *extern_obj = NULL;
|
if (argv1[k] != 0 && argv1[k] != (uint32)-1)
|
||||||
bool ret = wasm_externref_ref2obj(argv1[k], &extern_obj);
|
os_printf("%p:ref.extern", (void *)argv1[k]);
|
||||||
bh_assert(ret);
|
|
||||||
(void)ret;
|
|
||||||
os_printf("%p:ref.extern", extern_obj);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
os_printf("extern:ref.null");
|
os_printf("extern:ref.null");
|
||||||
k++;
|
k++;
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
u.parts[0] = argv1[k];
|
||||||
|
u.parts[1] = argv1[k + 1];
|
||||||
|
k += 2;
|
||||||
|
if (u.val && u.val != (uintptr_t)-1LL)
|
||||||
|
os_printf("%p:ref.extern", (void *)u.val);
|
||||||
|
else
|
||||||
|
os_printf("extern:ref.null");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1235,9 +1235,8 @@ wasm_exporttype_type(const wasm_exporttype_t *export_type)
|
||||||
void
|
void
|
||||||
wasm_val_delete(wasm_val_t *v)
|
wasm_val_delete(wasm_val_t *v)
|
||||||
{
|
{
|
||||||
if (v) {
|
if (v)
|
||||||
wasm_runtime_free(v);
|
wasm_runtime_free(v);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1562,19 +1561,13 @@ wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
|
||||||
|
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||||
if (!(error_info =
|
error_info = wasm_get_exception((WASMModuleInstance *)inst_comm_rt);
|
||||||
wasm_get_exception((WASMModuleInstance *)inst_comm_rt))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_AOT != 0
|
#if WASM_ENABLE_AOT != 0
|
||||||
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||||
if (!(error_info =
|
error_info = aot_get_exception((AOTModuleInstance *)inst_comm_rt);
|
||||||
aot_get_exception((AOTModuleInstance *)inst_comm_rt))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2160,7 +2153,7 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
|
||||||
- import_memory_count);
|
- import_memory_count);
|
||||||
module_name_rt = import->module_name;
|
module_name_rt = import->module_name;
|
||||||
field_name_rt = import->table_name;
|
field_name_rt = import->table_name;
|
||||||
elem_type_rt = VALUE_TYPE_FUNCREF;
|
elem_type_rt = import->elem_type;
|
||||||
min_size = import->table_init_size;
|
min_size = import->table_init_size;
|
||||||
max_size = import->table_max_size;
|
max_size = import->table_max_size;
|
||||||
}
|
}
|
||||||
|
@ -2563,151 +2556,127 @@ wasm_func_type(const wasm_func_t *func)
|
||||||
return wasm_functype_copy(func->type);
|
return wasm_functype_copy(func->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
static bool
|
||||||
params_to_argv(WASMModuleInstanceCommon *inst_comm_rt, const wasm_val_t *params,
|
params_to_argv(const wasm_val_vec_t *params,
|
||||||
const wasm_valtype_vec_t *param_defs, size_t param_arity,
|
const wasm_valtype_vec_t *param_defs, uint32 *argv,
|
||||||
uint32 *out)
|
uint32 *ptr_argc)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
uint32 argc = 0;
|
|
||||||
const wasm_val_t *param = NULL;
|
|
||||||
|
|
||||||
if (!param_arity) {
|
if (!param_defs->num_elems) {
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bh_assert(params && param_defs && out);
|
if (!params || !params->num_elems || !params->size || !params->data) {
|
||||||
bh_assert(param_defs->num_elems == param_arity);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; out && i < param_arity; ++i) {
|
*ptr_argc = 0;
|
||||||
param = params + i;
|
for (i = 0; i < param_defs->num_elems; ++i) {
|
||||||
|
const wasm_val_t *param = params->data + i;
|
||||||
bh_assert((*(param_defs->data + i))->kind == param->kind);
|
bh_assert((*(param_defs->data + i))->kind == param->kind);
|
||||||
|
|
||||||
switch (param->kind) {
|
switch (param->kind) {
|
||||||
case WASM_I32:
|
case WASM_I32:
|
||||||
*(int32 *)out = param->of.i32;
|
*(int32 *)argv = param->of.i32;
|
||||||
out += 1;
|
argv += 1;
|
||||||
argc += 1;
|
*ptr_argc += 1;
|
||||||
break;
|
break;
|
||||||
case WASM_I64:
|
case WASM_I64:
|
||||||
*(int64 *)out = param->of.i64;
|
*(int64 *)argv = param->of.i64;
|
||||||
out += 2;
|
argv += 2;
|
||||||
argc += 2;
|
*ptr_argc += 2;
|
||||||
break;
|
break;
|
||||||
case WASM_F32:
|
case WASM_F32:
|
||||||
*(float32 *)out = param->of.f32;
|
*(float32 *)argv = param->of.f32;
|
||||||
out += 1;
|
argv += 1;
|
||||||
argc += 1;
|
*ptr_argc += 1;
|
||||||
break;
|
break;
|
||||||
case WASM_F64:
|
case WASM_F64:
|
||||||
*(float64 *)out = param->of.f64;
|
*(float64 *)argv = param->of.f64;
|
||||||
out += 2;
|
argv += 2;
|
||||||
argc += 2;
|
*ptr_argc += 2;
|
||||||
break;
|
break;
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case WASM_ANYREF:
|
case WASM_ANYREF:
|
||||||
if (!wasm_externref_obj2ref(inst_comm_rt, param->of.ref, out)) {
|
*(uintptr_t *)argv = (uintptr_t)param->of.ref;
|
||||||
goto failed;
|
argv += sizeof(uintptr_t) / sizeof(uint32);
|
||||||
}
|
*ptr_argc += 1;
|
||||||
|
|
||||||
out += 1;
|
|
||||||
argc += 1;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
LOG_WARNING("unexpected parameter val type %d", param->kind);
|
LOG_WARNING("unexpected parameter val type %d", param->kind);
|
||||||
goto failed;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return argc;
|
return true;
|
||||||
|
|
||||||
failed:
|
|
||||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
static bool
|
||||||
argv_to_results(const uint32 *results, const wasm_valtype_vec_t *result_defs,
|
argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
|
||||||
size_t result_arity, wasm_val_t *out)
|
wasm_val_vec_t *results)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0, argv_i = 0;
|
||||||
uint32 argc = 0;
|
wasm_val_t *result;
|
||||||
const uint32 *result = results;
|
|
||||||
const wasm_valtype_t *def = NULL;
|
|
||||||
|
|
||||||
if (!result_arity) {
|
if (!result_defs->num_elems) {
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bh_assert(results && result_defs && out);
|
if (!results || !results->num_elems || !results->size || !results->data) {
|
||||||
bh_assert(result_arity == result_defs->num_elems);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; out && i < result_arity; i++) {
|
for (i = 0, result = results->data, argv_i = 0; i < result_defs->num_elems;
|
||||||
def = *(result_defs->data + i);
|
i++, result++) {
|
||||||
|
switch (result_defs->data[i]->kind) {
|
||||||
switch (def->kind) {
|
|
||||||
case WASM_I32:
|
case WASM_I32:
|
||||||
{
|
{
|
||||||
out->kind = WASM_I32;
|
result->kind = WASM_I32;
|
||||||
out->of.i32 = *(int32 *)result;
|
result->of.i32 = *(int32 *)(argv + argv_i);
|
||||||
result += 1;
|
argv_i += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_I64:
|
case WASM_I64:
|
||||||
{
|
{
|
||||||
out->kind = WASM_I64;
|
result->kind = WASM_I64;
|
||||||
out->of.i64 = *(int64 *)result;
|
result->of.i64 = *(int64 *)(argv + argv_i);
|
||||||
result += 2;
|
argv_i += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_F32:
|
case WASM_F32:
|
||||||
{
|
{
|
||||||
out->kind = WASM_F32;
|
result->kind = WASM_F32;
|
||||||
out->of.f32 = *(float32 *)result;
|
result->of.f32 = *(float32 *)(argv + argv_i);
|
||||||
result += 1;
|
argv_i += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WASM_F64:
|
case WASM_F64:
|
||||||
{
|
{
|
||||||
out->kind = WASM_F64;
|
result->kind = WASM_F64;
|
||||||
out->of.f64 = *(float64 *)result;
|
result->of.f64 = *(float64 *)(argv + argv_i);
|
||||||
result += 2;
|
argv_i += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case WASM_ANYREF:
|
case WASM_ANYREF:
|
||||||
{
|
{
|
||||||
out->kind = WASM_ANYREF;
|
result->kind = WASM_ANYREF;
|
||||||
|
result->of.ref =
|
||||||
if (NULL_REF == *(uint32 *)result) {
|
(struct wasm_ref_t *)(*(uintptr_t *)(argv + argv_i));
|
||||||
out->of.ref = NULL;
|
argv_i += sizeof(uintptr_t) / sizeof(uint32);
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!wasm_externref_ref2obj(*(uint32 *)result,
|
|
||||||
(void **)&out->of.ref)) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result += 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
|
LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
|
||||||
def->kind);
|
result_defs->data[i]->kind);
|
||||||
goto failed;
|
return false;
|
||||||
}
|
}
|
||||||
out++;
|
|
||||||
argc++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return argc;
|
return true;
|
||||||
|
|
||||||
failed:
|
|
||||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_trap_t *
|
wasm_trap_t *
|
||||||
|
@ -2718,7 +2687,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
||||||
/* a int64 or float64 parameter means 2 */
|
/* a int64 or float64 parameter means 2 */
|
||||||
uint32 argc = 0;
|
uint32 argc = 0;
|
||||||
/* a parameter list and a return value list */
|
/* a parameter list and a return value list */
|
||||||
uint32 argv_buf[32], *argv = argv_buf;
|
uint32 argv_buf[32] = { 0 }, *argv = argv_buf;
|
||||||
WASMFunctionInstanceCommon *func_comm_rt = NULL;
|
WASMFunctionInstanceCommon *func_comm_rt = NULL;
|
||||||
WASMExecEnv *exec_env = NULL;
|
WASMExecEnv *exec_env = NULL;
|
||||||
size_t param_count, result_count, alloc_count;
|
size_t param_count, result_count, alloc_count;
|
||||||
|
@ -2776,10 +2745,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
||||||
|
|
||||||
/* copy parametes */
|
/* copy parametes */
|
||||||
if (param_count
|
if (param_count
|
||||||
&& (!params
|
&& !params_to_argv(params, wasm_functype_params(func->type), argv,
|
||||||
|| !(argc = params_to_argv(func->inst_comm_rt, params->data,
|
&argc)) {
|
||||||
wasm_functype_params(func->type),
|
|
||||||
param_count, argv)))) {
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2798,9 +2765,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
||||||
|
|
||||||
/* copy results */
|
/* copy results */
|
||||||
if (result_count) {
|
if (result_count) {
|
||||||
if (!results
|
if (!argv_to_results(argv, wasm_functype_results(func->type),
|
||||||
|| !(argc = argv_to_results(argv, wasm_functype_results(func->type),
|
results)) {
|
||||||
result_count, results->data))) {
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
results->num_elems = result_count;
|
results->num_elems = result_count;
|
||||||
|
@ -3265,7 +3231,7 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
|
||||||
if (table_idx_rt < module_aot->import_table_count) {
|
if (table_idx_rt < module_aot->import_table_count) {
|
||||||
AOTImportTable *table_aot =
|
AOTImportTable *table_aot =
|
||||||
module_aot->import_tables + table_idx_rt;
|
module_aot->import_tables + table_idx_rt;
|
||||||
val_type_rt = VALUE_TYPE_FUNCREF;
|
val_type_rt = table_aot->elem_type;
|
||||||
init_size = table_aot->table_init_size;
|
init_size = table_aot->table_init_size;
|
||||||
max_size = table_aot->table_max_size;
|
max_size = table_aot->table_max_size;
|
||||||
}
|
}
|
||||||
|
@ -3273,7 +3239,7 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
|
||||||
AOTTable *table_aot =
|
AOTTable *table_aot =
|
||||||
module_aot->tables
|
module_aot->tables
|
||||||
+ (table_idx_rt - module_aot->import_table_count);
|
+ (table_idx_rt - module_aot->import_table_count);
|
||||||
val_type_rt = VALUE_TYPE_FUNCREF;
|
val_type_rt = table_aot->elem_type;
|
||||||
init_size = table_aot->table_init_size;
|
init_size = table_aot->table_init_size;
|
||||||
max_size = table_aot->table_max_size;
|
max_size = table_aot->table_max_size;
|
||||||
}
|
}
|
||||||
|
@ -3360,13 +3326,12 @@ wasm_table_type(const wasm_table_t *table)
|
||||||
own wasm_ref_t *
|
own wasm_ref_t *
|
||||||
wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
|
wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
|
||||||
{
|
{
|
||||||
uint32 func_idx_rt = NULL_REF;
|
uint32 ref_idx = NULL_REF;
|
||||||
|
|
||||||
if (!table) {
|
if (!table) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* index -> func_idx_rt */
|
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||||
WASMTableInstance *table_interp =
|
WASMTableInstance *table_interp =
|
||||||
|
@ -3375,7 +3340,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
|
||||||
if (index >= table_interp->cur_size) {
|
if (index >= table_interp->cur_size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
func_idx_rt = ((uint32 *)table_interp->base_addr)[index];
|
ref_idx = ((uint32 *)table_interp->base_addr)[index];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3387,7 +3352,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
|
||||||
if (index >= table_aot->cur_size) {
|
if (index >= table_aot->cur_size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
func_idx_rt = table_aot->data[index];
|
ref_idx = table_aot->data[index];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3395,35 +3360,48 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
|
||||||
* a wrong combination of module filetype and compilation flags
|
* a wrong combination of module filetype and compilation flags
|
||||||
* also leads to below branch
|
* also leads to below branch
|
||||||
*/
|
*/
|
||||||
if (func_idx_rt == NULL_REF) {
|
if (ref_idx == NULL_REF) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wasm_ref_new_internal(table->store, WASM_REF_func, func_idx_rt,
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
table->inst_comm_rt);
|
if (table->type->val_type->kind == WASM_ANYREF) {
|
||||||
|
void *externref_obj;
|
||||||
|
if (!wasm_externref_ref2obj(ref_idx, &externref_obj)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return externref_obj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return wasm_ref_new_internal(table->store, WASM_REF_func, ref_idx,
|
||||||
|
table->inst_comm_rt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
|
wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
|
||||||
own wasm_ref_t *func_ref)
|
own wasm_ref_t *ref)
|
||||||
{
|
{
|
||||||
uint32 *p_func_idx_rt = NULL;
|
uint32 *p_ref_idx = NULL;
|
||||||
uint32 function_count = 0, ref_idx_rt = NULL_REF;
|
uint32 function_count = 0;
|
||||||
|
|
||||||
if (!table) {
|
if (!table) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_ref && func_ref->kind != WASM_REF_func) {
|
if (ref
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
&& !(WASM_REF_foreign == ref->kind
|
||||||
|
&& WASM_ANYREF == table->type->val_type->kind)
|
||||||
|
#endif
|
||||||
|
&& !(WASM_REF_func == ref->kind
|
||||||
|
&& WASM_FUNCREF == table->type->val_type->kind)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_ref) {
|
|
||||||
ref_idx_rt = func_ref->ref_idx_rt;
|
|
||||||
wasm_ref_delete(func_ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* index -> *p_func_idx_rt */
|
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||||
WASMTableInstance *table_interp =
|
WASMTableInstance *table_interp =
|
||||||
|
@ -3434,7 +3412,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_func_idx_rt = ((uint32 *)table_interp->base_addr) + index;
|
p_ref_idx = ((uint32 *)table_interp->base_addr) + index;
|
||||||
function_count =
|
function_count =
|
||||||
((WASMModuleInstance *)table->inst_comm_rt)->function_count;
|
((WASMModuleInstance *)table->inst_comm_rt)->function_count;
|
||||||
}
|
}
|
||||||
|
@ -3451,7 +3429,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_func_idx_rt = table_aot->data + index;
|
p_ref_idx = table_aot->data + index;
|
||||||
function_count = module_aot->func_count;
|
function_count = module_aot->func_count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3460,17 +3438,31 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
|
||||||
* a wrong combination of module filetype and compilation flags
|
* a wrong combination of module filetype and compilation flags
|
||||||
* leads to below branch
|
* leads to below branch
|
||||||
*/
|
*/
|
||||||
if (!p_func_idx_rt) {
|
if (!p_ref_idx) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL_REF != ref_idx_rt) {
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
if (ref_idx_rt >= function_count) {
|
if (table->type->val_type->kind == WASM_ANYREF) {
|
||||||
return false;
|
return wasm_externref_obj2ref(table->inst_comm_rt, ref, p_ref_idx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (ref) {
|
||||||
|
if (NULL_REF != ref->ref_idx_rt) {
|
||||||
|
if (ref->ref_idx_rt >= function_count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p_ref_idx = ref->ref_idx_rt;
|
||||||
|
wasm_ref_delete(ref);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*p_ref_idx = NULL_REF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*p_func_idx_rt = ref_idx_rt;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ struct wasm_globaltype_t {
|
||||||
|
|
||||||
struct wasm_tabletype_t {
|
struct wasm_tabletype_t {
|
||||||
uint32 extern_kind;
|
uint32 extern_kind;
|
||||||
/* always be WASM_FUNCREF */
|
|
||||||
wasm_valtype_t *val_type;
|
wasm_valtype_t *val_type;
|
||||||
wasm_limits_t limits;
|
wasm_limits_t limits;
|
||||||
};
|
};
|
||||||
|
|
|
@ -125,10 +125,6 @@ typedef struct WASMExecEnv {
|
||||||
WASMJmpBuf *jmpbuf_stack_top;
|
WASMJmpBuf *jmpbuf_stack_top;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
uint16 nested_calling_depth;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||||
uint32 max_wasm_stack_used;
|
uint32 max_wasm_stack_used;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,11 +53,30 @@ get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
|
||||||
uint32
|
uint32
|
||||||
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
|
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
compare_type_with_signautre(uint8 type, const char signature)
|
||||||
|
{
|
||||||
|
const char num_sig_map[] = { 'F', 'f', 'I', 'i' };
|
||||||
|
|
||||||
|
if (VALUE_TYPE_F64 <= type && type <= VALUE_TYPE_I32
|
||||||
|
&& signature == num_sig_map[type - VALUE_TYPE_F64]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
if ('r' == signature && type == VALUE_TYPE_EXTERNREF)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TODO: a v128 parameter */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_symbol_signature(const WASMType *type, const char *signature)
|
check_symbol_signature(const WASMType *type, const char *signature)
|
||||||
{
|
{
|
||||||
const char *p = signature, *p_end;
|
const char *p = signature, *p_end;
|
||||||
char sig_map[] = { 'F', 'f', 'I', 'i' }, sig;
|
char sig;
|
||||||
uint32 i = 0;
|
uint32 i = 0;
|
||||||
|
|
||||||
if (!p || strlen(p) < 2)
|
if (!p || strlen(p) < 2)
|
||||||
|
@ -74,16 +93,12 @@ check_symbol_signature(const WASMType *type, const char *signature)
|
||||||
|
|
||||||
for (i = 0; i < type->param_count; i++) {
|
for (i = 0; i < type->param_count; i++) {
|
||||||
sig = *p++;
|
sig = *p++;
|
||||||
if ((type->types[i] >= VALUE_TYPE_F64
|
|
||||||
&& type->types[i] <= VALUE_TYPE_I32
|
/* a f64/f32/i64/i32/externref parameter */
|
||||||
&& sig == sig_map[type->types[i] - VALUE_TYPE_F64])
|
if (compare_type_with_signautre(type->types[i], sig))
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
|| (sig == 'i' && type->types[i] == VALUE_TYPE_EXTERNREF)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
/* normal parameter */
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* a pointer/string paramter */
|
||||||
if (type->types[i] != VALUE_TYPE_I32)
|
if (type->types[i] != VALUE_TYPE_I32)
|
||||||
/* pointer and string must be i32 type */
|
/* pointer and string must be i32 type */
|
||||||
return false;
|
return false;
|
||||||
|
@ -112,8 +127,12 @@ check_symbol_signature(const WASMType *type, const char *signature)
|
||||||
if (type->result_count) {
|
if (type->result_count) {
|
||||||
if (p >= p_end)
|
if (p >= p_end)
|
||||||
return false;
|
return false;
|
||||||
if (*p++ != sig_map[type->types[i] - VALUE_TYPE_F64])
|
|
||||||
|
/* result types includes: f64,f32,i64,i32,externref */
|
||||||
|
if (!compare_type_with_signautre(type->types[i], *p))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p != '\0')
|
if (*p != '\0')
|
||||||
|
|
|
@ -1199,46 +1199,163 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
static void
|
/* (uintptr_t)externref -> (uint32_t)index */
|
||||||
wasm_runtime_reclaim_externref(WASMExecEnv *exec_env,
|
/* argv -> *ret_argv */
|
||||||
WASMFunctionInstanceCommon *function,
|
static bool
|
||||||
uint32 *argv)
|
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
|
||||||
|
WASMFunctionInstanceCommon *function,
|
||||||
|
uint32 *argv, uint32 argc, uint32 **ret_argv,
|
||||||
|
uint32 *ret_argc_param,
|
||||||
|
uint32 *ret_argc_result)
|
||||||
{
|
{
|
||||||
uint32 i = 0, cell_num = 0;
|
uint32 *new_argv = NULL, argv_i = 0, new_argv_i = 0, param_i = 0,
|
||||||
|
result_i = 0;
|
||||||
|
bool need_param_transform = false, need_result_transform = false;
|
||||||
|
uint64 size = 0;
|
||||||
WASMType *func_type = wasm_runtime_get_function_type(
|
WASMType *func_type = wasm_runtime_get_function_type(
|
||||||
function, exec_env->module_inst->module_type);
|
function, exec_env->module_inst->module_type);
|
||||||
|
|
||||||
|
bh_assert(func_type);
|
||||||
|
|
||||||
|
*ret_argc_param = func_type->param_cell_num;
|
||||||
|
*ret_argc_result = func_type->ret_cell_num;
|
||||||
|
for (param_i = 0; param_i < func_type->param_count; param_i++) {
|
||||||
|
if (VALUE_TYPE_EXTERNREF == func_type->types[param_i]) {
|
||||||
|
need_param_transform = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (result_i = 0; result_i < func_type->result_count; result_i++) {
|
||||||
|
if (VALUE_TYPE_EXTERNREF
|
||||||
|
== func_type->types[func_type->param_count + result_i]) {
|
||||||
|
need_result_transform = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!need_param_transform && !need_result_transform) {
|
||||||
|
*ret_argv = argv;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func_type->param_cell_num >= func_type->ret_cell_num) {
|
||||||
|
size = sizeof(uint32) * func_type->param_cell_num;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size = sizeof(uint32) * func_type->ret_cell_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(new_argv = runtime_malloc(size, exec_env->module_inst, NULL, 0))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!need_param_transform) {
|
||||||
|
bh_memcpy_s(new_argv, size, argv, size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (param_i = 0; param_i < func_type->param_count && argv_i < argc
|
||||||
|
&& new_argv_i < func_type->param_cell_num;
|
||||||
|
param_i++) {
|
||||||
|
uint8 param_type = func_type->types[param_i];
|
||||||
|
if (VALUE_TYPE_EXTERNREF == param_type) {
|
||||||
|
void *externref_obj;
|
||||||
|
uint32 externref_index;
|
||||||
|
|
||||||
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|
externref_obj = (void *)argv[argv_i];
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
|
||||||
|
u.parts[0] = argv[argv_i];
|
||||||
|
u.parts[1] = argv[argv_i + 1];
|
||||||
|
externref_obj = (void *)u.val;
|
||||||
|
#endif
|
||||||
|
if (!wasm_externref_obj2ref(exec_env->module_inst,
|
||||||
|
externref_obj, &externref_index)) {
|
||||||
|
wasm_runtime_free(new_argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_argv[new_argv_i] = externref_index;
|
||||||
|
argv_i += sizeof(uintptr_t) / sizeof(uint32);
|
||||||
|
new_argv_i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint16 param_cell_num = wasm_value_type_cell_num(param_type);
|
||||||
|
uint32 param_size = sizeof(uint32) * param_cell_num;
|
||||||
|
bh_memcpy_s(new_argv + new_argv_i, param_size, argv + argv_i,
|
||||||
|
param_size);
|
||||||
|
argv_i += param_cell_num;
|
||||||
|
new_argv_i += param_cell_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_argv = new_argv;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (uintptr_t)externref <- (uint32_t)index */
|
||||||
|
/* argv <- new_argv */
|
||||||
|
static bool
|
||||||
|
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
||||||
|
WASMFunctionInstanceCommon *function,
|
||||||
|
uint32 *argv, uint32 argc, uint32 *ret_argv)
|
||||||
|
{
|
||||||
|
uint32 argv_i = 0, result_i = 0, ret_argv_i = 0;
|
||||||
|
WASMType *func_type;
|
||||||
|
|
||||||
|
bh_assert(argv && ret_argv);
|
||||||
|
|
||||||
|
if (argv == ret_argv) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_type = wasm_runtime_get_function_type(
|
||||||
|
function, exec_env->module_inst->module_type);
|
||||||
bh_assert(func_type);
|
bh_assert(func_type);
|
||||||
|
|
||||||
while (i < func_type->result_count) {
|
for (result_i = 0; result_i < func_type->result_count && argv_i < argc;
|
||||||
uint8 result_type = func_type->types[func_type->param_count + i];
|
result_i++) {
|
||||||
if (result_type == VALUE_TYPE_EXTERNREF && argv[i] != NULL_REF) {
|
uint8 result_type = func_type->types[func_type->param_count + result_i];
|
||||||
/* Retain the externref returned to runtime embedder */
|
if (result_type == VALUE_TYPE_EXTERNREF) {
|
||||||
(void)wasm_externref_retain(argv[i]);
|
void *externref_obj;
|
||||||
|
#if UINTPTR_MAX != UINT32_MAX
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!wasm_externref_ref2obj(argv[argv_i], &externref_obj)) {
|
||||||
|
wasm_runtime_free(argv);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|
ret_argv[ret_argv_i] = (uintptr_t)externref_obj;
|
||||||
|
#else
|
||||||
|
u.val = (uintptr_t)externref_obj;
|
||||||
|
ret_argv[ret_argv_i] = u.parts[0];
|
||||||
|
ret_argv[ret_argv_i + 1] = u.parts[1];
|
||||||
|
#endif
|
||||||
|
argv_i += 1;
|
||||||
|
ret_argv_i += sizeof(uintptr_t) / sizeof(uint32);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint16 result_cell_num = wasm_value_type_cell_num(result_type);
|
||||||
|
uint32 result_size = sizeof(uint32) * result_cell_num;
|
||||||
|
bh_memcpy_s(ret_argv + ret_argv_i, result_size, argv + argv_i,
|
||||||
|
result_size);
|
||||||
|
argv_i += result_cell_num;
|
||||||
|
ret_argv_i += result_cell_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_num += wasm_value_type_cell_num(result_type);
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_externref_reclaim(exec_env->module_inst);
|
wasm_runtime_free(argv);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
void
|
|
||||||
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
|
|
||||||
WASMFunctionInstanceCommon *function)
|
|
||||||
{
|
|
||||||
exec_env->nested_calling_depth++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
|
||||||
WASMFunctionInstanceCommon *function,
|
|
||||||
bool ret, uint32 *argv)
|
|
||||||
{
|
|
||||||
exec_env->nested_calling_depth--;
|
|
||||||
if (!exec_env->nested_calling_depth && ret) {
|
|
||||||
wasm_runtime_reclaim_externref(exec_env, function, argv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1248,6 +1365,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
||||||
uint32 argv[])
|
uint32 argv[])
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
uint32 *new_argv = NULL, param_argc;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
uint32 result_argc = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!wasm_runtime_exec_env_check(exec_env)) {
|
if (!wasm_runtime_exec_env_check(exec_env)) {
|
||||||
LOG_ERROR("Invalid exec env stack info.");
|
LOG_ERROR("Invalid exec env stack info.");
|
||||||
|
@ -1255,34 +1376,53 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
wasm_runtime_prepare_call_function(exec_env, function);
|
if (!wasm_runtime_prepare_call_function(exec_env, function, argv, argc,
|
||||||
|
&new_argv, ¶m_argc,
|
||||||
|
&result_argc)) {
|
||||||
|
wasm_runtime_set_exception(exec_env->module_inst,
|
||||||
|
"the arguments conversion is failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
new_argv = argv;
|
||||||
|
param_argc = argc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
|
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
|
||||||
ret = wasm_call_function(exec_env, (WASMFunctionInstance *)function,
|
ret = wasm_call_function(exec_env, (WASMFunctionInstance *)function,
|
||||||
argc, argv);
|
param_argc, new_argv);
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_AOT != 0
|
#if WASM_ENABLE_AOT != 0
|
||||||
if (exec_env->module_inst->module_type == Wasm_Module_AoT)
|
if (exec_env->module_inst->module_type == Wasm_Module_AoT)
|
||||||
ret = aot_call_function(exec_env, (AOTFunctionInstance *)function, argc,
|
ret = aot_call_function(exec_env, (AOTFunctionInstance *)function,
|
||||||
argv);
|
param_argc, new_argv);
|
||||||
#endif
|
#endif
|
||||||
|
if (!ret) {
|
||||||
|
if (new_argv != argv) {
|
||||||
|
wasm_runtime_free(new_argv);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
wasm_runtime_finalize_call_function(exec_env, function, ret, argv);
|
if (!wasm_runtime_finalize_call_function(exec_env, function, new_argv,
|
||||||
|
result_argc, argv)) {
|
||||||
|
wasm_runtime_set_exception(exec_env->module_inst,
|
||||||
|
"the result conversion is failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
static void
|
||||||
parse_args_to_uint32_array(WASMType *type, uint32 num_args, wasm_val_t *args,
|
parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
|
||||||
uint32 *out_argv)
|
|
||||||
{
|
{
|
||||||
uint32 i, p;
|
uint32 i, p;
|
||||||
|
|
||||||
for (i = 0, p = 0; i < num_args; i++) {
|
for (i = 0, p = 0; i < type->param_count; i++) {
|
||||||
switch (args[i].kind) {
|
switch (args[i].kind) {
|
||||||
case WASM_I32:
|
case WASM_I32:
|
||||||
out_argv[p++] = args[i].of.i32;
|
out_argv[p++] = args[i].of.i32;
|
||||||
|
@ -1319,16 +1459,38 @@ parse_args_to_uint32_array(WASMType *type, uint32 num_args, wasm_val_t *args,
|
||||||
out_argv[p++] = u.parts[1];
|
out_argv[p++] = u.parts[1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case WASM_FUNCREF:
|
||||||
|
{
|
||||||
|
out_argv[p++] = args[i].of.i32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WASM_ANYREF:
|
||||||
|
{
|
||||||
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|
out_argv[p++] = args[i].of.foreign;
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
|
||||||
|
u.val = (uintptr_t)args[i].of.foreign;
|
||||||
|
out_argv[p++] = u.parts[0];
|
||||||
|
out_argv[p++] = u.parts[1];
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
static void
|
||||||
parse_uint32_array_to_results(WASMType *type, uint32 argc, uint32 *argv,
|
parse_uint32_array_to_results(WASMType *type, uint32 *argv,
|
||||||
wasm_val_t *out_results)
|
wasm_val_t *out_results)
|
||||||
{
|
{
|
||||||
uint32 i, p;
|
uint32 i, p;
|
||||||
|
@ -1374,13 +1536,36 @@ parse_uint32_array_to_results(WASMType *type, uint32 argc, uint32 *argv,
|
||||||
out_results[i].of.f64 = u.val;
|
out_results[i].of.f64 = u.val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_FUNCREF:
|
||||||
|
{
|
||||||
|
out_results[i].kind = WASM_I32;
|
||||||
|
out_results[i].of.i32 = (int32)argv[p++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|
out_results[i].kind = WASM_ANYREF;
|
||||||
|
out_results[i].of.foreign = (uintptr_t)argv[p++];
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
u.parts[0] = argv[p++];
|
||||||
|
u.parts[1] = argv[p++];
|
||||||
|
out_results[i].kind = WASM_ANYREF;
|
||||||
|
out_results[i].of.foreign = u.val;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bh_assert(argc == p);
|
|
||||||
return type->result_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1389,7 +1574,10 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
|
||||||
uint32 num_results, wasm_val_t results[],
|
uint32 num_results, wasm_val_t results[],
|
||||||
uint32 num_args, wasm_val_t args[])
|
uint32 num_args, wasm_val_t args[])
|
||||||
{
|
{
|
||||||
uint32 argc, *argv, ret_num, cell_num, total_size, module_type;
|
uint32 argc, *argv, cell_num, total_size, module_type;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
uint32 i, param_size_in_double_world = 0, result_size_in_double_world = 0;
|
||||||
|
#endif
|
||||||
WASMType *type;
|
WASMType *type;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
|
@ -1402,8 +1590,23 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
|
||||||
goto fail1;
|
goto fail1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
for (i = 0; i < type->param_count; i++) {
|
||||||
|
param_size_in_double_world +=
|
||||||
|
wasm_value_type_cell_num_outside(type->types[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < type->result_count; i++) {
|
||||||
|
result_size_in_double_world += wasm_value_type_cell_num_outside(
|
||||||
|
type->types[type->param_count + i]);
|
||||||
|
}
|
||||||
|
argc = param_size_in_double_world;
|
||||||
|
cell_num = (argc >= result_size_in_double_world)
|
||||||
|
? argc
|
||||||
|
: result_size_in_double_world;
|
||||||
|
#else
|
||||||
argc = type->param_cell_num;
|
argc = type->param_cell_num;
|
||||||
cell_num = (argc > type->ret_cell_num) ? argc : type->ret_cell_num;
|
cell_num = (argc > type->ret_cell_num) ? argc : type->ret_cell_num;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (num_results != type->result_count) {
|
if (num_results != type->result_count) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
|
@ -1425,14 +1628,11 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
|
||||||
goto fail1;
|
goto fail1;
|
||||||
}
|
}
|
||||||
|
|
||||||
argc = parse_args_to_uint32_array(type, num_args, args, argv);
|
parse_args_to_uint32_array(type, args, argv);
|
||||||
if (!(ret = wasm_runtime_call_wasm(exec_env, function, argc, argv)))
|
if (!(ret = wasm_runtime_call_wasm(exec_env, function, num_args, argv)))
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
ret_num =
|
parse_uint32_array_to_results(type, argv, results);
|
||||||
parse_uint32_array_to_results(type, type->ret_cell_num, argv, results);
|
|
||||||
bh_assert(ret_num == num_results);
|
|
||||||
(void)ret_num;
|
|
||||||
|
|
||||||
fail2:
|
fail2:
|
||||||
wasm_runtime_free(argv);
|
wasm_runtime_free(argv);
|
||||||
|
@ -1492,6 +1692,20 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
|
||||||
args[i].kind = WASM_F64;
|
args[i].kind = WASM_F64;
|
||||||
args[i].of.f64 = va_arg(vargs, float64);
|
args[i].of.f64 = va_arg(vargs, float64);
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_FUNCREF:
|
||||||
|
{
|
||||||
|
args[i].kind = WASM_FUNCREF;
|
||||||
|
args[i].of.i32 = va_arg(vargs, uint32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
args[i].kind = WASM_ANYREF;
|
||||||
|
args[i].of.foreign = va_arg(vargs, uintptr_t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -1547,13 +1761,21 @@ WASMExecEnv *
|
||||||
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
|
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
|
||||||
{
|
{
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||||
|
if (!((WASMModuleInstance *)module_inst)->exec_env_singleton) {
|
||||||
|
wasm_create_exec_env_singleton((WASMModuleInstance *)module_inst);
|
||||||
|
}
|
||||||
return ((WASMModuleInstance *)module_inst)->exec_env_singleton;
|
return ((WASMModuleInstance *)module_inst)->exec_env_singleton;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_AOT != 0
|
#if WASM_ENABLE_AOT != 0
|
||||||
if (module_inst->module_type == Wasm_Module_AoT)
|
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||||
|
if (!((AOTModuleInstance *)module_inst)->exec_env_singleton.ptr) {
|
||||||
|
aot_create_exec_env_singleton((AOTModuleInstance *)module_inst);
|
||||||
|
}
|
||||||
return (WASMExecEnv *)((AOTModuleInstance *)module_inst)
|
return (WASMExecEnv *)((AOTModuleInstance *)module_inst)
|
||||||
->exec_env_singleton.ptr;
|
->exec_env_singleton.ptr;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2497,6 +2719,9 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
for (i = 0; i < func_type->param_count; i++, argv_dst++) {
|
for (i = 0; i < func_type->param_count; i++, argv_dst++) {
|
||||||
switch (func_type->types[i]) {
|
switch (func_type->types[i]) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_FUNCREF:
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
*(uint32 *)argv_dst = arg_i32 = *argv_src++;
|
*(uint32 *)argv_dst = arg_i32 = *argv_src++;
|
||||||
if (signature) {
|
if (signature) {
|
||||||
|
@ -2540,10 +2765,19 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
*(float32 *)argv_dst = *(float32 *)argv_src++;
|
*(float32 *)argv_dst = *(float32 *)argv_src++;
|
||||||
break;
|
break;
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
*(uint32 *)argv_dst = *argv_src++;
|
{
|
||||||
|
uint32 externref_idx = *argv_src++;
|
||||||
|
|
||||||
|
void *externref_obj;
|
||||||
|
|
||||||
|
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
bh_memcpy_s(argv_dst, sizeof(uintptr_t), argv_src,
|
||||||
|
sizeof(uintptr_t));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
|
@ -2560,7 +2794,6 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
#endif
|
#endif
|
||||||
argv_ret[0] = *(uint32 *)argv1;
|
argv_ret[0] = *(uint32 *)argv1;
|
||||||
break;
|
break;
|
||||||
|
@ -2572,6 +2805,23 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1,
|
bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1,
|
||||||
sizeof(uint64));
|
sizeof(uint64));
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
uint32 externref_idx;
|
||||||
|
uint64 externref_obj;
|
||||||
|
|
||||||
|
bh_memcpy_s(&externref_obj, sizeof(uint64), argv1,
|
||||||
|
sizeof(uint64));
|
||||||
|
|
||||||
|
if (!wasm_externref_obj2ref(exec_env->module_inst,
|
||||||
|
(void *)(uintptr_t)externref_obj,
|
||||||
|
&externref_idx))
|
||||||
|
goto fail;
|
||||||
|
argv_ret[0] = externref_idx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -2634,6 +2884,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
uint32 result_count = func_type->result_count;
|
uint32 result_count = func_type->result_count;
|
||||||
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
bool is_aot_func = (NULL == signature);
|
||||||
|
#endif
|
||||||
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
|
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
|
||||||
uint32 *fps;
|
uint32 *fps;
|
||||||
int n_fps = 0;
|
int n_fps = 0;
|
||||||
|
@ -2792,6 +3045,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
for (i = 0; i < func_type->param_count; i++) {
|
for (i = 0; i < func_type->param_count; i++) {
|
||||||
switch (func_type->types[i]) {
|
switch (func_type->types[i]) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_FUNCREF:
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
arg_i32 = *argv_src++;
|
arg_i32 = *argv_src++;
|
||||||
|
|
||||||
|
@ -2829,17 +3085,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
stacks[n_stacks++] = arg_i32;
|
stacks[n_stacks++] = arg_i32;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
case VALUE_TYPE_FUNCREF:
|
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
{
|
|
||||||
if (n_ints < MAX_REG_INTS)
|
|
||||||
ints[n_ints++] = *argv_src++;
|
|
||||||
else
|
|
||||||
stacks[n_stacks++] = *argv_src++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
case VALUE_TYPE_I64:
|
case VALUE_TYPE_I64:
|
||||||
{
|
{
|
||||||
if (n_ints < MAX_REG_INTS - 1) {
|
if (n_ints < MAX_REG_INTS - 1) {
|
||||||
|
@ -2959,6 +3204,31 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* BUILD_TARGET_RISCV32_ILP32D */
|
#endif /* BUILD_TARGET_RISCV32_ILP32D */
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
uint32 externref_idx = *argv_src++;
|
||||||
|
|
||||||
|
if (is_aot_func) {
|
||||||
|
if (n_ints < MAX_REG_INTS)
|
||||||
|
ints[n_ints++] = externref_idx;
|
||||||
|
else
|
||||||
|
stacks[n_stacks++] = externref_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
void *externref_obj;
|
||||||
|
|
||||||
|
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (n_ints < MAX_REG_INTS)
|
||||||
|
ints[n_ints++] = (uintptr_t)externref_obj;
|
||||||
|
else
|
||||||
|
stacks[n_stacks++] = (uintptr_t)externref_obj;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -2982,7 +3252,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
#endif
|
#endif
|
||||||
argv_ret[0] =
|
argv_ret[0] =
|
||||||
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||||
|
@ -2999,6 +3268,30 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
PUT_F64_TO_ADDR(
|
PUT_F64_TO_ADDR(
|
||||||
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
if (is_aot_func) {
|
||||||
|
uint32 externref_idx =
|
||||||
|
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
|
||||||
|
argv_ret[0] = externref_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint32 externref_idx;
|
||||||
|
void *externref_obj;
|
||||||
|
|
||||||
|
externref_obj = (void *)(uintptr_t)invokeNative_Int32(
|
||||||
|
func_ptr, argv1, argc1);
|
||||||
|
|
||||||
|
if (!wasm_externref_obj2ref(exec_env->module_inst,
|
||||||
|
externref_obj, &externref_idx))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
argv_ret[0] = externref_idx;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -3060,6 +3353,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
||||||
uint64 size;
|
uint64 size;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
bool is_aot_func = (NULL == signature);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(BUILD_TARGET_X86_32)
|
#if defined(BUILD_TARGET_X86_32)
|
||||||
argc1 = argc + ext_ret_count + 2;
|
argc1 = argc + ext_ret_count + 2;
|
||||||
|
@ -3083,6 +3379,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
for (i = 0; i < func_type->param_count; i++) {
|
for (i = 0; i < func_type->param_count; i++) {
|
||||||
switch (func_type->types[i]) {
|
switch (func_type->types[i]) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_FUNCREF:
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
arg_i32 = *argv++;
|
arg_i32 = *argv++;
|
||||||
|
|
||||||
|
@ -3129,12 +3428,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
argv1[j++] = *argv++;
|
argv1[j++] = *argv++;
|
||||||
break;
|
break;
|
||||||
case VALUE_TYPE_F32:
|
case VALUE_TYPE_F32:
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
case VALUE_TYPE_FUNCREF:
|
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
#endif
|
|
||||||
argv1[j++] = *argv++;
|
argv1[j++] = *argv++;
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
uint32 externref_idx = *argv++;
|
||||||
|
if (is_aot_func) {
|
||||||
|
argv1[j++] = externref_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
void *externref_obj;
|
||||||
|
|
||||||
|
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
argv1[j++] = (uintptr_t)externref_obj;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -3154,7 +3467,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
#endif
|
#endif
|
||||||
argv_ret[0] =
|
argv_ret[0] =
|
||||||
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
|
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
|
||||||
|
@ -3171,6 +3483,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
PUT_F64_TO_ADDR(argv_ret,
|
PUT_F64_TO_ADDR(argv_ret,
|
||||||
invokeNative_Float64(func_ptr, argv1, argc1));
|
invokeNative_Float64(func_ptr, argv1, argc1));
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
if (is_aot_func) {
|
||||||
|
uint32 externref_idx =
|
||||||
|
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
|
||||||
|
argv_ret[0] = externref_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
void *externref_obj = (void *)(uintptr_t)invokeNative_Int32(
|
||||||
|
func_ptr, argv1, argc1);
|
||||||
|
uint32 externref_idx;
|
||||||
|
if (!wasm_externref_obj2ref(exec_env->module_inst,
|
||||||
|
externref_obj, &externref_idx))
|
||||||
|
goto fail;
|
||||||
|
argv_ret[0] = externref_idx;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
bh_assert(0);
|
bh_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -3281,12 +3613,16 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
uint32 *argv_ret)
|
uint32 *argv_ret)
|
||||||
{
|
{
|
||||||
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
|
||||||
uint64 argv_buf[32], *argv1 = argv_buf, *ints, *stacks, size, arg_i64;
|
uint64 argv_buf[32] = { 0 }, *argv1 = argv_buf, *ints, *stacks, size,
|
||||||
|
arg_i64;
|
||||||
uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0;
|
uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0;
|
||||||
uint32 arg_i32, ptr_len;
|
uint32 arg_i32, ptr_len;
|
||||||
uint32 result_count = func_type->result_count;
|
uint32 result_count = func_type->result_count;
|
||||||
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
bool is_aot_func = (NULL == signature);
|
||||||
|
#endif
|
||||||
#ifndef BUILD_TARGET_RISCV64_LP64
|
#ifndef BUILD_TARGET_RISCV64_LP64
|
||||||
#if WASM_ENABLE_SIMD == 0
|
#if WASM_ENABLE_SIMD == 0
|
||||||
uint64 *fps;
|
uint64 *fps;
|
||||||
|
@ -3336,6 +3672,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
for (i = 0; i < func_type->param_count; i++) {
|
for (i = 0; i < func_type->param_count; i++) {
|
||||||
switch (func_type->types[i]) {
|
switch (func_type->types[i]) {
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_FUNCREF:
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
arg_i32 = *argv_src++;
|
arg_i32 = *argv_src++;
|
||||||
arg_i64 = arg_i32;
|
arg_i64 = arg_i32;
|
||||||
|
@ -3397,13 +3736,28 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
argv_src += 2;
|
argv_src += 2;
|
||||||
break;
|
break;
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
if (n_ints < MAX_REG_INTS)
|
{
|
||||||
ints[n_ints++] = *argv_src++;
|
uint32 externref_idx = *argv_src++;
|
||||||
else
|
if (is_aot_func) {
|
||||||
stacks[n_stacks++] = *argv_src++;
|
if (n_ints < MAX_REG_INTS)
|
||||||
|
ints[n_ints++] = externref_idx;
|
||||||
|
else
|
||||||
|
stacks[n_stacks++] = externref_idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
void *externref_obj;
|
||||||
|
|
||||||
|
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (n_ints < MAX_REG_INTS)
|
||||||
|
ints[n_ints++] = (uintptr_t)externref_obj;
|
||||||
|
else
|
||||||
|
stacks[n_stacks++] = (uintptr_t)externref_obj;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_SIMD != 0
|
#if WASM_ENABLE_SIMD != 0
|
||||||
case VALUE_TYPE_V128:
|
case VALUE_TYPE_V128:
|
||||||
|
@ -3442,7 +3796,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
case VALUE_TYPE_I32:
|
case VALUE_TYPE_I32:
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_FUNCREF:
|
case VALUE_TYPE_FUNCREF:
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
#endif
|
#endif
|
||||||
argv_ret[0] =
|
argv_ret[0] =
|
||||||
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||||
|
@ -3459,6 +3812,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||||
PUT_F64_TO_ADDR(
|
PUT_F64_TO_ADDR(
|
||||||
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
case VALUE_TYPE_EXTERNREF:
|
||||||
|
{
|
||||||
|
if (is_aot_func) {
|
||||||
|
argv_ret[0] = invokeNative_Int32(func_ptr, argv1, n_stacks);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint32 externref_idx;
|
||||||
|
void *externref_obj = (void *)(uintptr_t)invokeNative_Int64(
|
||||||
|
func_ptr, argv1, n_stacks);
|
||||||
|
|
||||||
|
if (!wasm_externref_obj2ref(exec_env->module_inst,
|
||||||
|
externref_obj, &externref_idx))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
argv_ret[0] = externref_idx;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if WASM_ENABLE_SIMD != 0
|
#if WASM_ENABLE_SIMD != 0
|
||||||
case VALUE_TYPE_V128:
|
case VALUE_TYPE_V128:
|
||||||
*(v128 *)argv_ret =
|
*(v128 *)argv_ret =
|
||||||
|
@ -3709,10 +4082,24 @@ bool
|
||||||
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
||||||
uint32 *p_externref_idx)
|
uint32 *p_externref_idx)
|
||||||
{
|
{
|
||||||
LookupExtObj_UserData lookup_user_data;
|
LookupExtObj_UserData lookup_user_data = { 0 };
|
||||||
ExternRefMapNode *node;
|
ExternRefMapNode *node;
|
||||||
uint32 externref_idx;
|
uint32 externref_idx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* to catch a parameter from `wasm_application_execute_func`,
|
||||||
|
* which represents a string 'null'
|
||||||
|
*/
|
||||||
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|
if ((uint32)-1 == (uintptr_t)extern_obj) {
|
||||||
|
#else
|
||||||
|
if ((uint64)-1LL == (uintptr_t)extern_obj) {
|
||||||
|
#endif
|
||||||
|
*p_externref_idx = NULL_REF;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* in a wrapper, extern_obj could be any value */
|
||||||
lookup_user_data.node.extern_obj = extern_obj;
|
lookup_user_data.node.extern_obj = extern_obj;
|
||||||
lookup_user_data.node.module_inst = module_inst;
|
lookup_user_data.node.module_inst = module_inst;
|
||||||
lookup_user_data.found = false;
|
lookup_user_data.found = false;
|
||||||
|
@ -3764,8 +4151,10 @@ wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj)
|
||||||
{
|
{
|
||||||
ExternRefMapNode *node;
|
ExternRefMapNode *node;
|
||||||
|
|
||||||
|
/* catch a `ref.null` vairable */
|
||||||
if (externref_idx == NULL_REF) {
|
if (externref_idx == NULL_REF) {
|
||||||
return false;
|
*p_extern_obj = NULL;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_mutex_lock(&externref_lock);
|
os_mutex_lock(&externref_lock);
|
||||||
|
@ -4170,14 +4559,9 @@ argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
param->kind = WASM_ANYREF;
|
param->kind = WASM_ANYREF;
|
||||||
|
|
||||||
if (NULL_REF == *argv) {
|
if (!wasm_externref_ref2obj(*argv,
|
||||||
param->of.ref = NULL;
|
(void **)¶m->of.foreign)) {
|
||||||
}
|
return false;
|
||||||
else {
|
|
||||||
if (!wasm_externref_ref2obj(*argv,
|
|
||||||
(void **)¶m->of.ref)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
argv++;
|
argv++;
|
||||||
|
@ -4213,8 +4597,8 @@ results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
|
||||||
break;
|
break;
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
case VALUE_TYPE_EXTERNREF:
|
case VALUE_TYPE_EXTERNREF:
|
||||||
if (!wasm_externref_obj2ref(module_inst, result->of.ref,
|
if (!wasm_externref_obj2ref(module_inst,
|
||||||
argv)) {
|
(void *)result->of.foreign, argv)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
argv++;
|
argv++;
|
||||||
|
@ -4234,17 +4618,19 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
|
||||||
uint32 argc, uint32 *argv, bool with_env,
|
uint32 argc, uint32 *argv, bool with_env,
|
||||||
void *wasm_c_api_env)
|
void *wasm_c_api_env)
|
||||||
{
|
{
|
||||||
wasm_val_t params_buf[16], results_buf[4];
|
wasm_val_t params_buf[16] = { 0 }, results_buf[4] = { 0 };
|
||||||
wasm_val_t *params = params_buf, *results = results_buf;
|
wasm_val_t *params = params_buf, *results = results_buf;
|
||||||
wasm_trap_t *trap = NULL;
|
wasm_trap_t *trap = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
wasm_val_vec_t params_vec, results_vec;
|
wasm_val_vec_t params_vec, results_vec;
|
||||||
|
|
||||||
if (func_type->param_count > 16
|
if (func_type->param_count > 16) {
|
||||||
&& !(params = wasm_runtime_malloc(sizeof(wasm_val_t)
|
if (!(params =
|
||||||
* func_type->param_count))) {
|
runtime_malloc(sizeof(wasm_val_t) * func_type->param_count,
|
||||||
wasm_runtime_set_exception(module_inst, "allocate memory failed");
|
module_inst, NULL, 0))) {
|
||||||
return false;
|
wasm_runtime_set_exception(module_inst, "allocate memory failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!argv_to_params(params, argv, func_type)) {
|
if (!argv_to_params(params, argv, func_type)) {
|
||||||
|
@ -4252,11 +4638,13 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_type->result_count > 4
|
if (func_type->result_count > 4) {
|
||||||
&& !(results = wasm_runtime_malloc(sizeof(wasm_val_t)
|
if (!(results =
|
||||||
* func_type->result_count))) {
|
runtime_malloc(sizeof(wasm_val_t) * func_type->result_count,
|
||||||
wasm_runtime_set_exception(module_inst, "allocate memory failed");
|
module_inst, NULL, 0))) {
|
||||||
goto fail;
|
wasm_runtime_set_exception(module_inst, "allocate memory failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params_vec.data = params;
|
params_vec.data = params;
|
||||||
|
|
|
@ -525,11 +525,6 @@ bool
|
||||||
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
|
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
|
||||||
uint32 argc, uint32 argv[]);
|
uint32 argc, uint32 argv[]);
|
||||||
|
|
||||||
bool
|
|
||||||
wasm_runtime_create_exec_env_and_call_wasm(
|
|
||||||
WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function,
|
|
||||||
uint32 argc, uint32 argv[]);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
|
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
|
||||||
|
|
||||||
|
@ -813,16 +808,6 @@ wasm_runtime_dump_module_inst_mem_consumption(
|
||||||
void
|
void
|
||||||
wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
|
wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
void
|
|
||||||
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
|
|
||||||
WASMFunctionInstanceCommon *function);
|
|
||||||
void
|
|
||||||
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
|
||||||
WASMFunctionInstanceCommon *function,
|
|
||||||
bool ret, uint32 *argv);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
|
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
|
||||||
const WASMExport *export_, WASMType **out);
|
const WASMExport *export_, WASMType **out);
|
||||||
|
|
|
@ -96,6 +96,7 @@ typedef struct AOTMemInitData {
|
||||||
typedef struct AOTImportTable {
|
typedef struct AOTImportTable {
|
||||||
char *module_name;
|
char *module_name;
|
||||||
char *table_name;
|
char *table_name;
|
||||||
|
uint32 elem_type;
|
||||||
uint32 table_flags;
|
uint32 table_flags;
|
||||||
uint32 table_init_size;
|
uint32 table_init_size;
|
||||||
uint32 table_max_size;
|
uint32 table_max_size;
|
||||||
|
|
|
@ -1398,6 +1398,7 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||||
* EMIT_STR(comp_data->import_tables[i].module_name );
|
* EMIT_STR(comp_data->import_tables[i].module_name );
|
||||||
* EMIT_STR(comp_data->import_tables[i].table_name);
|
* EMIT_STR(comp_data->import_tables[i].table_name);
|
||||||
*/
|
*/
|
||||||
|
EMIT_U32(comp_data->import_tables[i].elem_type);
|
||||||
EMIT_U32(comp_data->import_tables[i].table_init_size);
|
EMIT_U32(comp_data->import_tables[i].table_init_size);
|
||||||
EMIT_U32(comp_data->import_tables[i].table_max_size);
|
EMIT_U32(comp_data->import_tables[i].table_max_size);
|
||||||
EMIT_U32(comp_data->import_tables[i].possible_grow & 0x000000FF);
|
EMIT_U32(comp_data->import_tables[i].possible_grow & 0x000000FF);
|
||||||
|
|
|
@ -155,16 +155,17 @@ enum wasm_valkind_enum {
|
||||||
|
|
||||||
#ifndef WASM_VAL_T_DEFINED
|
#ifndef WASM_VAL_T_DEFINED
|
||||||
#define WASM_VAL_T_DEFINED
|
#define WASM_VAL_T_DEFINED
|
||||||
struct wasm_ref_t;
|
|
||||||
|
|
||||||
typedef struct wasm_val_t {
|
typedef struct wasm_val_t {
|
||||||
wasm_valkind_t kind;
|
wasm_valkind_t kind;
|
||||||
union {
|
union {
|
||||||
|
/* also represent a function index */
|
||||||
int32_t i32;
|
int32_t i32;
|
||||||
int64_t i64;
|
int64_t i64;
|
||||||
float f32;
|
float f32;
|
||||||
double f64;
|
double f64;
|
||||||
struct wasm_ref_t *ref;
|
/* represent a foreign object, aka externref in .wat */
|
||||||
|
uintptr_t foreign;
|
||||||
} of;
|
} of;
|
||||||
} wasm_val_t;
|
} wasm_val_t;
|
||||||
#endif
|
#endif
|
||||||
|
@ -790,6 +791,7 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
|
||||||
* 'I': the parameter is i64 type
|
* 'I': the parameter is i64 type
|
||||||
* 'f': the parameter is f32 type
|
* 'f': the parameter is f32 type
|
||||||
* 'F': the parameter is f64 type
|
* 'F': the parameter is f64 type
|
||||||
|
* 'r': the parameter is externref type, it should be a uintptr_t in host
|
||||||
* '*': the parameter is a pointer (i32 in WASM), and runtime will
|
* '*': the parameter is a pointer (i32 in WASM), and runtime will
|
||||||
* auto check its boundary before calling the native function.
|
* auto check its boundary before calling the native function.
|
||||||
* If it is followed by '~', the checked length of the pointer
|
* If it is followed by '~', the checked length of the pointer
|
||||||
|
|
|
@ -544,6 +544,19 @@ wasm_get_cell_num(const uint8 *types, uint32 type_count)
|
||||||
return cell_num;
|
return cell_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_REF_TYPES != 0
|
||||||
|
inline static uint16
|
||||||
|
wasm_value_type_cell_num_outside(uint8 value_type)
|
||||||
|
{
|
||||||
|
if (VALUE_TYPE_EXTERNREF == value_type) {
|
||||||
|
return sizeof(uintptr_t) / sizeof(uint32);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return wasm_value_type_cell_num(value_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline static bool
|
inline static bool
|
||||||
wasm_type_equal(const WASMType *type1, const WASMType *type2)
|
wasm_type_equal(const WASMType *type1, const WASMType *type2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1748,16 +1748,8 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
wasm_runtime_prepare_call_function(exec_env, func);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = wasm_call_function(exec_env, func, argc, argv);
|
ret = wasm_call_function(exec_env, func, argc, argv);
|
||||||
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
wasm_runtime_finalize_call_function(exec_env, func, ret, argv);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WASM_ENABLE_THREAD_MGR != 0
|
#if WASM_ENABLE_THREAD_MGR != 0
|
||||||
/* don't destroy the exec_env if it's searched from the cluster */
|
/* don't destroy the exec_env if it's searched from the cluster */
|
||||||
if (!existing_exec_env)
|
if (!existing_exec_env)
|
||||||
|
@ -1770,9 +1762,14 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
|
||||||
bool
|
bool
|
||||||
wasm_create_exec_env_singleton(WASMModuleInstance *module_inst)
|
wasm_create_exec_env_singleton(WASMModuleInstance *module_inst)
|
||||||
{
|
{
|
||||||
WASMExecEnv *exec_env =
|
WASMExecEnv *exec_env = NULL;
|
||||||
wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
|
|
||||||
module_inst->default_wasm_stack_size);
|
if (module_inst->exec_env_singleton) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_env = wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
|
||||||
|
module_inst->default_wasm_stack_size);
|
||||||
if (exec_env)
|
if (exec_env)
|
||||||
module_inst->exec_env_singleton = exec_env;
|
module_inst->exec_env_singleton = exec_env;
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,9 @@ os_mem_decommit(void *ptr, size_t size);
|
||||||
|
|
||||||
#define os_thread_local_attribute __declspec(thread)
|
#define os_thread_local_attribute __declspec(thread)
|
||||||
|
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
|
||||||
#if WASM_DISABLE_HW_BOUND_CHECK == 0
|
#if WASM_DISABLE_HW_BOUND_CHECK == 0
|
||||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
|
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,11 @@ The function signature field in **NativeSymbol** structure is a string for descr
|
||||||
|
|
||||||
Each letter in the "()" represents a parameter type, and the one following after ")" represents the return value type. The meaning of each letter:
|
Each letter in the "()" represents a parameter type, and the one following after ")" represents the return value type. The meaning of each letter:
|
||||||
|
|
||||||
- '**i**': i32 or externref (for externref, developer should use `wasm_externref_obj2ref()` to map host object to externref index firstly)
|
- '**i**': i32
|
||||||
- '**I**': i64
|
- '**I**': i64
|
||||||
- '**f**': f32
|
- '**f**': f32
|
||||||
- '**F**': f64
|
- '**F**': f64
|
||||||
|
- '**r**': externref (has to be the value of a `uintptr_t` variable)
|
||||||
- '**\***': the parameter is a buffer address in WASM application
|
- '**\***': the parameter is a buffer address in WASM application
|
||||||
- '**~**': the parameter is the byte length of WASM buffer as referred by preceding argument "\*". It must follow after '*', otherwise, registration will fail
|
- '**~**': the parameter is the byte length of WASM buffer as referred by preceding argument "\*". It must follow after '*', otherwise, registration will fail
|
||||||
- '**$**': the parameter is a string in WASM application
|
- '**$**': the parameter is a string in WASM application
|
||||||
|
|
|
@ -1,22 +1,9 @@
|
||||||
# WAMR reference-types introduction
|
# WAMR reference-types introduction
|
||||||
|
|
||||||
WebAssembly [reference-types](https://github.com/WebAssembly/reference-types) proposal introduces the new type `externref` and makes it easier and more efficient to interoperate with host environment, allowing host references to be represented directly by type externref. And WASM modules can talk about host references directly, rather than requiring external glue code running in the host.
|
WebAssembly [reference-types](https://github.com/WebAssembly/reference-types) proposal introduces two new types `funcref` and `externref`. With `externref`, It is easier and more efficient to interoperate with host environment. Host references are able to be represented directly by type `externref`.
|
||||||
|
|
||||||
WAMR implements the reference-types proposal, allowing developer to pass the host object to WASM application and then restore and access the host object in native lib. In WAMR internal, the external host object is represented as externref index with `uint32` type, developer must firstly map the host object of `void *` type to the externref index, and then pass the index to the function to called as the function's externref argument.
|
WAMR has implemented the reference-types proposal. WAMR allows a native method to pass a host object to a WASM application as an `externref` parameter or receives a host object from a WASM application as an `externref` result. Internally, WAMR won't try to parse or dereference `externref`. It is an opaque type.
|
||||||
|
|
||||||
Currently WAMR provides APIs as below:
|
The restriction of using `externref` in a native method is the host object has to be the value of a `unintptr_t` variable. In other words, it takes **8 bytes** on 64-bit machine and **4 bytes** on 32-bit machines. Please keep that in mind especially when calling `wasm_runtime_call_wasm`.
|
||||||
```C
|
|
||||||
bool
|
|
||||||
wasm_externref_obj2ref(wasm_module_inst_t module_inst,
|
|
||||||
void *extern_obj, uint32_t *p_externref_idx);
|
|
||||||
|
|
||||||
WASM_RUNTIME_API_EXTERN bool
|
|
||||||
wasm_externref_ref2obj(uint32_t externref_idx, void **p_extern_obj);
|
|
||||||
|
|
||||||
WASM_RUNTIME_API_EXTERN bool
|
|
||||||
wasm_externref_retain(uint32 externref_idx);
|
|
||||||
```
|
|
||||||
|
|
||||||
The `wasm_externref_obj2ref()` API is used to map the host object to the externref index, and the `wasm_externref_ref2obj()` API is used to retrieve the original host object mapped. The `wasm_externref_retain()` API is to retain the host object if we don't want the object to be cleaned when it isn't used during externref object reclaim.
|
|
||||||
|
|
||||||
Please ref to the [sample](../samples/ref-types) for more details.
|
Please ref to the [sample](../samples/ref-types) for more details.
|
||||||
|
|
|
@ -116,7 +116,7 @@ endif()
|
||||||
# wat to wasm
|
# wat to wasm
|
||||||
file(GLOB WAT_FILE src/hello.wat)
|
file(GLOB WAT_FILE src/hello.wat)
|
||||||
add_custom_target(hello_wasm ALL
|
add_custom_target(hello_wasm ALL
|
||||||
COMMAND ${WAT2WASM} ${WAT_FILE} -o ${PROJECT_BINARY_DIR}/hello.wasm
|
COMMAND ${WAT2WASM} ${WAT_FILE} --enable-reference-types -o ${PROJECT_BINARY_DIR}/hello.wasm
|
||||||
DEPENDS ${WAT_FILE}
|
DEPENDS ${WAT_FILE}
|
||||||
BYPRODUCTS ${PROJECT_BINARY_DIR}/hello.wasm
|
BYPRODUCTS ${PROJECT_BINARY_DIR}/hello.wasm
|
||||||
VERBATIM
|
VERBATIM
|
||||||
|
|
|
@ -13,52 +13,170 @@
|
||||||
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
|
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static uintptr_t global_objects[10] = { 0 };
|
||||||
test_write_wrapper(wasm_exec_env_t exec_env, uint32 externref_idx_of_file,
|
|
||||||
const char *str, int len)
|
int32
|
||||||
|
local_cmp_externref(wasm_exec_env_t exec_env, uintptr_t externref_a,
|
||||||
|
uintptr_t externref_b)
|
||||||
{
|
{
|
||||||
FILE *file;
|
return externref_a == externref_b;
|
||||||
char buf[16];
|
}
|
||||||
|
|
||||||
printf("## retrieve file handle from externref index\n");
|
int32
|
||||||
if (!wasm_externref_ref2obj(externref_idx_of_file, (void **)&file)) {
|
local_chk_externref(wasm_exec_env_t exec_env, int32 index, uintptr_t externref)
|
||||||
printf("failed to get host object from externref index!\n");
|
{
|
||||||
return -1;
|
return externref == global_objects[index];
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%%%ds", len);
|
|
||||||
|
|
||||||
printf("## write string to file: ");
|
|
||||||
printf(buf, str);
|
|
||||||
|
|
||||||
return fprintf(file, buf, str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
static NativeSymbol native_symbols[] = {
|
static NativeSymbol native_symbols[] = {
|
||||||
{ "test_write", test_write_wrapper, "(i*~)i", NULL }
|
{ "native-cmp-externref", local_cmp_externref, "(II)i", NULL },
|
||||||
|
{ "native-chk-externref", local_chk_externref, "(iI)i", NULL },
|
||||||
};
|
};
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
local_set_externref(int32 index, uintptr_t externref)
|
||||||
|
{
|
||||||
|
global_objects[index] = externref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WASMFunctionInstanceCommon *wasm_set_externref_ptr;
|
||||||
|
static WASMFunctionInstanceCommon *wasm_get_externref_ptr;
|
||||||
|
static WASMFunctionInstanceCommon *wasm_cmp_externref_ptr;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wasm_set_externref(wasm_exec_env_t exec_env, wasm_module_inst_t inst,
|
||||||
|
int32 index, uintptr_t externref)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uintptr_t val;
|
||||||
|
uint32 parts[2];
|
||||||
|
} u;
|
||||||
|
uint32 argv[3] = { 0 };
|
||||||
|
|
||||||
|
if (!exec_env || !wasm_set_externref_ptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u.val = externref;
|
||||||
|
argv[0] = index;
|
||||||
|
argv[1] = u.parts[0];
|
||||||
|
argv[2] = u.parts[1];
|
||||||
|
if (!wasm_runtime_call_wasm(exec_env, wasm_set_externref_ptr, 2, argv)) {
|
||||||
|
const char *exception;
|
||||||
|
if ((exception = wasm_runtime_get_exception(inst))) {
|
||||||
|
printf("Exception: %s\n", exception);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wasm_get_externref(wasm_exec_env_t exec_env, wasm_module_inst_t inst,
|
||||||
|
int32 index, uintptr_t *ret_externref)
|
||||||
|
{
|
||||||
|
wasm_val_t results[1] = { 0 };
|
||||||
|
|
||||||
|
if (!exec_env || !wasm_get_externref_ptr || !ret_externref) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasm_runtime_call_wasm_v(exec_env, wasm_get_externref_ptr, 1, results,
|
||||||
|
1, index)) {
|
||||||
|
const char *exception;
|
||||||
|
if ((exception = wasm_runtime_get_exception(inst))) {
|
||||||
|
printf("Exception: %s\n", exception);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WASM_ANYREF != results[0].kind) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_externref = results[0].of.foreign;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wasm_cmp_externref(wasm_exec_env_t exec_env, wasm_module_inst_t inst,
|
||||||
|
int32 index, uintptr_t externref, int32 *ret_result)
|
||||||
|
{
|
||||||
|
wasm_val_t results[1] = { 0 };
|
||||||
|
wasm_val_t arguments[2] = {
|
||||||
|
{ .kind = WASM_I32, .of.i32 = index },
|
||||||
|
{ .kind = WASM_ANYREF, .of.foreign = externref },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!exec_env || !wasm_cmp_externref_ptr || !ret_result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasm_runtime_call_wasm_a(exec_env, wasm_cmp_externref_ptr, 1, results,
|
||||||
|
2, arguments)) {
|
||||||
|
const char *exception;
|
||||||
|
if ((exception = wasm_runtime_get_exception(inst))) {
|
||||||
|
printf("Exception: %s\n", exception);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results[0].kind != WASM_I32) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_result = results[0].of.i32;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
set_and_cmp(wasm_exec_env_t exec_env, wasm_module_inst_t inst, int32 i,
|
||||||
|
uintptr_t externref)
|
||||||
|
{
|
||||||
|
int32 cmp_result = 0;
|
||||||
|
uintptr_t wasm_externref = 0;
|
||||||
|
|
||||||
|
wasm_set_externref(exec_env, inst, i, externref);
|
||||||
|
local_set_externref(i, externref);
|
||||||
|
|
||||||
|
wasm_get_externref(exec_env, inst, 0, &wasm_externref);
|
||||||
|
if (!local_chk_externref(exec_env, 0, wasm_externref)) {
|
||||||
|
printf("#%d, In host language world Wasm Externref 0x%lx Vs. Native "
|
||||||
|
"Externref 0x%lx FAILED\n",
|
||||||
|
i, wasm_externref, externref);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasm_cmp_externref(exec_env, inst, i, global_objects[i], &cmp_result)
|
||||||
|
|| !cmp_result) {
|
||||||
|
printf("#%d, In Wasm world Native Externref 0x%lx Vs, Wasm Externref "
|
||||||
|
"FAILED\n",
|
||||||
|
i, global_objects[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *wasm_file = "hello.wasm";
|
char *wasm_file = "hello.wasm";
|
||||||
uint8 *wasm_file_buf = NULL;
|
uint8 *wasm_file_buf = NULL;
|
||||||
uint32 wasm_file_size, externref_idx;
|
uint32 wasm_file_size;
|
||||||
uint32 stack_size = 16 * 1024, heap_size = 16 * 1024;
|
uint32 stack_size = 16 * 1024, heap_size = 16 * 1024;
|
||||||
wasm_module_t wasm_module = NULL;
|
wasm_module_t wasm_module = NULL;
|
||||||
wasm_module_inst_t wasm_module_inst = NULL;
|
wasm_module_inst_t wasm_module_inst = NULL;
|
||||||
wasm_function_inst_t func_inst = NULL;
|
|
||||||
wasm_exec_env_t exec_env = NULL;
|
wasm_exec_env_t exec_env = NULL;
|
||||||
RuntimeInitArgs init_args;
|
RuntimeInitArgs init_args;
|
||||||
char error_buf[128] = { 0 };
|
char error_buf[128] = { 0 };
|
||||||
const char *exce;
|
|
||||||
unsigned argv1[8];
|
|
||||||
#if WASM_ENABLE_LOG != 0
|
#if WASM_ENABLE_LOG != 0
|
||||||
int log_verbose_level = 2;
|
int log_verbose_level = 2;
|
||||||
#endif
|
#endif
|
||||||
FILE *file;
|
const uint64 big_number = 0x123456789abc;
|
||||||
|
|
||||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||||
|
|
||||||
|
@ -90,13 +208,13 @@ main(int argc, char *argv[])
|
||||||
/* load WASM byte buffer from WASM bin file */
|
/* load WASM byte buffer from WASM bin file */
|
||||||
if (!(wasm_file_buf =
|
if (!(wasm_file_buf =
|
||||||
(uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
|
(uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
|
||||||
goto fail1;
|
goto fail;
|
||||||
|
|
||||||
/* load WASM module */
|
/* load WASM module */
|
||||||
if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
|
if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
|
||||||
error_buf, sizeof(error_buf)))) {
|
error_buf, sizeof(error_buf)))) {
|
||||||
printf("%s\n", error_buf);
|
printf("%s\n", error_buf);
|
||||||
goto fail2;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instantiate the module */
|
/* instantiate the module */
|
||||||
|
@ -104,62 +222,66 @@ main(int argc, char *argv[])
|
||||||
wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
|
wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
|
||||||
error_buf, sizeof(error_buf)))) {
|
error_buf, sizeof(error_buf)))) {
|
||||||
printf("%s\n", error_buf);
|
printf("%s\n", error_buf);
|
||||||
goto fail3;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
/* lookup function instance */
|
|
||||||
if (!(func_inst =
|
|
||||||
wasm_runtime_lookup_function(wasm_module_inst, "test", NULL))) {
|
|
||||||
printf("%s\n", "lookup function test failed");
|
|
||||||
goto fail4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create an execution env */
|
||||||
if (!(exec_env =
|
if (!(exec_env =
|
||||||
wasm_runtime_create_exec_env(wasm_module_inst, stack_size))) {
|
wasm_runtime_create_exec_env(wasm_module_inst, stack_size))) {
|
||||||
printf("%s\n", "create exec env failed");
|
printf("%s\n", "create exec env failed");
|
||||||
goto fail4;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("## open file test.txt\n");
|
/* lookup function instance */
|
||||||
if (!(file = fopen("test.txt", "wb+"))) {
|
if (!(wasm_cmp_externref_ptr = wasm_runtime_lookup_function(
|
||||||
printf("%s\n", "open file text.txt failed");
|
wasm_module_inst, "cmp-externref", NULL))) {
|
||||||
goto fail5;
|
printf("%s\n", "lookup function cmp-externref failed");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("## map file handle to externref index\n");
|
if (!(wasm_get_externref_ptr = wasm_runtime_lookup_function(
|
||||||
if (!wasm_externref_obj2ref(wasm_module_inst, file, &externref_idx)) {
|
wasm_module_inst, "get-externref", NULL))) {
|
||||||
printf("%s\n", "map host object to externref index failed");
|
printf("%s\n", "lookup function get-externref failed");
|
||||||
goto fail6;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("## call wasm function with externref index\n");
|
if (!(wasm_set_externref_ptr = wasm_runtime_lookup_function(
|
||||||
argv1[0] = externref_idx;
|
wasm_module_inst, "set-externref", NULL))) {
|
||||||
wasm_runtime_call_wasm(exec_env, func_inst, 1, argv1);
|
printf("%s\n", "lookup function set-externref failed");
|
||||||
|
goto fail;
|
||||||
if ((exce = wasm_runtime_get_exception(wasm_module_inst))) {
|
|
||||||
printf("Exception: %s\n", exce);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fail6:
|
/* test with NULL */
|
||||||
fclose(file);
|
if (!set_and_cmp(exec_env, wasm_module_inst, 0, 0)
|
||||||
|
|| !set_and_cmp(exec_env, wasm_module_inst, 1, big_number + 1)
|
||||||
|
|| !set_and_cmp(exec_env, wasm_module_inst, 2, big_number + 2)
|
||||||
|
|| !set_and_cmp(exec_env, wasm_module_inst, 3, big_number + 3)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
fail5:
|
printf("GREAT! PASS ALL CHKs\n");
|
||||||
|
|
||||||
|
fail:
|
||||||
/* destroy exec env */
|
/* destroy exec env */
|
||||||
wasm_runtime_destroy_exec_env(exec_env);
|
if (exec_env) {
|
||||||
|
wasm_runtime_destroy_exec_env(exec_env);
|
||||||
|
}
|
||||||
|
|
||||||
fail4:
|
|
||||||
/* destroy the module instance */
|
/* destroy the module instance */
|
||||||
wasm_runtime_deinstantiate(wasm_module_inst);
|
if (wasm_module_inst) {
|
||||||
|
wasm_runtime_deinstantiate(wasm_module_inst);
|
||||||
|
}
|
||||||
|
|
||||||
fail3:
|
|
||||||
/* unload the module */
|
/* unload the module */
|
||||||
wasm_runtime_unload(wasm_module);
|
if (wasm_module) {
|
||||||
|
wasm_runtime_unload(wasm_module);
|
||||||
|
}
|
||||||
|
|
||||||
fail2:
|
|
||||||
/* free the file buffer */
|
/* free the file buffer */
|
||||||
wasm_runtime_free(wasm_file_buf);
|
if (wasm_file_buf) {
|
||||||
|
wasm_runtime_free(wasm_file_buf);
|
||||||
|
}
|
||||||
|
|
||||||
fail1:
|
|
||||||
/* destroy runtime environment */
|
/* destroy runtime environment */
|
||||||
wasm_runtime_destroy();
|
wasm_runtime_destroy();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,21 +2,43 @@
|
||||||
;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
|
||||||
(module
|
(module
|
||||||
;; import test_write function which is implemented by host
|
(type $t0 (func (param i32 externref) (result i32)))
|
||||||
(import "env" "test_write"
|
|
||||||
(func $test_write (param externref i32 i32) (result i32)))
|
|
||||||
|
|
||||||
;; memory with one page (64KiB).
|
(import "env" "native-cmp-externref"
|
||||||
(memory (export "memory") 1)
|
(func $native-cmp-externref (param externref externref) (result i32))
|
||||||
|
)
|
||||||
|
|
||||||
(data (i32.const 0x8) "Hello, world!\n")
|
(import "env" "native-chk-externref"
|
||||||
|
(func $native-chk-externref (param i32 externref) (result i32))
|
||||||
|
)
|
||||||
|
|
||||||
;; function that writes string to a given open file handle
|
(table $t1 8 8 externref)
|
||||||
(func (export "test") (param externref)
|
(table $t2 funcref
|
||||||
(local.get 0)
|
(elem
|
||||||
(i32.const 0x8)
|
$native-cmp-externref
|
||||||
(i32.const 14)
|
$native-chk-externref
|
||||||
(call $test_write)
|
)
|
||||||
drop
|
)
|
||||||
|
|
||||||
|
(func (export "set-externref") (param $i i32) (param $r externref)
|
||||||
|
(table.set $t1 (local.get $i) (local.get $r))
|
||||||
|
)
|
||||||
|
|
||||||
|
(func (export "get-externref") (param $i i32) (result externref)
|
||||||
|
(table.get $t1 (local.get $i))
|
||||||
|
)
|
||||||
|
|
||||||
|
(func (export "cmp-externref") (param $i i32) (param $r externref) (result i32)
|
||||||
|
(table.get $t1 (local.get $i))
|
||||||
|
(local.get $r)
|
||||||
|
(call $native-cmp-externref)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func (export "chk-externref") (param $i i32) (param $r externref) (result i32)
|
||||||
|
(call_indirect $t2 (type $t0)
|
||||||
|
(local.get $i)
|
||||||
|
(local.get $r)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -35,7 +35,7 @@ void wasm_val_print(wasm_val_t val) {
|
||||||
|
|
||||||
// A function to be called from Wasm code.
|
// A function to be called from Wasm code.
|
||||||
own wasm_trap_t* print_callback(
|
own wasm_trap_t* print_callback(
|
||||||
const wasm_val_vec_t *args, wasm_val_vec_t *results
|
const wasm_val_vec_t* args, wasm_val_vec_t* results
|
||||||
) {
|
) {
|
||||||
printf("Calling back...\n> ");
|
printf("Calling back...\n> ");
|
||||||
wasm_val_print(args->data[0]);
|
wasm_val_print(args->data[0]);
|
||||||
|
@ -48,7 +48,7 @@ own wasm_trap_t* print_callback(
|
||||||
|
|
||||||
// A function closure.
|
// A function closure.
|
||||||
own wasm_trap_t* closure_callback(
|
own wasm_trap_t* closure_callback(
|
||||||
void* env, const wasm_val_vec_t *args, wasm_val_vec_t *results
|
void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
|
||||||
) {
|
) {
|
||||||
int i = *(int*)env;
|
int i = *(int*)env;
|
||||||
printf("Calling back closure...\n");
|
printf("Calling back closure...\n");
|
||||||
|
@ -113,11 +113,10 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
|
wasm_extern_t* externs[] = {
|
||||||
wasm_extern_vec_t imports;
|
|
||||||
wasm_extern_vec_new(&imports, 2, (wasm_extern_t *[]) {
|
|
||||||
wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func)
|
wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func)
|
||||||
});
|
};
|
||||||
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
@ -147,9 +146,10 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Call.
|
// Call.
|
||||||
printf("Calling export...\n");
|
printf("Calling export...\n");
|
||||||
wasm_val_vec_t args, results;
|
wasm_val_t as[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
|
||||||
wasm_val_vec_new(&args, 2, (wasm_val_t[]){ WASM_I32_VAL(3), WASM_I32_VAL(4) });
|
wasm_val_t rs[1] = { WASM_INIT_VAL };
|
||||||
wasm_val_vec_new(&results, 1, (wasm_val_t[]) { WASM_INIT_VAL });
|
wasm_val_vec_t args = WASM_ARRAY_VEC(as);
|
||||||
|
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
|
||||||
if (wasm_func_call(run_func, &args, &results)) {
|
if (wasm_func_call(run_func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -159,7 +159,7 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Print result.
|
// Print result.
|
||||||
printf("Printing result...\n");
|
printf("Printing result...\n");
|
||||||
printf("> %u\n", results.data[0].of.i32);
|
printf("> %u\n", rs[0].of.i32);
|
||||||
|
|
||||||
// Shut down.
|
// Shut down.
|
||||||
printf("Shutting down...\n");
|
printf("Shutting down...\n");
|
||||||
|
|
|
@ -61,10 +61,7 @@ enum EXPORT_ITEM_NAME {
|
||||||
|
|
||||||
DEFINE_FUNCTION(get_pairs)
|
DEFINE_FUNCTION(get_pairs)
|
||||||
{
|
{
|
||||||
wasm_val_vec_t arg, ret;
|
call_wasm_function(e_malloc, args, results, "malloc");
|
||||||
wasm_val_vec_new(&ret, 1, (wasm_val_t []){ WASM_INIT_VAL });
|
|
||||||
wasm_val_vec_new(&arg, 1, (wasm_val_t []){ WASM_I32_VAL(24) });
|
|
||||||
call_wasm_function(e_malloc, &arg, &ret, "malloc");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,9 +201,6 @@ main(int argc, const char *argv[])
|
||||||
IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME)
|
IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME)
|
||||||
#undef IMPORT_FUNCTION_VARIABLE_NAME
|
#undef IMPORT_FUNCTION_VARIABLE_NAME
|
||||||
|
|
||||||
wasm_extern_vec_t imports;
|
|
||||||
wasm_extern_vec_new_uninitialized(&imports, 10);
|
|
||||||
|
|
||||||
#define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \
|
#define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \
|
||||||
{ \
|
{ \
|
||||||
own wasm_functype_t *type = CREATE_FUNC_TYPE; \
|
own wasm_functype_t *type = CREATE_FUNC_TYPE; \
|
||||||
|
@ -219,13 +213,13 @@ main(int argc, const char *argv[])
|
||||||
IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
|
IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
|
||||||
#undef CREATE_WASM_FUNCTION
|
#undef CREATE_WASM_FUNCTION
|
||||||
|
|
||||||
|
wasm_extern_t *fs[10] = {0};
|
||||||
#define ADD_TO_FUNCTION_LIST(name, index, ...) \
|
#define ADD_TO_FUNCTION_LIST(name, index, ...) \
|
||||||
imports.data[index] = wasm_func_as_extern(function_##name); \
|
fs[index] = wasm_func_as_extern(function_##name);
|
||||||
imports.num_elems += 1;
|
|
||||||
IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)
|
IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST)
|
||||||
#undef CREATE_IMPORT_FUNCTION
|
#undef ADD_TO_FUNCTION_LIST
|
||||||
|
|
||||||
|
|
||||||
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(fs);
|
||||||
own wasm_instance_t *instance =
|
own wasm_instance_t *instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
|
|
@ -39,10 +39,11 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) {
|
||||||
|
|
||||||
#define check_call(func, type, expected) \
|
#define check_call(func, type, expected) \
|
||||||
{ \
|
{ \
|
||||||
wasm_val_vec_t results; \
|
wasm_val_t vs[1]; \
|
||||||
wasm_val_vec_new_uninitialized(&results, 1); \
|
wasm_val_vec_t args = WASM_EMPTY_VEC; \
|
||||||
wasm_func_call(func, NULL, &results); \
|
wasm_val_vec_t results = WASM_ARRAY_VEC(vs); \
|
||||||
check(results.data[0], type, expected); \
|
wasm_func_call(func, &args, &results); \
|
||||||
|
check(vs[0], type, expected); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,19 +117,13 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
/*const wasm_extern_t* imports1[] = {
|
wasm_extern_t* externs[] = {
|
||||||
wasm_global_as_extern(const_f32_import),
|
wasm_global_as_extern(const_f32_import),
|
||||||
wasm_global_as_extern(const_i64_import),
|
wasm_global_as_extern(const_i64_import),
|
||||||
wasm_global_as_extern(var_f32_import),
|
wasm_global_as_extern(var_f32_import),
|
||||||
wasm_global_as_extern(var_i64_import)
|
wasm_global_as_extern(var_i64_import)
|
||||||
};*/
|
};
|
||||||
wasm_extern_vec_t imports;
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||||
wasm_extern_vec_new(&imports, 4, (wasm_extern_t* []) {
|
|
||||||
wasm_global_as_extern(const_f32_import),
|
|
||||||
wasm_global_as_extern(const_i64_import),
|
|
||||||
wasm_global_as_extern(var_f32_import),
|
|
||||||
wasm_global_as_extern(var_i64_import)
|
|
||||||
});
|
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
@ -208,18 +203,19 @@ int main(int argc, const char* argv[]) {
|
||||||
check_call(get_var_i64_export, i64, 38);
|
check_call(get_var_i64_export, i64, 38);
|
||||||
|
|
||||||
// Modify variables through calls and check again.
|
// Modify variables through calls and check again.
|
||||||
wasm_val_vec_t args73;
|
wasm_val_vec_t res = WASM_EMPTY_VEC;
|
||||||
wasm_val_vec_new(&args73, 1, (wasm_val_t []){ WASM_F32_VAL(73) });
|
wasm_val_t vs73[] = { WASM_F32_VAL(73) };
|
||||||
wasm_func_call(set_var_f32_import, &args73, NULL);
|
wasm_val_vec_t args73 = WASM_ARRAY_VEC(vs73);
|
||||||
wasm_val_vec_t args74;
|
wasm_func_call(set_var_f32_import, &args73, &res);
|
||||||
wasm_val_vec_new(&args74, 1, (wasm_val_t []){ WASM_I64_VAL(74) });
|
wasm_val_t vs74[] = { WASM_I64_VAL(74) };
|
||||||
wasm_func_call(set_var_i64_import, &args74, NULL);
|
wasm_val_vec_t args74 = WASM_ARRAY_VEC(vs74);
|
||||||
wasm_val_vec_t args77;
|
wasm_func_call(set_var_i64_import, &args74, &res);
|
||||||
wasm_val_vec_new(&args77, 1, (wasm_val_t []){ WASM_F32_VAL(77) });
|
wasm_val_t vs77[] = { WASM_F32_VAL(77) };
|
||||||
wasm_func_call(set_var_f32_export, &args77, NULL);
|
wasm_val_vec_t args77 = WASM_ARRAY_VEC(vs77);
|
||||||
wasm_val_vec_t args78;
|
wasm_func_call(set_var_f32_export, &args77, &res);
|
||||||
wasm_val_vec_new(&args78, 1, (wasm_val_t []){ WASM_I64_VAL(78) });
|
wasm_val_t vs78[] = { WASM_I64_VAL(78) };
|
||||||
wasm_func_call(set_var_i64_export, &args78, NULL);
|
wasm_val_vec_t args78 = WASM_ARRAY_VEC(vs78);
|
||||||
|
wasm_func_call(set_var_i64_export, &args78, &res);
|
||||||
|
|
||||||
check_global(var_f32_import, f32, 73);
|
check_global(var_f32_import, f32, 73);
|
||||||
check_global(var_i64_import, i64, 74);
|
check_global(var_i64_import, i64, 74);
|
||||||
|
|
|
@ -66,9 +66,8 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
wasm_extern_vec_t imports;
|
wasm_extern_t* externs[] = { wasm_func_as_extern(hello_func) };
|
||||||
wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(hello_func) });
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||||
|
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
@ -98,7 +97,9 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Call.
|
// Call.
|
||||||
printf("Calling export...\n");
|
printf("Calling export...\n");
|
||||||
if (wasm_func_call(run_func, NULL, NULL)) {
|
wasm_val_vec_t args = WASM_EMPTY_VEC;
|
||||||
|
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||||
|
if (wasm_func_call(run_func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -114,4 +115,3 @@ int main(int argc, const char* argv[]) {
|
||||||
printf("Done.\n");
|
printf("Done.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,21 +47,23 @@ wasm_table_t* get_export_table(const wasm_extern_vec_t* exports, size_t i) {
|
||||||
|
|
||||||
own wasm_ref_t* call_v_r(const wasm_func_t* func) {
|
own wasm_ref_t* call_v_r(const wasm_func_t* func) {
|
||||||
printf("call_v_r... "); fflush(stdout);
|
printf("call_v_r... "); fflush(stdout);
|
||||||
wasm_val_vec_t rs;
|
wasm_val_t rs[] = { WASM_INIT_VAL };
|
||||||
wasm_val_vec_new_uninitialized(&rs, 1);
|
wasm_val_vec_t args = WASM_EMPTY_VEC;
|
||||||
if (wasm_func_call(func, NULL, &rs)) {
|
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
|
||||||
|
if (wasm_func_call(func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
printf("okay\n");
|
printf("okay\n");
|
||||||
return rs.data[0].of.ref;
|
return rs[0].of.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) {
|
void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) {
|
||||||
printf("call_r_v... "); fflush(stdout);
|
printf("call_r_v... "); fflush(stdout);
|
||||||
wasm_val_vec_t vs;
|
wasm_val_t vs[1] = { WASM_REF_VAL(ref) };
|
||||||
wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_REF_VAL(ref) });
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
|
||||||
if (wasm_func_call(func, &vs, NULL)) {
|
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||||
|
if (wasm_func_call(func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -70,22 +72,24 @@ void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) {
|
||||||
|
|
||||||
own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) {
|
own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) {
|
||||||
printf("call_r_r... "); fflush(stdout);
|
printf("call_r_r... "); fflush(stdout);
|
||||||
wasm_val_vec_t vs, rs;
|
wasm_val_t vs[1] = { WASM_REF_VAL(ref) };
|
||||||
wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_REF_VAL(ref) });
|
wasm_val_t rs[1] = { WASM_INIT_VAL };
|
||||||
wasm_val_vec_new_uninitialized(&rs, 1);
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
|
||||||
if (wasm_func_call(func, &vs, &rs)) {
|
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
|
||||||
|
if (wasm_func_call(func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
printf("okay\n");
|
printf("okay\n");
|
||||||
return rs.data[0].of.ref;
|
return rs[0].of.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) {
|
void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) {
|
||||||
printf("call_ir_v... "); fflush(stdout);
|
printf("call_ir_v... "); fflush(stdout);
|
||||||
wasm_val_vec_t vs;
|
wasm_val_t vs[2] = { WASM_I32_VAL(i), WASM_REF_VAL(ref) };
|
||||||
wasm_val_vec_new(&vs, 2, (wasm_val_t []){ WASM_I32_VAL(i), WASM_REF_VAL(ref) });
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
|
||||||
if (wasm_func_call(func, &vs, NULL)) {
|
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||||
|
if (wasm_func_call(func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -94,31 +98,30 @@ void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) {
|
||||||
|
|
||||||
own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) {
|
own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) {
|
||||||
printf("call_i_r... "); fflush(stdout);
|
printf("call_i_r... "); fflush(stdout);
|
||||||
wasm_val_vec_t vs, rs;
|
wasm_val_t vs[1] = { WASM_I32_VAL(i) };
|
||||||
wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_I32_VAL(i) });
|
wasm_val_t rs[1] = { WASM_INIT_VAL };
|
||||||
wasm_val_vec_new_uninitialized(&rs, 1);
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
|
||||||
if (wasm_func_call(func, &vs, &rs)) {
|
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
|
||||||
|
if (wasm_func_call(func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
printf("okay\n");
|
printf("okay\n");
|
||||||
return rs.data[0].of.ref;
|
return rs[0].of.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void check(own wasm_ref_t* actual, const wasm_ref_t* expected) {
|
||||||
check(own wasm_ref_t *actual, const wasm_ref_t *expected, bool release_ref)
|
if (actual != expected &&
|
||||||
{
|
!(actual && expected && wasm_ref_same(actual, expected))) {
|
||||||
if (actual != expected
|
printf("> Error reading reference, expected %p, got %p\n",
|
||||||
&& !(actual && expected && wasm_ref_same(actual, expected))) {
|
expected ? wasm_ref_get_host_info(expected) : NULL,
|
||||||
printf("> Error reading reference, expected %p, got %p\n",
|
actual ? wasm_ref_get_host_info(actual) : NULL);
|
||||||
expected ? wasm_ref_get_host_info(expected) : NULL,
|
exit(1);
|
||||||
actual ? wasm_ref_get_host_info(actual) : NULL);
|
}
|
||||||
exit(1);
|
// if (actual) wasm_ref_delete(actual);
|
||||||
}
|
|
||||||
if (release_ref && actual)
|
|
||||||
wasm_ref_delete(actual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
// Initialize.
|
// Initialize.
|
||||||
printf("Initializing...\n");
|
printf("Initializing...\n");
|
||||||
|
@ -169,8 +172,8 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
wasm_extern_vec_t imports;
|
wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) };
|
||||||
wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(callback_func) });
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
@ -204,54 +207,61 @@ int main(int argc, const char* argv[]) {
|
||||||
wasm_ref_set_host_info(host2, (void*)2);
|
wasm_ref_set_host_info(host2, (void*)2);
|
||||||
|
|
||||||
// Some sanity checks.
|
// Some sanity checks.
|
||||||
check(NULL, NULL, true);
|
check(NULL, NULL);
|
||||||
check(wasm_ref_copy(host1), host1, true);
|
wasm_ref_t *host1_cp = wasm_ref_copy(host1);
|
||||||
check(wasm_ref_copy(host2), host2, true);
|
wasm_ref_t *host2_cp = wasm_ref_copy(host2);
|
||||||
|
check(host1_cp, host1);
|
||||||
|
check(host2_cp, host2);
|
||||||
|
wasm_ref_delete(host1_cp);
|
||||||
|
wasm_ref_delete(host2_cp);
|
||||||
|
|
||||||
own wasm_val_t val;
|
own wasm_val_t val;
|
||||||
val.kind = WASM_ANYREF;
|
val.kind = WASM_ANYREF;
|
||||||
val.of.ref = wasm_ref_copy(host1);
|
val.of.ref = wasm_ref_copy(host1);
|
||||||
check(wasm_ref_copy(val.of.ref), host1, true);
|
wasm_ref_t *ref_cp = wasm_ref_copy(val.of.ref);
|
||||||
own wasm_ref_t* ref = val.of.ref;
|
check(ref_cp, host1);
|
||||||
check(wasm_ref_copy(ref), host1, true);
|
check(val.of.ref, host1);
|
||||||
wasm_ref_delete(val.of.ref);
|
wasm_ref_delete(val.of.ref);
|
||||||
|
wasm_ref_delete(ref_cp);
|
||||||
|
|
||||||
// Interact.
|
// Interact.
|
||||||
printf("Accessing global...\n");
|
printf("Accessing global...\n");
|
||||||
check(call_v_r(global_get), NULL, false);
|
check(call_v_r(global_get), NULL);
|
||||||
call_r_v(global_set, host1);
|
call_r_v(global_set, host1);
|
||||||
check(call_v_r(global_get), host1, false);
|
check(call_v_r(global_get), host1);
|
||||||
call_r_v(global_set, host2);
|
call_r_v(global_set, host2);
|
||||||
check(call_v_r(global_get), host2, false);
|
check(call_v_r(global_get), host2);
|
||||||
call_r_v(global_set, NULL);
|
call_r_v(global_set, NULL);
|
||||||
check(call_v_r(global_get), NULL, false);
|
check(call_v_r(global_get), NULL);
|
||||||
|
|
||||||
wasm_global_get(global, &val);
|
wasm_global_get(global, &val);
|
||||||
assert(val.kind == WASM_ANYREF);
|
assert(val.kind == WASM_ANYREF);
|
||||||
check(val.of.ref, NULL, false);
|
assert(val.of.ref == NULL);
|
||||||
val.of.ref = host2;
|
val.of.ref = host2;
|
||||||
wasm_global_set(global, &val);
|
wasm_global_set(global, &val);
|
||||||
check(call_v_r(global_get), host2, false);
|
|
||||||
wasm_global_get(global, &val);
|
wasm_global_get(global, &val);
|
||||||
assert(val.kind == WASM_ANYREF);
|
assert(val.kind == WASM_ANYREF);
|
||||||
check(val.of.ref, host2, false);
|
assert(val.of.ref == host2);
|
||||||
|
|
||||||
printf("Accessing table...\n");
|
printf("Accessing table...\n");
|
||||||
check(call_i_r(table_get, 0), NULL, false);
|
check(call_i_r(table_get, 0), NULL);
|
||||||
check(call_i_r(table_get, 1), NULL, false);
|
check(call_i_r(table_get, 1), NULL);
|
||||||
call_ir_v(table_set, 0, host1);
|
call_ir_v(table_set, 0, host1);
|
||||||
call_ir_v(table_set, 1, host2);
|
call_ir_v(table_set, 1, host2);
|
||||||
check(call_i_r(table_get, 0), host1, false);
|
check(call_i_r(table_get, 0), host1);
|
||||||
check(call_i_r(table_get, 1), host2, false);
|
check(call_i_r(table_get, 1), host2);
|
||||||
call_ir_v(table_set, 0, NULL);
|
call_ir_v(table_set, 0, NULL);
|
||||||
check(call_i_r(table_get, 0), NULL, false);
|
check(call_i_r(table_get, 0), NULL);
|
||||||
|
|
||||||
check(wasm_table_get(table, 2), NULL, false);
|
check(wasm_table_get(table, 2), NULL);
|
||||||
|
wasm_table_set(table, 2, host1);
|
||||||
|
check(call_i_r(table_get, 2), host1);
|
||||||
|
check(wasm_table_get(table, 2), host1);
|
||||||
|
|
||||||
printf("Accessing function...\n");
|
printf("Accessing function...\n");
|
||||||
check(call_r_r(func_call, NULL), NULL, false);
|
check(call_r_r(func_call, NULL), NULL);
|
||||||
check(call_r_r(func_call, host1), host1, false);
|
check(call_r_r(func_call, host1), host1);
|
||||||
check(call_r_r(func_call, host2), host2, false);
|
check(call_r_r(func_call, host2), host2);
|
||||||
|
|
||||||
wasm_ref_delete(host1);
|
wasm_ref_delete(host1);
|
||||||
wasm_ref_delete(host2);
|
wasm_ref_delete(host2);
|
||||||
|
|
|
@ -33,13 +33,10 @@ void check(bool success) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) {
|
void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) {
|
||||||
wasm_val_vec_t args_vec;
|
wasm_val_t r[] = {WASM_INIT_VAL};
|
||||||
wasm_val_vec_t results_vec;
|
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
|
||||||
if (args)
|
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
|
||||||
wasm_val_vec_new(&args_vec, i, args);
|
if (wasm_func_call(func, &args_, &results) || r[0].of.i32 != expected) {
|
||||||
wasm_val_vec_new(&results_vec, 1, (wasm_val_t []){ WASM_INIT_VAL });
|
|
||||||
if (wasm_func_call(func, args ? &args_vec : NULL, &results_vec)
|
|
||||||
|| results_vec.data[0].of.i32 != expected) {
|
|
||||||
printf("> Error on result\n");
|
printf("> Error on result\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -60,9 +57,9 @@ void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) {
|
void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) {
|
||||||
wasm_val_vec_t args_vec;
|
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
|
||||||
wasm_val_vec_new(&args_vec, i, args);
|
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||||
if (wasm_func_call(func, &args_vec, NULL)) {
|
if (wasm_func_call(func, &args_, &results)) {
|
||||||
printf("> Error on result, expected empty\n");
|
printf("> Error on result, expected empty\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -74,10 +71,10 @@ void check_ok2(wasm_func_t* func, int32_t arg1, int32_t arg2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_trap(wasm_func_t* func, int i, wasm_val_t args[]) {
|
void check_trap(wasm_func_t* func, int i, wasm_val_t args[]) {
|
||||||
wasm_val_vec_t args_vec, results_vec;
|
wasm_val_t r[] = {WASM_INIT_VAL};
|
||||||
wasm_val_vec_new(&args_vec, i, args);
|
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
|
||||||
wasm_val_vec_new(&results_vec, 1, (wasm_val_t []){ WASM_INIT_VAL });
|
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
|
||||||
own wasm_trap_t* trap = wasm_func_call(func, &args_vec, &results_vec);
|
own wasm_trap_t* trap = wasm_func_call(func, &args_, &results);
|
||||||
if (! trap) {
|
if (! trap) {
|
||||||
printf("> Error on result, expected trap\n");
|
printf("> Error on result, expected trap\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -137,8 +134,9 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
own wasm_instance_t* instance =
|
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
|
||||||
wasm_instance_new_with_args(store, module, NULL, NULL, KILOBYTE(8), 0);
|
own wasm_instance_t *instance = wasm_instance_new_with_args(
|
||||||
|
store, module, &imports, NULL, KILOBYTE(32), 0);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
printf("> Error instantiating module!\n");
|
printf("> Error instantiating module!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -156,15 +154,6 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
wasm_module_delete(module);
|
wasm_module_delete(module);
|
||||||
|
|
||||||
if (!memory || !wasm_memory_data(memory)) {
|
|
||||||
printf("> Error getting memory!\n");
|
|
||||||
wasm_extern_vec_delete(&exports);
|
|
||||||
wasm_instance_delete(instance);
|
|
||||||
wasm_store_delete(store);
|
|
||||||
wasm_engine_delete(engine);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try cloning.
|
// Try cloning.
|
||||||
own wasm_memory_t* copy = wasm_memory_copy(memory);
|
own wasm_memory_t* copy = wasm_memory_copy(memory);
|
||||||
assert(wasm_memory_same(memory, copy));
|
assert(wasm_memory_same(memory, copy));
|
||||||
|
@ -172,13 +161,13 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Check initial memory.
|
// Check initial memory.
|
||||||
printf("Checking memory...\n");
|
printf("Checking memory...\n");
|
||||||
check(wasm_memory_size(memory) >= 2);
|
check(wasm_memory_size(memory) == 2);
|
||||||
check(wasm_memory_data_size(memory) >= 0x20000);
|
check(wasm_memory_data_size(memory) == 0x20000);
|
||||||
check(wasm_memory_data(memory)[0] == 0);
|
check(wasm_memory_data(memory)[0] == 0);
|
||||||
check(wasm_memory_data(memory)[0x1000] == 1);
|
check(wasm_memory_data(memory)[0x1000] == 1);
|
||||||
check(wasm_memory_data(memory)[0x1003] == 4);
|
check(wasm_memory_data(memory)[0x1003] == 4);
|
||||||
|
|
||||||
(void)size_func;
|
check_call0(size_func, 2);
|
||||||
check_call1(load_func, 0, 0);
|
check_call1(load_func, 0, 0);
|
||||||
check_call1(load_func, 0x1000, 1);
|
check_call1(load_func, 0x1000, 1);
|
||||||
check_call1(load_func, 0x1003, 4);
|
check_call1(load_func, 0x1003, 4);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
// A function to be called from Wasm code.
|
// A function to be called from Wasm code.
|
||||||
own wasm_trap_t* callback(
|
own wasm_trap_t* callback(
|
||||||
const wasm_val_vec_t *args, wasm_val_vec_t *results
|
const wasm_val_vec_t* args, wasm_val_vec_t* results
|
||||||
) {
|
) {
|
||||||
printf("Calling back...\n> ");
|
printf("Calling back...\n> ");
|
||||||
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
|
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
|
||||||
|
@ -27,14 +27,14 @@ own wasm_trap_t* callback(
|
||||||
|
|
||||||
// A function closure.
|
// A function closure.
|
||||||
own wasm_trap_t* closure_callback(
|
own wasm_trap_t* closure_callback(
|
||||||
void* env, const wasm_val_t args[], wasm_val_t results[]
|
void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
|
||||||
) {
|
) {
|
||||||
int i = *(int*)env;
|
int i = *(int*)env;
|
||||||
printf("Calling back closure...\n");
|
printf("Calling back closure...\n");
|
||||||
printf("> %d\n", i);
|
printf("> %d\n", i);
|
||||||
|
|
||||||
results[0].kind = WASM_I32;
|
results->data[0].kind = WASM_I32;
|
||||||
results[0].of.i32 = (int32_t)i;
|
results->data[0].of.i32 = (int32_t)i;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,11 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Load binary.
|
// Load binary.
|
||||||
printf("Loading binary...\n");
|
printf("Loading binary...\n");
|
||||||
|
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
|
||||||
|
FILE* file = fopen("multi.aot", "rb");
|
||||||
|
#else
|
||||||
FILE* file = fopen("multi.wasm", "rb");
|
FILE* file = fopen("multi.wasm", "rb");
|
||||||
|
#endif
|
||||||
if (!file) {
|
if (!file) {
|
||||||
printf("> Error loading module!\n");
|
printf("> Error loading module!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -91,8 +95,8 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
wasm_extern_vec_t imports;
|
wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) };
|
||||||
wasm_extern_vec_new(&imports, 1, (wasm_extern_t *[]) { wasm_func_as_extern(callback_func) });
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
@ -121,13 +125,14 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Call.
|
// Call.
|
||||||
printf("Calling export...\n");
|
printf("Calling export...\n");
|
||||||
wasm_val_vec_t args, results;
|
wasm_val_t vals[4] = {
|
||||||
wasm_val_vec_new(&args, 4, (wasm_val_t []){
|
WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4)
|
||||||
WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4)
|
};
|
||||||
});
|
wasm_val_t res[4] = {
|
||||||
wasm_val_vec_new(&results, 4, (wasm_val_t []) {
|
WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
|
||||||
WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
|
};
|
||||||
});
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vals);
|
||||||
|
wasm_val_vec_t results = WASM_ARRAY_VEC(res);
|
||||||
if (wasm_func_call(run_func, &args, &results)) {
|
if (wasm_func_call(run_func, &args, &results)) {
|
||||||
printf("> Error calling function!\n");
|
printf("> Error calling function!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -138,12 +143,12 @@ int main(int argc, const char* argv[]) {
|
||||||
// Print result.
|
// Print result.
|
||||||
printf("Printing result...\n");
|
printf("Printing result...\n");
|
||||||
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
|
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
|
||||||
results.data[0].of.i32, results.data[1].of.i64, results.data[2].of.i64, results.data[3].of.i32);
|
res[0].of.i32, res[1].of.i64, res[2].of.i64, res[3].of.i32);
|
||||||
|
|
||||||
assert(results.data[0].of.i32 == 1);
|
assert(res[0].of.i32 == 4);
|
||||||
assert(results.data[1].of.i64 == 2);
|
assert(res[1].of.i64 == 3);
|
||||||
assert(results.data[2].of.i64 == 3);
|
assert(res[2].of.i64 == 2);
|
||||||
assert(results.data[3].of.i32 == 4);
|
assert(res[3].of.i32 == 1);
|
||||||
|
|
||||||
// Shut down.
|
// Shut down.
|
||||||
printf("Shutting down...\n");
|
printf("Shutting down...\n");
|
||||||
|
|
|
@ -32,12 +32,6 @@ void print_valtype(const wasm_valtype_t* type) {
|
||||||
|
|
||||||
void print_valtypes(const wasm_valtype_vec_t* types) {
|
void print_valtypes(const wasm_valtype_vec_t* types) {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
if (!types) {
|
|
||||||
printf("> Error print a NULL valtype\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < types->size; ++i) {
|
for (size_t i = 0; i < types->size; ++i) {
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
|
@ -49,11 +43,6 @@ void print_valtypes(const wasm_valtype_vec_t* types) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_externtype(const wasm_externtype_t* type) {
|
void print_externtype(const wasm_externtype_t* type) {
|
||||||
if (!type) {
|
|
||||||
printf("> Error print a NULL externtype\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (wasm_externtype_kind(type)) {
|
switch (wasm_externtype_kind(type)) {
|
||||||
case WASM_EXTERN_FUNC: {
|
case WASM_EXTERN_FUNC: {
|
||||||
const wasm_functype_t* functype =
|
const wasm_functype_t* functype =
|
||||||
|
@ -89,11 +78,6 @@ void print_externtype(const wasm_externtype_t* type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_name(const wasm_name_t* name) {
|
void print_name(const wasm_name_t* name) {
|
||||||
if (!name) {
|
|
||||||
printf("> Error print a NULL name\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\"%.*s\"", (int)name->size, name->data);
|
printf("\"%.*s\"", (int)name->size, name->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +123,9 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
|
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, NULL, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
printf("> Error instantiating module!\n");
|
printf("> Error instantiating module!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -49,19 +49,21 @@ void check_table(wasm_table_t* table, int32_t i, bool expect_set) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) {
|
void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) {
|
||||||
wasm_val_vec_t args, results;
|
wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
|
||||||
wasm_val_vec_new(&args, 2, (wasm_val_t []){ WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) });
|
wasm_val_t r[1] = { WASM_INIT_VAL };
|
||||||
wasm_val_vec_new(&results, 1, (wasm_val_t []){ WASM_INIT_VAL });
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
|
||||||
if (wasm_func_call(func, &args, &results) || results.data[0].of.i32 != expected) {
|
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
|
||||||
|
if (wasm_func_call(func, &args, &results) || r[0].of.i32 != expected) {
|
||||||
printf("> Error on result\n");
|
printf("> Error on result\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) {
|
void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) {
|
||||||
wasm_val_vec_t args, results;
|
wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
|
||||||
wasm_val_vec_new(&args, 2, (wasm_val_t []){ WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) });
|
wasm_val_t r[1] = { WASM_INIT_VAL };
|
||||||
wasm_val_vec_new(&results, 1, (wasm_val_t []){ WASM_INIT_VAL });
|
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
|
||||||
|
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
|
||||||
own wasm_trap_t* trap = wasm_func_call(func, &args, &results);
|
own wasm_trap_t* trap = wasm_func_call(func, &args, &results);
|
||||||
if (! trap) {
|
if (! trap) {
|
||||||
printf("> Error on result, expected trap\n");
|
printf("> Error on result, expected trap\n");
|
||||||
|
@ -112,8 +114,9 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
own wasm_instance_t *instance =
|
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
|
||||||
wasm_instance_new(store, module, NULL, NULL);
|
own wasm_instance_t* instance =
|
||||||
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
printf("> Error instantiating module!\n");
|
printf("> Error instantiating module!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -134,6 +137,7 @@ int main(int argc, const char* argv[]) {
|
||||||
// Create external function.
|
// Create external function.
|
||||||
printf("Creating callback...\n");
|
printf("Creating callback...\n");
|
||||||
own wasm_functype_t* neg_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32());
|
own wasm_functype_t* neg_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32());
|
||||||
|
own wasm_func_t* h = wasm_func_new(store, neg_type, neg_callback);
|
||||||
|
|
||||||
wasm_functype_delete(neg_type);
|
wasm_functype_delete(neg_type);
|
||||||
|
|
||||||
|
@ -155,7 +159,9 @@ int main(int argc, const char* argv[]) {
|
||||||
printf("Mutating table...\n");
|
printf("Mutating table...\n");
|
||||||
check(wasm_table_set(table, 0, wasm_func_as_ref(g)));
|
check(wasm_table_set(table, 0, wasm_func_as_ref(g)));
|
||||||
check(wasm_table_set(table, 1, NULL));
|
check(wasm_table_set(table, 1, NULL));
|
||||||
check(! wasm_table_set(table, 2, wasm_func_as_ref(f)));
|
wasm_ref_t *ref_f = wasm_func_as_ref(f);
|
||||||
|
check(! wasm_table_set(table, 2, ref_f));
|
||||||
|
wasm_ref_delete(ref_f);
|
||||||
check_table(table, 0, true);
|
check_table(table, 0, true);
|
||||||
check_table(table, 1, false);
|
check_table(table, 1, false);
|
||||||
check_call(call_indirect, 7, 0, 666);
|
check_call(call_indirect, 7, 0, 666);
|
||||||
|
@ -165,6 +171,8 @@ int main(int argc, const char* argv[]) {
|
||||||
// Grow table.
|
// Grow table.
|
||||||
// DO NOT SUPPORT
|
// DO NOT SUPPORT
|
||||||
printf("Bypass Growing table...\n");
|
printf("Bypass Growing table...\n");
|
||||||
|
|
||||||
|
wasm_func_delete(h);
|
||||||
wasm_extern_vec_delete(&exports);
|
wasm_extern_vec_delete(&exports);
|
||||||
wasm_instance_delete(instance);
|
wasm_instance_delete(instance);
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,8 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
wasm_extern_vec_t imports;
|
wasm_extern_t* externs[] = { wasm_func_as_extern(fail_func) };
|
||||||
wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(fail_func) });
|
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||||
own wasm_instance_t* instance =
|
own wasm_instance_t* instance =
|
||||||
wasm_instance_new(store, module, &imports, NULL);
|
wasm_instance_new(store, module, &imports, NULL);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
@ -112,10 +112,9 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Calling export %d...\n", i);
|
printf("Calling export %d...\n", i);
|
||||||
|
wasm_val_vec_t args = WASM_EMPTY_VEC;
|
||||||
wasm_val_vec_t results;
|
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||||
wasm_val_vec_new_uninitialized(&results, 1);
|
own wasm_trap_t* trap = wasm_func_call(func, &args, &results);
|
||||||
own wasm_trap_t* trap = wasm_func_call(func, NULL, &results);
|
|
||||||
if (!trap) {
|
if (!trap) {
|
||||||
printf("> Error calling function, expected trap!\n");
|
printf("> Error calling function, expected trap!\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user