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:
Wenyong Huang 2022-01-19 11:25:08 +08:00 committed by GitHub
parent 2c743dbd51
commit 260d36a62d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1148 additions and 595 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -1235,10 +1235,9 @@ 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
wasm_val_copy(wasm_val_t *out, const wasm_val_t *src) wasm_val_copy(wasm_val_t *out, const wasm_val_t *src)
@ -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
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); 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 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; 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;
} }

View File

@ -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;
}; };

View File

@ -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

View File

@ -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')

View File

@ -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 */
static bool
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function, WASMFunctionInstanceCommon *function,
uint32 *argv) 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;
} }
cell_num += wasm_value_type_cell_num(result_type); #if UINTPTR_MAX == UINT32_MAX
i++; 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;
}
} }
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, &param_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:
{
uint32 externref_idx = *argv_src++;
if (is_aot_func) {
if (n_ints < MAX_REG_INTS) if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++; ints[n_ints++] = externref_idx;
else else
stacks[n_stacks++] = *argv_src++; 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,15 +4559,10 @@ 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) {
param->of.ref = NULL;
}
else {
if (!wasm_externref_ref2obj(*argv, if (!wasm_externref_ref2obj(*argv,
(void **)&param->of.ref)) { (void **)&param->of.foreign)) {
return false; return false;
} }
}
argv++; argv++;
break; break;
@ -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,30 +4618,34 @@ 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,
module_inst, NULL, 0))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed"); wasm_runtime_set_exception(module_inst, "allocate memory failed");
return false; return false;
} }
}
if (!argv_to_params(params, argv, func_type)) { if (!argv_to_params(params, argv, func_type)) {
wasm_runtime_set_exception(module_inst, "unsupported param type"); wasm_runtime_set_exception(module_inst, "unsupported param type");
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,
module_inst, NULL, 0))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed"); wasm_runtime_set_exception(module_inst, "allocate memory failed");
goto fail; goto fail;
} }
}
params_vec.data = params; params_vec.data = params;
params_vec.num_elems = func_type->param_count; params_vec.num_elems = func_type->param_count;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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)
{ {

View File

@ -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,8 +1762,13 @@ 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,
if (module_inst->exec_env_singleton) {
return true;
}
exec_env = wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size); 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;

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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)
{
FILE *file;
char buf[16];
printf("## retrieve file handle from externref index\n"); int32
if (!wasm_externref_ref2obj(externref_idx_of_file, (void **)&file)) { local_cmp_externref(wasm_exec_env_t exec_env, uintptr_t externref_a,
printf("failed to get host object from externref index!\n"); uintptr_t externref_b)
return -1; {
return externref_a == externref_b;
} }
snprintf(buf, sizeof(buf), "%%%ds", len); int32
local_chk_externref(wasm_exec_env_t exec_env, int32 index, uintptr_t externref)
printf("## write string to file: "); {
printf(buf, str); return externref == global_objects[index];
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 */
if (exec_env) {
wasm_runtime_destroy_exec_env(exec_env); wasm_runtime_destroy_exec_env(exec_env);
}
fail4:
/* destroy the module instance */ /* destroy the module instance */
if (wasm_module_inst) {
wasm_runtime_deinstantiate(wasm_module_inst); wasm_runtime_deinstantiate(wasm_module_inst);
}
fail3:
/* unload the module */ /* unload the module */
if (wasm_module) {
wasm_runtime_unload(wasm_module); wasm_runtime_unload(wasm_module);
}
fail2:
/* free the file buffer */ /* free the file buffer */
if (wasm_file_buf) {
wasm_runtime_free(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;

View File

@ -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)
)
) )
) )

View File

@ -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");

View File

@ -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) {

View File

@ -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);

View File

@ -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;
} }

View File

@ -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
&& !(actual && expected && wasm_ref_same(actual, expected))) {
printf("> Error reading reference, expected %p, got %p\n", printf("> Error reading reference, expected %p, got %p\n",
expected ? wasm_ref_get_host_info(expected) : NULL, expected ? wasm_ref_get_host_info(expected) : NULL,
actual ? wasm_ref_get_host_info(actual) : NULL); actual ? wasm_ref_get_host_info(actual) : NULL);
exit(1); exit(1);
} }
if (release_ref && actual) // if (actual) wasm_ref_delete(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);

View File

@ -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);

View File

@ -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_vec_new(&results, 4, (wasm_val_t []) { wasm_val_t res[4] = {
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");

View File

@ -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;

View File

@ -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");
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;
@ -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);

View File

@ -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;