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 */
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_max_size);
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) {
case VALUE_TYPE_I32:
case VALUE_TYPE_F32:
#if WASM_ENABLE_REF_TYPES
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#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);
#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 */
if (!existing_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;
WASMType *func_type = NULL;
WASMExecEnv *exec_env = NULL;
uint32 argc1 = 0, argv1[2] = { 0 };
uint32 total_argv_size = 0;
uint64 total_size;
@ -91,14 +92,20 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
uint32 *argv_offsets, module_type;
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
/* In wasi mode, we should call the function named "_start"
which initializes the wasi envrionment and then calls
the actual main function. Directly calling main function
may cause exception thrown. */
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, 0,
NULL);
return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
}
#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);
}
ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1,
argv1);
ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1);
if (ret && func_type->result_count > 0 && argc > 0 && argv)
/* copy the return value */
*(int *)argv = (int)argv1[0];
@ -345,7 +351,11 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
WASMFunctionInstanceCommon *target_func;
WASMModuleInstanceCommon *target_inst;
WASMType *type = NULL;
WASMExecEnv *exec_env = NULL;
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;
uint64 total_size;
const char *exception;
@ -373,8 +383,23 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
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;
cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
#endif
total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
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
case VALUE_TYPE_FUNCREF:
{
if (strncmp(argv[i], "null", 4) == 0
|| strncmp(argv[i], "NULL", 4) == 0) {
argv1[p++] = NULL_REF;
if (strncasecmp(argv[i], "null", 4) == 0) {
argv1[p++] = (uint32)-1;
}
else {
argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
@ -498,23 +522,27 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
}
case VALUE_TYPE_EXTERNREF:
{
if (strncmp(argv[i], "null", 4) == 0
|| strncmp(argv[i], "NULL", 4) == 0) {
argv1[p++] = NULL_REF;
#if UINTPTR_MAX == UINT32_MAX
if (strncasecmp(argv[i], "null", 4) == 0) {
argv1[p++] = (uint32)-1;
}
else {
uint64 val = strtoull(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;
argv1[p++] = strtoul(argv[i], &endptr, 0);
}
#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;
}
#endif /* WASM_ENABLE_REF_TYPES */
@ -529,11 +557,20 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
goto fail;
}
}
bh_assert(p == (int32)argc1);
wasm_runtime_set_exception(module_inst, NULL);
if (!wasm_runtime_create_exec_env_and_call_wasm(target_inst, target_func,
argc1, argv1)) {
#if WASM_ENABLE_REF_TYPES == 0
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;
}
@ -576,7 +613,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
os_printf("%.7g:f64", u.val);
break;
}
#if WASM_ENABLE_REF_TYPES
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
if (argv1[k] != NULL_REF)
@ -588,16 +625,25 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
}
case VALUE_TYPE_EXTERNREF:
{
if (argv1[k] != NULL_REF) {
void *extern_obj = NULL;
bool ret = wasm_externref_ref2obj(argv1[k], &extern_obj);
bh_assert(ret);
(void)ret;
os_printf("%p:ref.extern", extern_obj);
}
#if UINTPTR_MAX == UINT32_MAX
if (argv1[k] != 0 && argv1[k] != (uint32)-1)
os_printf("%p:ref.extern", (void *)argv1[k]);
else
os_printf("extern:ref.null");
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;
}
#endif

View File

@ -1235,9 +1235,8 @@ wasm_exporttype_type(const wasm_exporttype_t *export_type)
void
wasm_val_delete(wasm_val_t *v)
{
if (v) {
if (v)
wasm_runtime_free(v);
}
}
void
@ -1562,19 +1561,13 @@ wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
#if WASM_ENABLE_INTERP != 0
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
if (!(error_info =
wasm_get_exception((WASMModuleInstance *)inst_comm_rt))) {
return NULL;
}
error_info = wasm_get_exception((WASMModuleInstance *)inst_comm_rt);
}
#endif
#if WASM_ENABLE_AOT != 0
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
if (!(error_info =
aot_get_exception((AOTModuleInstance *)inst_comm_rt))) {
return NULL;
}
error_info = aot_get_exception((AOTModuleInstance *)inst_comm_rt);
}
#endif
@ -2160,7 +2153,7 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
- import_memory_count);
module_name_rt = import->module_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;
max_size = import->table_max_size;
}
@ -2563,151 +2556,127 @@ wasm_func_type(const wasm_func_t *func)
return wasm_functype_copy(func->type);
}
static uint32
params_to_argv(WASMModuleInstanceCommon *inst_comm_rt, const wasm_val_t *params,
const wasm_valtype_vec_t *param_defs, size_t param_arity,
uint32 *out)
static bool
params_to_argv(const wasm_val_vec_t *params,
const wasm_valtype_vec_t *param_defs, uint32 *argv,
uint32 *ptr_argc)
{
size_t i = 0;
uint32 argc = 0;
const wasm_val_t *param = NULL;
if (!param_arity) {
return 0;
if (!param_defs->num_elems) {
return true;
}
bh_assert(params && param_defs && out);
bh_assert(param_defs->num_elems == param_arity);
if (!params || !params->num_elems || !params->size || !params->data) {
return false;
}
for (i = 0; out && i < param_arity; ++i) {
param = params + i;
*ptr_argc = 0;
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);
switch (param->kind) {
case WASM_I32:
*(int32 *)out = param->of.i32;
out += 1;
argc += 1;
*(int32 *)argv = param->of.i32;
argv += 1;
*ptr_argc += 1;
break;
case WASM_I64:
*(int64 *)out = param->of.i64;
out += 2;
argc += 2;
*(int64 *)argv = param->of.i64;
argv += 2;
*ptr_argc += 2;
break;
case WASM_F32:
*(float32 *)out = param->of.f32;
out += 1;
argc += 1;
*(float32 *)argv = param->of.f32;
argv += 1;
*ptr_argc += 1;
break;
case WASM_F64:
*(float64 *)out = param->of.f64;
out += 2;
argc += 2;
*(float64 *)argv = param->of.f64;
argv += 2;
*ptr_argc += 2;
break;
#if WASM_ENABLE_REF_TYPES != 0
case WASM_ANYREF:
if (!wasm_externref_obj2ref(inst_comm_rt, param->of.ref, out)) {
goto failed;
}
out += 1;
argc += 1;
*(uintptr_t *)argv = (uintptr_t)param->of.ref;
argv += sizeof(uintptr_t) / sizeof(uint32);
*ptr_argc += 1;
break;
#endif
default:
LOG_WARNING("unexpected parameter val type %d", param->kind);
goto failed;
return false;
}
}
return argc;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return 0;
return true;
}
static uint32
argv_to_results(const uint32 *results, const wasm_valtype_vec_t *result_defs,
size_t result_arity, wasm_val_t *out)
static bool
argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
wasm_val_vec_t *results)
{
size_t i = 0;
uint32 argc = 0;
const uint32 *result = results;
const wasm_valtype_t *def = NULL;
size_t i = 0, argv_i = 0;
wasm_val_t *result;
if (!result_arity) {
return 0;
if (!result_defs->num_elems) {
return true;
}
bh_assert(results && result_defs && out);
bh_assert(result_arity == result_defs->num_elems);
if (!results || !results->num_elems || !results->size || !results->data) {
return false;
}
for (i = 0; out && i < result_arity; i++) {
def = *(result_defs->data + i);
switch (def->kind) {
for (i = 0, result = results->data, argv_i = 0; i < result_defs->num_elems;
i++, result++) {
switch (result_defs->data[i]->kind) {
case WASM_I32:
{
out->kind = WASM_I32;
out->of.i32 = *(int32 *)result;
result += 1;
result->kind = WASM_I32;
result->of.i32 = *(int32 *)(argv + argv_i);
argv_i += 1;
break;
}
case WASM_I64:
{
out->kind = WASM_I64;
out->of.i64 = *(int64 *)result;
result += 2;
result->kind = WASM_I64;
result->of.i64 = *(int64 *)(argv + argv_i);
argv_i += 2;
break;
}
case WASM_F32:
{
out->kind = WASM_F32;
out->of.f32 = *(float32 *)result;
result += 1;
result->kind = WASM_F32;
result->of.f32 = *(float32 *)(argv + argv_i);
argv_i += 1;
break;
}
case WASM_F64:
{
out->kind = WASM_F64;
out->of.f64 = *(float64 *)result;
result += 2;
result->kind = WASM_F64;
result->of.f64 = *(float64 *)(argv + argv_i);
argv_i += 2;
break;
}
#if WASM_ENABLE_REF_TYPES != 0
case WASM_ANYREF:
{
out->kind = WASM_ANYREF;
if (NULL_REF == *(uint32 *)result) {
out->of.ref = NULL;
}
else {
if (!wasm_externref_ref2obj(*(uint32 *)result,
(void **)&out->of.ref)) {
goto failed;
}
}
result += 1;
result->kind = WASM_ANYREF;
result->of.ref =
(struct wasm_ref_t *)(*(uintptr_t *)(argv + argv_i));
argv_i += sizeof(uintptr_t) / sizeof(uint32);
break;
}
#endif
default:
LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
def->kind);
goto failed;
result_defs->data[i]->kind);
return false;
}
out++;
argc++;
}
return argc;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return 0;
return true;
}
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 */
uint32 argc = 0;
/* 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;
WASMExecEnv *exec_env = NULL;
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 */
if (param_count
&& (!params
|| !(argc = params_to_argv(func->inst_comm_rt, params->data,
wasm_functype_params(func->type),
param_count, argv)))) {
&& !params_to_argv(params, wasm_functype_params(func->type), argv,
&argc)) {
goto failed;
}
@ -2798,9 +2765,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
/* copy results */
if (result_count) {
if (!results
|| !(argc = argv_to_results(argv, wasm_functype_results(func->type),
result_count, results->data))) {
if (!argv_to_results(argv, wasm_functype_results(func->type),
results)) {
goto failed;
}
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) {
AOTImportTable *table_aot =
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;
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 =
module_aot->tables
+ (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;
max_size = table_aot->table_max_size;
}
@ -3360,13 +3326,12 @@ wasm_table_type(const wasm_table_t *table)
own wasm_ref_t *
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) {
return NULL;
}
/* index -> func_idx_rt */
#if WASM_ENABLE_INTERP != 0
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
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) {
return NULL;
}
func_idx_rt = ((uint32 *)table_interp->base_addr)[index];
ref_idx = ((uint32 *)table_interp->base_addr)[index];
}
#endif
@ -3387,7 +3352,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
if (index >= table_aot->cur_size) {
return NULL;
}
func_idx_rt = table_aot->data[index];
ref_idx = table_aot->data[index];
}
#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
* also leads to below branch
*/
if (func_idx_rt == NULL_REF) {
if (ref_idx == NULL_REF) {
return NULL;
}
return wasm_ref_new_internal(table->store, WASM_REF_func, func_idx_rt,
table->inst_comm_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);
}
}
bool
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 function_count = 0, ref_idx_rt = NULL_REF;
uint32 *p_ref_idx = NULL;
uint32 function_count = 0;
if (!table) {
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;
}
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 (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
WASMTableInstance *table_interp =
@ -3434,7 +3412,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
return false;
}
p_func_idx_rt = ((uint32 *)table_interp->base_addr) + index;
p_ref_idx = ((uint32 *)table_interp->base_addr) + index;
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;
}
p_func_idx_rt = table_aot->data + index;
p_ref_idx = table_aot->data + index;
function_count = module_aot->func_count;
}
#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
* leads to below branch
*/
if (!p_func_idx_rt) {
if (!p_ref_idx) {
return false;
}
if (NULL_REF != ref_idx_rt) {
if (ref_idx_rt >= function_count) {
return false;
#if WASM_ENABLE_REF_TYPES != 0
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;
}
}
*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;
}

View File

@ -56,7 +56,6 @@ struct wasm_globaltype_t {
struct wasm_tabletype_t {
uint32 extern_kind;
/* always be WASM_FUNCREF */
wasm_valtype_t *val_type;
wasm_limits_t limits;
};

View File

@ -125,10 +125,6 @@ typedef struct WASMExecEnv {
WASMJmpBuf *jmpbuf_stack_top;
#endif
#if WASM_ENABLE_REF_TYPES != 0
uint16 nested_calling_depth;
#endif
#if WASM_ENABLE_MEMORY_PROFILING != 0
uint32 max_wasm_stack_used;
#endif

View File

@ -53,11 +53,30 @@ get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
uint32
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
check_symbol_signature(const WASMType *type, const char *signature)
{
const char *p = signature, *p_end;
char sig_map[] = { 'F', 'f', 'I', 'i' }, sig;
char sig;
uint32 i = 0;
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++) {
sig = *p++;
if ((type->types[i] >= VALUE_TYPE_F64
&& type->types[i] <= VALUE_TYPE_I32
&& sig == sig_map[type->types[i] - VALUE_TYPE_F64])
#if WASM_ENABLE_REF_TYPES != 0
|| (sig == 'i' && type->types[i] == VALUE_TYPE_EXTERNREF)
#endif
)
/* normal parameter */
/* a f64/f32/i64/i32/externref parameter */
if (compare_type_with_signautre(type->types[i], sig))
continue;
/* a pointer/string paramter */
if (type->types[i] != VALUE_TYPE_I32)
/* pointer and string must be i32 type */
return false;
@ -112,8 +127,12 @@ check_symbol_signature(const WASMType *type, const char *signature)
if (type->result_count) {
if (p >= p_end)
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;
p++;
}
if (*p != '\0')

View File

@ -1199,46 +1199,163 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
}
#if WASM_ENABLE_REF_TYPES != 0
static void
wasm_runtime_reclaim_externref(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
uint32 *argv)
/* (uintptr_t)externref -> (uint32_t)index */
/* argv -> *ret_argv */
static bool
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
uint32 *argv, uint32 argc, uint32 **ret_argv,
uint32 *ret_argc_param,
uint32 *ret_argc_result)
{
uint32 i = 0, cell_num = 0;
uint32 *new_argv = NULL, argv_i = 0, new_argv_i = 0, param_i = 0,
result_i = 0;
bool need_param_transform = false, need_result_transform = false;
uint64 size = 0;
WASMType *func_type = wasm_runtime_get_function_type(
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);
while (i < func_type->result_count) {
uint8 result_type = func_type->types[func_type->param_count + i];
if (result_type == VALUE_TYPE_EXTERNREF && argv[i] != NULL_REF) {
/* Retain the externref returned to runtime embedder */
(void)wasm_externref_retain(argv[i]);
for (result_i = 0; result_i < func_type->result_count && argv_i < argc;
result_i++) {
uint8 result_type = func_type->types[func_type->param_count + result_i];
if (result_type == VALUE_TYPE_EXTERNREF) {
void *externref_obj;
#if UINTPTR_MAX != UINT32_MAX
union {
uintptr_t val;
uint32 parts[2];
} u;
#endif
if (!wasm_externref_ref2obj(argv[argv_i], &externref_obj)) {
wasm_runtime_free(argv);
return false;
}
#if UINTPTR_MAX == UINT32_MAX
ret_argv[ret_argv_i] = (uintptr_t)externref_obj;
#else
u.val = (uintptr_t)externref_obj;
ret_argv[ret_argv_i] = u.parts[0];
ret_argv[ret_argv_i + 1] = u.parts[1];
#endif
argv_i += 1;
ret_argv_i += sizeof(uintptr_t) / sizeof(uint32);
}
else {
uint16 result_cell_num = wasm_value_type_cell_num(result_type);
uint32 result_size = sizeof(uint32) * result_cell_num;
bh_memcpy_s(ret_argv + ret_argv_i, result_size, argv + argv_i,
result_size);
argv_i += result_cell_num;
ret_argv_i += result_cell_num;
}
cell_num += wasm_value_type_cell_num(result_type);
i++;
}
wasm_externref_reclaim(exec_env->module_inst);
}
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);
}
wasm_runtime_free(argv);
return true;
}
#endif
@ -1248,6 +1365,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
uint32 argv[])
{
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)) {
LOG_ERROR("Invalid exec env stack info.");
@ -1255,34 +1376,53 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
}
#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
#if WASM_ENABLE_INTERP != 0
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
ret = wasm_call_function(exec_env, (WASMFunctionInstance *)function,
argc, argv);
param_argc, new_argv);
#endif
#if WASM_ENABLE_AOT != 0
if (exec_env->module_inst->module_type == Wasm_Module_AoT)
ret = aot_call_function(exec_env, (AOTFunctionInstance *)function, argc,
argv);
ret = aot_call_function(exec_env, (AOTFunctionInstance *)function,
param_argc, new_argv);
#endif
if (!ret) {
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
}
#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
return ret;
}
static uint32
parse_args_to_uint32_array(WASMType *type, uint32 num_args, wasm_val_t *args,
uint32 *out_argv)
static void
parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
{
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) {
case WASM_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];
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:
bh_assert(0);
break;
}
}
return p;
}
static uint32
parse_uint32_array_to_results(WASMType *type, uint32 argc, uint32 *argv,
static void
parse_uint32_array_to_results(WASMType *type, uint32 *argv,
wasm_val_t *out_results)
{
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;
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:
bh_assert(0);
break;
}
}
bh_assert(argc == p);
return type->result_count;
}
bool
@ -1389,7 +1574,10 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
uint32 num_results, wasm_val_t results[],
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;
bool ret = false;
@ -1402,8 +1590,23 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
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;
cell_num = (argc > type->ret_cell_num) ? argc : type->ret_cell_num;
#endif
if (num_results != type->result_count) {
LOG_ERROR(
@ -1425,14 +1628,11 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
goto fail1;
}
argc = parse_args_to_uint32_array(type, num_args, args, argv);
if (!(ret = wasm_runtime_call_wasm(exec_env, function, argc, argv)))
parse_args_to_uint32_array(type, args, argv);
if (!(ret = wasm_runtime_call_wasm(exec_env, function, num_args, argv)))
goto fail2;
ret_num =
parse_uint32_array_to_results(type, type->ret_cell_num, argv, results);
bh_assert(ret_num == num_results);
(void)ret_num;
parse_uint32_array_to_results(type, argv, results);
fail2:
wasm_runtime_free(argv);
@ -1492,6 +1692,20 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
args[i].kind = WASM_F64;
args[i].of.f64 = va_arg(vargs, float64);
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:
bh_assert(0);
break;
@ -1547,13 +1761,21 @@ WASMExecEnv *
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
{
#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;
}
#endif
#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)
->exec_env_singleton.ptr;
}
#endif
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++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
*(uint32 *)argv_dst = arg_i32 = *argv_src++;
if (signature) {
@ -2540,10 +2765,19 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
*(float32 *)argv_dst = *(float32 *)argv_src++;
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
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;
}
#endif
default:
bh_assert(0);
@ -2560,7 +2794,6 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] = *(uint32 *)argv1;
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,
sizeof(uint64));
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:
bh_assert(0);
break;
@ -2634,6 +2884,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
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)
uint32 *fps;
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++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
arg_i32 = *argv_src++;
@ -2829,17 +3085,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
stacks[n_stacks++] = arg_i32;
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:
{
if (n_ints < MAX_REG_INTS - 1) {
@ -2959,6 +3204,31 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
#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:
bh_assert(0);
break;
@ -2982,7 +3252,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] =
(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(
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
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:
bh_assert(0);
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;
uint64 size;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#if defined(BUILD_TARGET_X86_32)
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++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
arg_i32 = *argv++;
@ -3129,12 +3428,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
argv1[j++] = *argv++;
break;
case VALUE_TYPE_F32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv1[j++] = *argv++;
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:
bh_assert(0);
break;
@ -3154,7 +3467,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] =
(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,
invokeNative_Float64(func_ptr, argv1, argc1));
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:
bh_assert(0);
break;
@ -3281,12 +3613,16 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 *argv_ret)
{
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 arg_i32, ptr_len;
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#ifndef BUILD_TARGET_RISCV64_LP64
#if WASM_ENABLE_SIMD == 0
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++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
arg_i32 = *argv_src++;
arg_i64 = arg_i32;
@ -3397,13 +3736,28 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
argv_src += 2;
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++;
{
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
#if WASM_ENABLE_SIMD != 0
case VALUE_TYPE_V128:
@ -3442,7 +3796,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] =
(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(
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
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
case VALUE_TYPE_V128:
*(v128 *)argv_ret =
@ -3709,10 +4082,24 @@ bool
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
uint32 *p_externref_idx)
{
LookupExtObj_UserData lookup_user_data;
LookupExtObj_UserData lookup_user_data = { 0 };
ExternRefMapNode *node;
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.module_inst = module_inst;
lookup_user_data.found = false;
@ -3764,8 +4151,10 @@ wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj)
{
ExternRefMapNode *node;
/* catch a `ref.null` vairable */
if (externref_idx == NULL_REF) {
return false;
*p_extern_obj = NULL;
return true;
}
os_mutex_lock(&externref_lock);
@ -4170,14 +4559,9 @@ argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
case VALUE_TYPE_EXTERNREF:
param->kind = WASM_ANYREF;
if (NULL_REF == *argv) {
param->of.ref = NULL;
}
else {
if (!wasm_externref_ref2obj(*argv,
(void **)&param->of.ref)) {
return false;
}
if (!wasm_externref_ref2obj(*argv,
(void **)&param->of.foreign)) {
return false;
}
argv++;
@ -4213,8 +4597,8 @@ results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
if (!wasm_externref_obj2ref(module_inst, result->of.ref,
argv)) {
if (!wasm_externref_obj2ref(module_inst,
(void *)result->of.foreign, argv)) {
return false;
}
argv++;
@ -4234,17 +4618,19 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
uint32 argc, uint32 *argv, bool with_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_trap_t *trap = NULL;
bool ret = false;
wasm_val_vec_t params_vec, results_vec;
if (func_type->param_count > 16
&& !(params = wasm_runtime_malloc(sizeof(wasm_val_t)
* func_type->param_count))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
return false;
if (func_type->param_count > 16) {
if (!(params =
runtime_malloc(sizeof(wasm_val_t) * func_type->param_count,
module_inst, NULL, 0))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
return false;
}
}
if (!argv_to_params(params, argv, func_type)) {
@ -4252,11 +4638,13 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
goto fail;
}
if (func_type->result_count > 4
&& !(results = wasm_runtime_malloc(sizeof(wasm_val_t)
* func_type->result_count))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
goto fail;
if (func_type->result_count > 4) {
if (!(results =
runtime_malloc(sizeof(wasm_val_t) * func_type->result_count,
module_inst, NULL, 0))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
goto fail;
}
}
params_vec.data = params;

View File

@ -525,11 +525,6 @@ bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
uint32 argc, uint32 argv[]);
bool
wasm_runtime_create_exec_env_and_call_wasm(
WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function,
uint32 argc, uint32 argv[]);
bool
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
@ -813,16 +808,6 @@ wasm_runtime_dump_module_inst_mem_consumption(
void
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
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
const WASMExport *export_, WASMType **out);

View File

@ -96,6 +96,7 @@ typedef struct AOTMemInitData {
typedef struct AOTImportTable {
char *module_name;
char *table_name;
uint32 elem_type;
uint32 table_flags;
uint32 table_init_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].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_max_size);
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
#define WASM_VAL_T_DEFINED
struct wasm_ref_t;
typedef struct wasm_val_t {
wasm_valkind_t kind;
union {
/* also represent a function index */
int32_t i32;
int64_t i64;
float f32;
double f64;
struct wasm_ref_t *ref;
/* represent a foreign object, aka externref in .wat */
uintptr_t foreign;
} of;
} wasm_val_t;
#endif
@ -790,6 +791,7 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
* 'I': the parameter is i64 type
* 'f': the parameter is f32 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
* auto check its boundary before calling the native function.
* 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;
}
#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
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
#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_prepare_call_function(exec_env, func);
#endif
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
/* don't destroy the exec_env if it's searched from the cluster */
if (!existing_exec_env)
@ -1770,9 +1762,14 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
bool
wasm_create_exec_env_singleton(WASMModuleInstance *module_inst)
{
WASMExecEnv *exec_env =
wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size);
WASMExecEnv *exec_env = NULL;
if (module_inst->exec_env_singleton) {
return true;
}
exec_env = wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size);
if (exec_env)
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 strncasecmp _strnicmp
#define strcasecmp _stricmp
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#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:
- '**i**': i32 or externref (for externref, developer should use `wasm_externref_obj2ref()` to map host object to externref index firstly)
- '**i**': i32
- '**I**': i64
- '**f**': f32
- '**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 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

View File

@ -1,22 +1,9 @@
# 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:
```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.
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`.
Please ref to the [sample](../samples/ref-types) for more details.

View File

@ -116,7 +116,7 @@ endif()
# wat to wasm
file(GLOB WAT_FILE src/hello.wat)
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}
BYPRODUCTS ${PROJECT_BINARY_DIR}/hello.wasm
VERBATIM

View File

@ -13,52 +13,170 @@
static char global_heap_buf[10 * 1024 * 1024] = { 0 };
#endif
static int
test_write_wrapper(wasm_exec_env_t exec_env, uint32 externref_idx_of_file,
const char *str, int len)
static uintptr_t global_objects[10] = { 0 };
int32
local_cmp_externref(wasm_exec_env_t exec_env, uintptr_t externref_a,
uintptr_t externref_b)
{
FILE *file;
char buf[16];
return externref_a == externref_b;
}
printf("## retrieve file handle from externref index\n");
if (!wasm_externref_ref2obj(externref_idx_of_file, (void **)&file)) {
printf("failed to get host object from externref index!\n");
return -1;
}
snprintf(buf, sizeof(buf), "%%%ds", len);
printf("## write string to file: ");
printf(buf, str);
return fprintf(file, buf, str);
int32
local_chk_externref(wasm_exec_env_t exec_env, int32 index, uintptr_t externref)
{
return externref == global_objects[index];
}
/* clang-format off */
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 */
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
main(int argc, char *argv[])
{
char *wasm_file = "hello.wasm";
uint8 *wasm_file_buf = NULL;
uint32 wasm_file_size, externref_idx;
uint32 wasm_file_size;
uint32 stack_size = 16 * 1024, heap_size = 16 * 1024;
wasm_module_t wasm_module = NULL;
wasm_module_inst_t wasm_module_inst = NULL;
wasm_function_inst_t func_inst = NULL;
wasm_exec_env_t exec_env = NULL;
RuntimeInitArgs init_args;
char error_buf[128] = { 0 };
const char *exce;
unsigned argv1[8];
#if WASM_ENABLE_LOG != 0
int log_verbose_level = 2;
#endif
FILE *file;
const uint64 big_number = 0x123456789abc;
memset(&init_args, 0, sizeof(RuntimeInitArgs));
@ -90,13 +208,13 @@ main(int argc, char *argv[])
/* load WASM byte buffer from WASM bin file */
if (!(wasm_file_buf =
(uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
goto fail1;
goto fail;
/* load WASM module */
if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
error_buf, sizeof(error_buf)))) {
printf("%s\n", error_buf);
goto fail2;
goto fail;
}
/* instantiate the module */
@ -104,62 +222,66 @@ main(int argc, char *argv[])
wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
error_buf, sizeof(error_buf)))) {
printf("%s\n", error_buf);
goto fail3;
}
/* lookup function instance */
if (!(func_inst =
wasm_runtime_lookup_function(wasm_module_inst, "test", NULL))) {
printf("%s\n", "lookup function test failed");
goto fail4;
goto fail;
}
/* create an execution env */
if (!(exec_env =
wasm_runtime_create_exec_env(wasm_module_inst, stack_size))) {
printf("%s\n", "create exec env failed");
goto fail4;
goto fail;
}
printf("## open file test.txt\n");
if (!(file = fopen("test.txt", "wb+"))) {
printf("%s\n", "open file text.txt failed");
goto fail5;
/* lookup function instance */
if (!(wasm_cmp_externref_ptr = wasm_runtime_lookup_function(
wasm_module_inst, "cmp-externref", NULL))) {
printf("%s\n", "lookup function cmp-externref failed");
goto fail;
}
printf("## map file handle to externref index\n");
if (!wasm_externref_obj2ref(wasm_module_inst, file, &externref_idx)) {
printf("%s\n", "map host object to externref index failed");
goto fail6;
if (!(wasm_get_externref_ptr = wasm_runtime_lookup_function(
wasm_module_inst, "get-externref", NULL))) {
printf("%s\n", "lookup function get-externref failed");
goto fail;
}
printf("## call wasm function with externref index\n");
argv1[0] = externref_idx;
wasm_runtime_call_wasm(exec_env, func_inst, 1, argv1);
if ((exce = wasm_runtime_get_exception(wasm_module_inst))) {
printf("Exception: %s\n", exce);
if (!(wasm_set_externref_ptr = wasm_runtime_lookup_function(
wasm_module_inst, "set-externref", NULL))) {
printf("%s\n", "lookup function set-externref failed");
goto fail;
}
fail6:
fclose(file);
/* test with NULL */
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 */
wasm_runtime_destroy_exec_env(exec_env);
if (exec_env) {
wasm_runtime_destroy_exec_env(exec_env);
}
fail4:
/* destroy the module instance */
wasm_runtime_deinstantiate(wasm_module_inst);
if (wasm_module_inst) {
wasm_runtime_deinstantiate(wasm_module_inst);
}
fail3:
/* unload the module */
wasm_runtime_unload(wasm_module);
if (wasm_module) {
wasm_runtime_unload(wasm_module);
}
fail2:
/* free the file buffer */
wasm_runtime_free(wasm_file_buf);
if (wasm_file_buf) {
wasm_runtime_free(wasm_file_buf);
}
fail1:
/* destroy runtime environment */
wasm_runtime_destroy();
return 0;

View File

@ -2,21 +2,43 @@
;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
(module
;; import test_write function which is implemented by host
(import "env" "test_write"
(func $test_write (param externref i32 i32) (result i32)))
(type $t0 (func (param i32 externref) (result i32)))
;; memory with one page (64KiB).
(memory (export "memory") 1)
(import "env" "native-cmp-externref"
(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
(func (export "test") (param externref)
(local.get 0)
(i32.const 0x8)
(i32.const 14)
(call $test_write)
drop
(table $t1 8 8 externref)
(table $t2 funcref
(elem
$native-cmp-externref
$native-chk-externref
)
)
(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

@ -35,7 +35,7 @@ void wasm_val_print(wasm_val_t val) {
// A function to be called from Wasm code.
own wasm_trap_t* print_callback(
const wasm_val_vec_t *args, wasm_val_vec_t *results
const wasm_val_vec_t* args, wasm_val_vec_t* results
) {
printf("Calling back...\n> ");
wasm_val_print(args->data[0]);
@ -48,7 +48,7 @@ own wasm_trap_t* print_callback(
// A function closure.
own wasm_trap_t* closure_callback(
void* env, const wasm_val_vec_t *args, wasm_val_vec_t *results
void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results
) {
int i = *(int*)env;
printf("Calling back closure...\n");
@ -113,11 +113,10 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports;
wasm_extern_vec_new(&imports, 2, (wasm_extern_t *[]) {
wasm_extern_t* externs[] = {
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 =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
@ -147,9 +146,10 @@ int main(int argc, const char* argv[]) {
// Call.
printf("Calling export...\n");
wasm_val_vec_t args, results;
wasm_val_vec_new(&args, 2, (wasm_val_t[]){ WASM_I32_VAL(3), WASM_I32_VAL(4) });
wasm_val_vec_new(&results, 1, (wasm_val_t[]) { WASM_INIT_VAL });
wasm_val_t as[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
wasm_val_t rs[1] = { 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)) {
printf("> Error calling function!\n");
return 1;
@ -159,7 +159,7 @@ int main(int argc, const char* argv[]) {
// Print result.
printf("Printing result...\n");
printf("> %u\n", results.data[0].of.i32);
printf("> %u\n", rs[0].of.i32);
// Shut down.
printf("Shutting down...\n");

View File

@ -61,10 +61,7 @@ enum EXPORT_ITEM_NAME {
DEFINE_FUNCTION(get_pairs)
{
wasm_val_vec_t arg, ret;
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");
call_wasm_function(e_malloc, args, results, "malloc");
return NULL;
}
@ -204,9 +201,6 @@ main(int argc, const char *argv[])
IMPORT_FUNCTION_LIST(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) \
{ \
own wasm_functype_t *type = CREATE_FUNC_TYPE; \
@ -219,13 +213,13 @@ main(int argc, const char *argv[])
IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION)
#undef CREATE_WASM_FUNCTION
wasm_extern_t *fs[10] = {0};
#define ADD_TO_FUNCTION_LIST(name, index, ...) \
imports.data[index] = wasm_func_as_extern(function_##name); \
imports.num_elems += 1;
fs[index] = wasm_func_as_extern(function_##name);
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 =
wasm_instance_new(store, module, &imports, NULL);
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) \
{ \
wasm_val_vec_t results; \
wasm_val_vec_new_uninitialized(&results, 1); \
wasm_func_call(func, NULL, &results); \
check(results.data[0], type, expected); \
wasm_val_t vs[1]; \
wasm_val_vec_t args = WASM_EMPTY_VEC; \
wasm_val_vec_t results = WASM_ARRAY_VEC(vs); \
wasm_func_call(func, &args, &results); \
check(vs[0], type, expected); \
}
@ -116,19 +117,13 @@ int main(int argc, const char* argv[]) {
// Instantiate.
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_i64_import),
wasm_global_as_extern(var_f32_import),
wasm_global_as_extern(var_i64_import)
};*/
wasm_extern_vec_t imports;
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)
});
};
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
@ -208,18 +203,19 @@ int main(int argc, const char* argv[]) {
check_call(get_var_i64_export, i64, 38);
// Modify variables through calls and check again.
wasm_val_vec_t args73;
wasm_val_vec_new(&args73, 1, (wasm_val_t []){ WASM_F32_VAL(73) });
wasm_func_call(set_var_f32_import, &args73, NULL);
wasm_val_vec_t args74;
wasm_val_vec_new(&args74, 1, (wasm_val_t []){ WASM_I64_VAL(74) });
wasm_func_call(set_var_i64_import, &args74, NULL);
wasm_val_vec_t args77;
wasm_val_vec_new(&args77, 1, (wasm_val_t []){ WASM_F32_VAL(77) });
wasm_func_call(set_var_f32_export, &args77, NULL);
wasm_val_vec_t args78;
wasm_val_vec_new(&args78, 1, (wasm_val_t []){ WASM_I64_VAL(78) });
wasm_func_call(set_var_i64_export, &args78, NULL);
wasm_val_vec_t res = WASM_EMPTY_VEC;
wasm_val_t vs73[] = { WASM_F32_VAL(73) };
wasm_val_vec_t args73 = WASM_ARRAY_VEC(vs73);
wasm_func_call(set_var_f32_import, &args73, &res);
wasm_val_t vs74[] = { WASM_I64_VAL(74) };
wasm_val_vec_t args74 = WASM_ARRAY_VEC(vs74);
wasm_func_call(set_var_i64_import, &args74, &res);
wasm_val_t vs77[] = { WASM_F32_VAL(77) };
wasm_val_vec_t args77 = WASM_ARRAY_VEC(vs77);
wasm_func_call(set_var_f32_export, &args77, &res);
wasm_val_t vs78[] = { WASM_I64_VAL(78) };
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_i64_import, i64, 74);

View File

@ -66,9 +66,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports;
wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(hello_func) });
wasm_extern_t* externs[] = { wasm_func_as_extern(hello_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
@ -98,7 +97,9 @@ int main(int argc, const char* argv[]) {
// Call.
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");
return 1;
}
@ -114,4 +115,3 @@ int main(int argc, const char* argv[]) {
printf("Done.\n");
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) {
printf("call_v_r... "); fflush(stdout);
wasm_val_vec_t rs;
wasm_val_vec_new_uninitialized(&rs, 1);
if (wasm_func_call(func, NULL, &rs)) {
wasm_val_t rs[] = { WASM_INIT_VAL };
wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n");
exit(1);
}
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) {
printf("call_r_v... "); fflush(stdout);
wasm_val_vec_t vs;
wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_REF_VAL(ref) });
if (wasm_func_call(func, &vs, NULL)) {
wasm_val_t vs[1] = { WASM_REF_VAL(ref) };
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
wasm_val_vec_t results = WASM_EMPTY_VEC;
if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n");
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) {
printf("call_r_r... "); fflush(stdout);
wasm_val_vec_t vs, rs;
wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_REF_VAL(ref) });
wasm_val_vec_new_uninitialized(&rs, 1);
if (wasm_func_call(func, &vs, &rs)) {
wasm_val_t vs[1] = { WASM_REF_VAL(ref) };
wasm_val_t rs[1] = { WASM_INIT_VAL };
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n");
exit(1);
}
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) {
printf("call_ir_v... "); fflush(stdout);
wasm_val_vec_t vs;
wasm_val_vec_new(&vs, 2, (wasm_val_t []){ WASM_I32_VAL(i), WASM_REF_VAL(ref) });
if (wasm_func_call(func, &vs, NULL)) {
wasm_val_t vs[2] = { WASM_I32_VAL(i), WASM_REF_VAL(ref) };
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
wasm_val_vec_t results = WASM_EMPTY_VEC;
if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n");
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) {
printf("call_i_r... "); fflush(stdout);
wasm_val_vec_t vs, rs;
wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_I32_VAL(i) });
wasm_val_vec_new_uninitialized(&rs, 1);
if (wasm_func_call(func, &vs, &rs)) {
wasm_val_t vs[1] = { WASM_I32_VAL(i) };
wasm_val_t rs[1] = { WASM_INIT_VAL };
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
if (wasm_func_call(func, &args, &results)) {
printf("> Error calling function!\n");
exit(1);
}
printf("okay\n");
return rs.data[0].of.ref;
return rs[0].of.ref;
}
void
check(own wasm_ref_t *actual, const wasm_ref_t *expected, bool release_ref)
{
if (actual != expected
&& !(actual && expected && wasm_ref_same(actual, expected))) {
printf("> Error reading reference, expected %p, got %p\n",
expected ? wasm_ref_get_host_info(expected) : NULL,
actual ? wasm_ref_get_host_info(actual) : NULL);
exit(1);
}
if (release_ref && actual)
wasm_ref_delete(actual);
void check(own wasm_ref_t* actual, const wasm_ref_t* expected) {
if (actual != expected &&
!(actual && expected && wasm_ref_same(actual, expected))) {
printf("> Error reading reference, expected %p, got %p\n",
expected ? wasm_ref_get_host_info(expected) : NULL,
actual ? wasm_ref_get_host_info(actual) : NULL);
exit(1);
}
// if (actual) wasm_ref_delete(actual);
}
int main(int argc, const char* argv[]) {
// Initialize.
printf("Initializing...\n");
@ -169,8 +172,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports;
wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(callback_func) });
wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
@ -204,54 +207,61 @@ int main(int argc, const char* argv[]) {
wasm_ref_set_host_info(host2, (void*)2);
// Some sanity checks.
check(NULL, NULL, true);
check(wasm_ref_copy(host1), host1, true);
check(wasm_ref_copy(host2), host2, true);
check(NULL, NULL);
wasm_ref_t *host1_cp = wasm_ref_copy(host1);
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;
val.kind = WASM_ANYREF;
val.of.ref = wasm_ref_copy(host1);
check(wasm_ref_copy(val.of.ref), host1, true);
own wasm_ref_t* ref = val.of.ref;
check(wasm_ref_copy(ref), host1, true);
wasm_ref_t *ref_cp = wasm_ref_copy(val.of.ref);
check(ref_cp, host1);
check(val.of.ref, host1);
wasm_ref_delete(val.of.ref);
wasm_ref_delete(ref_cp);
// Interact.
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);
check(call_v_r(global_get), host1, false);
check(call_v_r(global_get), host1);
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);
check(call_v_r(global_get), NULL, false);
check(call_v_r(global_get), NULL);
wasm_global_get(global, &val);
assert(val.kind == WASM_ANYREF);
check(val.of.ref, NULL, false);
assert(val.of.ref == NULL);
val.of.ref = host2;
wasm_global_set(global, &val);
check(call_v_r(global_get), host2, false);
wasm_global_get(global, &val);
assert(val.kind == WASM_ANYREF);
check(val.of.ref, host2, false);
assert(val.of.ref == host2);
printf("Accessing table...\n");
check(call_i_r(table_get, 0), NULL, false);
check(call_i_r(table_get, 1), NULL, false);
check(call_i_r(table_get, 0), NULL);
check(call_i_r(table_get, 1), NULL);
call_ir_v(table_set, 0, host1);
call_ir_v(table_set, 1, host2);
check(call_i_r(table_get, 0), host1, false);
check(call_i_r(table_get, 1), host2, false);
check(call_i_r(table_get, 0), host1);
check(call_i_r(table_get, 1), host2);
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");
check(call_r_r(func_call, NULL), NULL, false);
check(call_r_r(func_call, host1), host1, false);
check(call_r_r(func_call, host2), host2, false);
check(call_r_r(func_call, NULL), NULL);
check(call_r_r(func_call, host1), host1);
check(call_r_r(func_call, host2), host2);
wasm_ref_delete(host1);
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) {
wasm_val_vec_t args_vec;
wasm_val_vec_t results_vec;
if (args)
wasm_val_vec_new(&args_vec, i, args);
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) {
wasm_val_t r[] = {WASM_INIT_VAL};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
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");
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[]) {
wasm_val_vec_t args_vec;
wasm_val_vec_new(&args_vec, i, args);
if (wasm_func_call(func, &args_vec, NULL)) {
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
wasm_val_vec_t results = WASM_EMPTY_VEC;
if (wasm_func_call(func, &args_, &results)) {
printf("> Error on result, expected empty\n");
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[]) {
wasm_val_vec_t args_vec, results_vec;
wasm_val_vec_new(&args_vec, i, args);
wasm_val_vec_new(&results_vec, 1, (wasm_val_t []){ WASM_INIT_VAL });
own wasm_trap_t* trap = wasm_func_call(func, &args_vec, &results_vec);
wasm_val_t r[] = {WASM_INIT_VAL};
wasm_val_vec_t args_ = {i, args, i, sizeof(wasm_val_t)};
wasm_val_vec_t results = WASM_ARRAY_VEC(r);
own wasm_trap_t* trap = wasm_func_call(func, &args_, &results);
if (! trap) {
printf("> Error on result, expected trap\n");
exit(1);
@ -137,8 +134,9 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t* instance =
wasm_instance_new_with_args(store, module, NULL, NULL, KILOBYTE(8), 0);
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t *instance = wasm_instance_new_with_args(
store, module, &imports, NULL, KILOBYTE(32), 0);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
@ -156,15 +154,6 @@ int main(int argc, const char* argv[]) {
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.
own wasm_memory_t* copy = wasm_memory_copy(memory);
assert(wasm_memory_same(memory, copy));
@ -172,13 +161,13 @@ int main(int argc, const char* argv[]) {
// Check initial memory.
printf("Checking memory...\n");
check(wasm_memory_size(memory) >= 2);
check(wasm_memory_data_size(memory) >= 0x20000);
check(wasm_memory_size(memory) == 2);
check(wasm_memory_data_size(memory) == 0x20000);
check(wasm_memory_data(memory)[0] == 0);
check(wasm_memory_data(memory)[0x1000] == 1);
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, 0x1000, 1);
check_call1(load_func, 0x1003, 4);

View File

@ -9,7 +9,7 @@
// A function to be called from Wasm code.
own wasm_trap_t* callback(
const wasm_val_vec_t *args, wasm_val_vec_t *results
const wasm_val_vec_t* args, wasm_val_vec_t* results
) {
printf("Calling back...\n> ");
printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n",
@ -27,14 +27,14 @@ own wasm_trap_t* callback(
// A function closure.
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;
printf("Calling back closure...\n");
printf("> %d\n", i);
results[0].kind = WASM_I32;
results[0].of.i32 = (int32_t)i;
results->data[0].kind = WASM_I32;
results->data[0].of.i32 = (int32_t)i;
return NULL;
}
@ -47,7 +47,11 @@ int main(int argc, const char* argv[]) {
// Load binary.
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");
#endif
if (!file) {
printf("> Error loading module!\n");
return 1;
@ -91,8 +95,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports;
wasm_extern_vec_new(&imports, 1, (wasm_extern_t *[]) { wasm_func_as_extern(callback_func) });
wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
@ -121,13 +125,14 @@ int main(int argc, const char* argv[]) {
// Call.
printf("Calling export...\n");
wasm_val_vec_t args, results;
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_val_vec_new(&results, 4, (wasm_val_t []) {
WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL
});
wasm_val_t vals[4] = {
WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4)
};
wasm_val_t res[4] = {
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)) {
printf("> Error calling function!\n");
return 1;
@ -138,12 +143,12 @@ int main(int argc, const char* argv[]) {
// Print result.
printf("Printing result...\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(results.data[1].of.i64 == 2);
assert(results.data[2].of.i64 == 3);
assert(results.data[3].of.i32 == 4);
assert(res[0].of.i32 == 4);
assert(res[1].of.i64 == 3);
assert(res[2].of.i64 == 2);
assert(res[3].of.i32 == 1);
// Shut down.
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) {
bool first = true;
if (!types) {
printf("> Error print a NULL valtype\n");
return;
}
for (size_t i = 0; i < types->size; ++i) {
if (first) {
first = false;
@ -49,11 +43,6 @@ void print_valtypes(const wasm_valtype_vec_t* types) {
}
void print_externtype(const wasm_externtype_t* type) {
if (!type) {
printf("> Error print a NULL externtype\n");
return;
}
switch (wasm_externtype_kind(type)) {
case WASM_EXTERN_FUNC: {
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) {
if (!name) {
printf("> Error print a NULL name\n");
return;
}
printf("\"%.*s\"", (int)name->size, name->data);
}
@ -139,8 +123,9 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL);
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
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) {
wasm_val_vec_t args, results;
wasm_val_vec_new(&args, 2, (wasm_val_t []){ WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) });
wasm_val_vec_new(&results, 1, (wasm_val_t []){ WASM_INIT_VAL });
if (wasm_func_call(func, &args, &results) || results.data[0].of.i32 != expected) {
wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
wasm_val_t r[1] = { WASM_INIT_VAL };
wasm_val_vec_t args = WASM_ARRAY_VEC(vs);
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");
exit(1);
}
}
void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) {
wasm_val_vec_t args, results;
wasm_val_vec_new(&args, 2, (wasm_val_t []){ WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) });
wasm_val_vec_new(&results, 1, (wasm_val_t []){ WASM_INIT_VAL });
wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) };
wasm_val_t r[1] = { 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);
if (! trap) {
printf("> Error on result, expected trap\n");
@ -112,8 +114,9 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t *instance =
wasm_instance_new(store, module, NULL, NULL);
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
@ -134,6 +137,7 @@ int main(int argc, const char* argv[]) {
// Create external function.
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_func_t* h = wasm_func_new(store, neg_type, neg_callback);
wasm_functype_delete(neg_type);
@ -155,7 +159,9 @@ int main(int argc, const char* argv[]) {
printf("Mutating table...\n");
check(wasm_table_set(table, 0, wasm_func_as_ref(g)));
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, 1, false);
check_call(call_indirect, 7, 0, 666);
@ -165,6 +171,8 @@ int main(int argc, const char* argv[]) {
// Grow table.
// DO NOT SUPPORT
printf("Bypass Growing table...\n");
wasm_func_delete(h);
wasm_extern_vec_delete(&exports);
wasm_instance_delete(instance);

View File

@ -80,8 +80,8 @@ int main(int argc, const char* argv[]) {
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports;
wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(fail_func) });
wasm_extern_t* externs[] = { wasm_func_as_extern(fail_func) };
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
own wasm_instance_t* instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
@ -112,10 +112,9 @@ int main(int argc, const char* argv[]) {
}
printf("Calling export %d...\n", i);
wasm_val_vec_t results;
wasm_val_vec_new_uninitialized(&results, 1);
own wasm_trap_t* trap = wasm_func_call(func, NULL, &results);
wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t results = WASM_EMPTY_VEC;
own wasm_trap_t* trap = wasm_func_call(func, &args, &results);
if (!trap) {
printf("> Error calling function, expected trap!\n");
return 1;