Просмотр исходного кода

Enable call wasm-c-api native func directly from interpreter (#656)

And update loader error messages for latest spec cases, fix aot compiler build error based on latest LLVM code base.
Wenyong Huang 4 лет назад
Родитель
Сommit
cba4c78273

+ 3 - 139
core/iwasm/aot/aot_runtime.c

@@ -13,7 +13,6 @@
 #if WASM_ENABLE_THREAD_MGR != 0
 #include "../libraries/thread-mgr/thread_manager.h"
 #endif
-#include "../common/wasm_c_api_internal.h"
 
 static void
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
@@ -2204,140 +2203,6 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
     return wasm_type_equal(type1, type2);
 }
 
-static inline bool
-argv_to_params(wasm_val_t *out_params, const uint32 *argv,
-               AOTFuncType *func_type)
-{
-    wasm_val_t *param = out_params;
-    uint32 i = 0, *u32;
-
-    for (i = 0; i < func_type->param_count; i++, param++) {
-        switch (func_type->types[i]) {
-            case VALUE_TYPE_I32:
-                param->kind = WASM_I32;
-                param->of.i32 = *argv++;
-                break;
-            case VALUE_TYPE_I64:
-                param->kind = WASM_I64;
-                u32 = (uint32*)&param->of.i64;
-                u32[0] = *argv++;
-                u32[1] = *argv++;
-                break;
-            case VALUE_TYPE_F32:
-                param->kind = WASM_F32;
-                param->of.f32 = *(float32 *)argv++;
-                break;
-            case VALUE_TYPE_F64:
-                param->kind = WASM_F64;
-                u32 = (uint32*)&param->of.i64;
-                u32[0] = *argv++;
-                u32[1] = *argv++;
-                break;
-            default:
-                return false;
-        }
-    }
-
-    return true;
-}
-
-static inline bool
-results_to_argv(uint32 *out_argv, const wasm_val_t *results,
-                AOTFuncType *func_type)
-{
-    const wasm_val_t *result = results;
-    uint32 *argv = out_argv, *u32, i;
-    uint8 *result_types = func_type->types + func_type->param_count;
-
-    for (i = 0; i < func_type->result_count; i++, result++) {
-        switch (result_types[i]) {
-            case VALUE_TYPE_I32:
-            case VALUE_TYPE_F32:
-                *(int32*)argv++ = result->of.i32;
-                break;
-            case VALUE_TYPE_I64:
-            case VALUE_TYPE_F64:
-                u32 = (uint32*)&result->of.i64;
-                *argv++ = u32[0];
-                *argv++ = u32[1];
-                break;
-            default:
-                return false;
-        }
-    }
-
-    return true;
-}
-
-static inline bool
-invoke_wasm_c_api_native(AOTModuleInstance *module_inst, void *func_ptr,
-                         AOTFuncType *func_type, 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 = params_buf, *results = results_buf;
-    wasm_trap_t *trap = NULL;
-    bool ret = false;
-    char fmt[16];
-
-    if (func_type->param_count > 16
-        && !(params = wasm_runtime_malloc(sizeof(wasm_val_t)
-                                          * func_type->param_count))) {
-        aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY);
-        return false;
-    }
-
-    if (!argv_to_params(params, argv, func_type)) {
-        aot_set_exception(module_inst, "unsupported param type");
-        goto fail;
-    }
-
-    if (!with_env) {
-        wasm_func_callback_t callback = (wasm_func_callback_t)func_ptr;
-        trap = callback(params, results);
-    }
-    else {
-        wasm_func_callback_with_env_t callback =
-                            (wasm_func_callback_with_env_t)func_ptr;
-        trap = callback(wasm_c_api_env, params, results);
-    }
-    if (trap) {
-        if (trap->message->data) {
-            snprintf(fmt, sizeof(fmt), "%%.%us", (uint32)trap->message->size);
-            snprintf(module_inst->cur_exception,
-                     sizeof(module_inst->cur_exception),
-                     fmt, trap->message->data);
-        }
-        else {
-            aot_set_exception(module_inst,
-                              "native function throw unknown exception");
-        }
-        wasm_trap_delete(trap);
-        goto fail;
-    }
-
-    if (func_type->result_count > 4
-        && !(results = wasm_runtime_malloc(sizeof(wasm_val_t)
-                                           * func_type->result_count))) {
-        aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY);
-        goto fail;
-    }
-
-    if (!results_to_argv(argv, results, func_type)) {
-        aot_set_exception(module_inst, "unsupported result type");
-        goto fail;
-    }
-
-    ret = true;
-
-fail:
-    if (params != params_buf)
-        wasm_runtime_free(params);
-    if (results != results_buf)
-        wasm_runtime_free(results);
-    return ret;
-}
-
 bool
 aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
                   uint32 argc, uint32 *argv)
@@ -2368,10 +2233,9 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
 
     attachment = import_func->attachment;
     if (import_func->call_conv_wasm_c_api) {
-        return invoke_wasm_c_api_native(module_inst, func_ptr,
-                                       func_type, argc, argv,
-                                       import_func->wasm_c_api_with_env,
-                                       attachment);
+        return wasm_runtime_invoke_c_api_native(
+          (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc,
+          argv, import_func->wasm_c_api_with_env, attachment);
     }
     else if (!import_func->call_conv_raw) {
         signature = import_func->signature;

+ 26 - 193
core/iwasm/common/wasm_c_api.c

@@ -1401,10 +1401,9 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
 
     INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
 
-    module_ex->module_comm_rt =
-        wasm_runtime_load((uint8 *)module_ex->binary->data,
-                          (uint32)module_ex->binary->size,
-                          error_buf, (uint32)sizeof(error_buf));
+    module_ex->module_comm_rt = wasm_runtime_load(
+      (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
+      error_buf, (uint32)sizeof(error_buf));
     if (!(module_ex->module_comm_rt)) {
         LOG_ERROR(error_buf);
         goto failed;
@@ -1846,172 +1845,6 @@ failed_exporttype_new:
     wasm_exporttype_vec_delete(out);
 }
 
-static uint32
-argv_to_params(const uint64 *argv,
-               const wasm_valtype_vec_t *param_defs,
-               wasm_val_t out[])
-{
-    size_t i = 0;
-    uint32 argc = 0;
-
-    for (i = 0; i < param_defs->num_elems; i++) {
-        wasm_valtype_t *param_def = param_defs->data[i];
-        wasm_val_t *param = out + i;
-        switch (param_def->kind) {
-            case WASM_I32:
-                param->kind = WASM_I32;
-                param->of.i32 = *(uint32 *)(argv + i);
-                argc++;
-                break;
-            case WASM_I64:
-                param->kind = WASM_I64;
-                param->of.i64 = *(uint64 *)(argv + i);
-                argc++;
-                break;
-            case WASM_F32:
-                param->kind = WASM_F32;
-                param->of.f32 = *(float32 *)(argv + i);
-                argc++;
-                break;
-            case WASM_F64:
-                param->kind = WASM_F64;
-                param->of.f64 = *(float64 *)(argv + i);
-                argc++;
-                break;
-            default:
-                LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
-                            param_def->kind);
-                goto failed;
-        }
-    }
-
-    return argc;
-failed:
-    return 0;
-}
-
-static uint32
-results_to_argv(const wasm_val_t *results,
-                const wasm_valtype_vec_t *result_defs,
-                uint64 *out)
-{
-    size_t i = 0;
-    uint32 argc = 0;
-
-    for (i = 0; i < result_defs->num_elems; ++i) {
-        wasm_valtype_t *result_def = result_defs->data[i];
-        const wasm_val_t *result = results + i;
-        switch (result_def->kind) {
-            case WASM_I32:
-                *(int32 *)(out + i) = result->of.i32;
-                argc++;
-                break;
-            case WASM_I64:
-                *(int64 *)(out + i) = result->of.i64;
-                argc++;
-                break;
-            case WASM_F32:
-                *(float32 *)(out + i) = result->of.f32;
-                argc++;
-                break;
-            case WASM_F64:
-                *(float64 *)(out + i) = result->of.f64;
-                argc++;
-                break;
-            default:
-            {
-                LOG_WARNING("%s meets unsupported kind", __FUNCTION__,
-                            result_def->kind);
-                goto failed;
-            }
-        }
-    }
-
-    return argc;
-failed:
-    return 0;
-}
-
-static wasm_trap_t *cur_trap = NULL;
-static void
-native_func_trampoline(wasm_exec_env_t exec_env, uint64 *argv)
-{
-    wasm_val_t *params = NULL, *results = NULL;
-    uint32 argc = 0;
-    const wasm_func_t *func = NULL;
-    wasm_trap_t *trap = NULL;
-    size_t param_count, result_count;
-
-    func = wasm_runtime_get_function_attachment(exec_env);
-    bh_assert(func);
-
-    param_count = wasm_func_param_arity(func);
-    if (param_count) {
-        if (!argv) {
-            goto failed;
-        }
-
-        if (!(params = malloc_internal(param_count * sizeof(wasm_val_t)))) {
-            goto failed;
-        }
-
-        /* argv -> const wasm_val_t params[] */
-        if (!(argc = argv_to_params(argv, wasm_functype_params(func->type),
-                                    params))) {
-            goto failed;
-        }
-    }
-
-    result_count = wasm_func_result_arity(func);
-    if (result_count) {
-        if (!argv) {
-            goto failed;
-        }
-
-        if (!(results = malloc_internal(result_count * sizeof(wasm_val_t)))) {
-            goto failed;
-        }
-    }
-
-    if (func->with_env) {
-        trap = func->u.cb_env.cb(func->u.cb_env.env, params, results);
-    }
-    else {
-        trap = func->u.cb(params, results);
-    }
-
-    if (trap) {
-        wasm_byte_vec_t message = { 0 };
-        wasm_trap_message(trap, &message);
-        if (message.data) {
-            LOG_WARNING("got a trap %s", message.data);
-            wasm_runtime_set_exception(exec_env->module_inst,
-                                       "call failed, meet a wasm_trap_t");
-        }
-        wasm_byte_vec_delete(&message);
-
-        cur_trap = trap;
-    }
-
-    if (argv) {
-        memset(argv, 0, wasm_func_param_arity(func) * sizeof(uint64));
-    }
-
-    /* there is no trap and there is return values */
-    if (!trap && result_count) {
-        /* wasm_val_t results[] -> argv */
-        if (!(argc = results_to_argv(
-                results, wasm_functype_results(func->type), argv))) {
-            goto failed;
-        }
-    }
-
-failed:
-    FREEIF(params);
-    FREEIF(results);
-    return;
-}
-
 static wasm_func_t *
 wasm_func_new_basic(const wasm_functype_t *type,
                     wasm_func_callback_t func_callback)
@@ -2342,8 +2175,6 @@ wasm_func_call(const wasm_func_t *func,
 
     bh_assert(func && func->type && func->inst_comm_rt);
 
-    cur_trap = NULL;
-
 #if WASM_ENABLE_INTERP != 0
     if (func->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
         func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->functions
@@ -2354,7 +2185,8 @@ wasm_func_call(const wasm_func_t *func,
 #if WASM_ENABLE_AOT != 0
     if (func->inst_comm_rt->module_type == Wasm_Module_AoT) {
         if (!(func_comm_rt = func->func_comm_rt)) {
-            AOTModuleInstance *inst_aot = (AOTModuleInstance *)func->inst_comm_rt;
+            AOTModuleInstance *inst_aot =
+              (AOTModuleInstance *)func->inst_comm_rt;
             AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
             uint32 export_i = 0, export_func_j = 0;
 
@@ -2363,9 +2195,9 @@ wasm_func_call(const wasm_func_t *func,
                 if (export->kind == EXPORT_KIND_FUNC) {
                     if (export->index == func->func_idx_rt) {
                         func_comm_rt =
-                            (AOTFunctionInstance *)inst_aot->export_funcs.ptr
-                            + export_func_j;
-                        ((wasm_func_t*)func)->func_comm_rt = func_comm_rt;
+                          (AOTFunctionInstance *)inst_aot->export_funcs.ptr
+                          + export_func_j;
+                        ((wasm_func_t *)func)->func_comm_rt = func_comm_rt;
                         break;
                     }
                     export_func_j++;
@@ -2382,7 +2214,7 @@ wasm_func_call(const wasm_func_t *func,
     param_count = wasm_func_param_arity(func);
     result_count = wasm_func_result_arity(func);
     alloc_count = (param_count > result_count) ? param_count : result_count;
-    if (alloc_count > sizeof(argv_buf)/sizeof(uint64)) {
+    if (alloc_count > sizeof(argv_buf) / sizeof(uint64)) {
         if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) {
             goto failed;
         }
@@ -2422,17 +2254,13 @@ wasm_func_call(const wasm_func_t *func,
 failed:
     if (argv != argv_buf)
         wasm_runtime_free(argv);
-    if (cur_trap) {
-        return cur_trap;
+
+    if (wasm_runtime_get_exception(func->inst_comm_rt)) {
+        return wasm_trap_new_internal(
+          wasm_runtime_get_exception(func->inst_comm_rt));
     }
     else {
-        if (wasm_runtime_get_exception(func->inst_comm_rt)) {
-            return wasm_trap_new_internal(
-              wasm_runtime_get_exception(func->inst_comm_rt));
-        }
-        else {
-            return wasm_trap_new_internal("wasm_func_call failed");
-        }
+        return wasm_trap_new_internal("wasm_func_call failed");
     }
 }
 
@@ -3182,10 +3010,16 @@ interp_link_func(const wasm_instance_t *inst,
         return false;
     }
 
-    /* add native_func_trampoline as a NativeSymbol */
-    imported_func_interp->u.function.call_conv_raw = true;
-    imported_func_interp->u.function.attachment = cloned;
-    imported_func_interp->u.function.func_ptr_linked = native_func_trampoline;
+    imported_func_interp->u.function.call_conv_wasm_c_api = true;
+    imported_func_interp->u.function.wasm_c_api_with_env = import->with_env;
+    if (import->with_env) {
+        imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
+        imported_func_interp->u.function.attachment = import->u.cb_env.env;
+    }
+    else {
+        imported_func_interp->u.function.func_ptr_linked = import->u.cb;
+        imported_func_interp->u.function.attachment = NULL;
+    }
     import->func_idx_rt = func_idx_rt;
 
     return true;
@@ -3672,9 +3506,8 @@ wasm_instance_new(wasm_store_t *store,
 #endif
     }
 
-    instance->inst_comm_rt =
-        wasm_runtime_instantiate(*module, stack_size, heap_size,
-                                 error_buf, sizeof(error_buf));
+    instance->inst_comm_rt = wasm_runtime_instantiate(
+      *module, stack_size, heap_size, error_buf, sizeof(error_buf));
     if (!instance->inst_comm_rt) {
         LOG_ERROR(error_buf);
         goto failed;

+ 139 - 0
core/iwasm/common/wasm_runtime_common.c

@@ -21,6 +21,7 @@
 #if WASM_ENABLE_SHARED_MEMORY != 0
 #include "wasm_shared_memory.h"
 #endif
+#include "../common/wasm_c_api_internal.h"
 
 #if WASM_ENABLE_MULTI_MODULE != 0
 /*
@@ -4026,3 +4027,141 @@ wasm_runtime_get_memory_data_size(
     return 0;
 }
 
+static inline bool
+argv_to_params(wasm_val_t *out_params,
+               const uint32 *argv,
+               WASMType *func_type)
+{
+    wasm_val_t *param = out_params;
+    uint32 i = 0, *u32;
+
+    for (i = 0; i < func_type->param_count; i++, param++) {
+        switch (func_type->types[i]) {
+            case VALUE_TYPE_I32:
+                param->kind = WASM_I32;
+                param->of.i32 = *argv++;
+                break;
+            case VALUE_TYPE_I64:
+                param->kind = WASM_I64;
+                u32 = (uint32 *)&param->of.i64;
+                u32[0] = *argv++;
+                u32[1] = *argv++;
+                break;
+            case VALUE_TYPE_F32:
+                param->kind = WASM_F32;
+                param->of.f32 = *(float32 *)argv++;
+                break;
+            case VALUE_TYPE_F64:
+                param->kind = WASM_F64;
+                u32 = (uint32 *)&param->of.i64;
+                u32[0] = *argv++;
+                u32[1] = *argv++;
+                break;
+            default:
+                return false;
+        }
+    }
+
+    return true;
+}
+
+static inline bool
+results_to_argv(uint32 *out_argv,
+                const wasm_val_t *results,
+                WASMType *func_type)
+{
+    const wasm_val_t *result = results;
+    uint32 *argv = out_argv, *u32, i;
+    uint8 *result_types = func_type->types + func_type->param_count;
+
+    for (i = 0; i < func_type->result_count; i++, result++) {
+        switch (result_types[i]) {
+            case VALUE_TYPE_I32:
+            case VALUE_TYPE_F32:
+                *(int32 *)argv++ = result->of.i32;
+                break;
+            case VALUE_TYPE_I64:
+            case VALUE_TYPE_F64:
+                u32 = (uint32 *)&result->of.i64;
+                *argv++ = u32[0];
+                *argv++ = u32[1];
+                break;
+            default:
+                return false;
+        }
+    }
+
+    return true;
+}
+
+bool
+wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
+                                 void *func_ptr, WASMType *func_type,
+                                 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 = params_buf, *results = results_buf;
+    wasm_trap_t *trap = NULL;
+    bool ret = false;
+
+    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 (!argv_to_params(params, argv, func_type)) {
+        wasm_runtime_set_exception(module_inst, "unsupported param type");
+        goto fail;
+    }
+
+    if (!with_env) {
+        wasm_func_callback_t callback = (wasm_func_callback_t)func_ptr;
+        trap = callback(params, results);
+    }
+    else {
+        wasm_func_callback_with_env_t callback =
+          (wasm_func_callback_with_env_t)func_ptr;
+        trap = callback(wasm_c_api_env, params, results);
+    }
+
+    if (trap) {
+        if (trap->message->data) {
+            /* since trap->message->data does not end with '\0' */
+            char trap_message[128] = { 0 };
+            bh_memcpy_s(
+              trap_message, 127, trap->message->data,
+              (trap->message->size < 127 ? trap->message->size : 127));
+            wasm_runtime_set_exception(module_inst, trap_message);
+        }
+        else {
+            wasm_runtime_set_exception(
+              module_inst, "native function throw unknown exception");
+        }
+        wasm_trap_delete(trap);
+        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 (!results_to_argv(argv, results, func_type)) {
+        wasm_runtime_set_exception(module_inst, "unsupported result type");
+        goto fail;
+    }
+
+    ret = true;
+
+fail:
+    if (params != params_buf)
+        wasm_runtime_free(params);
+    if (results != results_buf)
+        wasm_runtime_free(results);
+    return ret;
+}

+ 6 - 0
core/iwasm/common/wasm_runtime_common.h

@@ -796,6 +796,12 @@ uint32
 wasm_runtime_get_memory_data_size(const WASMModuleInstanceCommon *module_inst_comm,
                                   uint32 memory_inst_idx);
 
+bool
+wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
+                                 void *func_ptr, WASMType *func_type,
+                                 uint32 argc, uint32 *argv,
+                                 bool with_env, void *wasm_c_api_env);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 0
core/iwasm/compilation/aot_llvm.c

@@ -1534,7 +1534,9 @@ aot_create_comp_context(AOTCompData *comp_data,
     LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);
     LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr);
     LLVMAddJumpThreadingPass(comp_ctx->pass_mgr);
+#if LLVM_VERSION_MAJOR < 12
     LLVMAddConstantPropagationPass(comp_ctx->pass_mgr);
+#endif
     LLVMAddIndVarSimplifyPass(comp_ctx->pass_mgr);
 
     if (!option->is_jit_mode) {

+ 1 - 0
core/iwasm/compilation/aot_llvm.h

@@ -7,6 +7,7 @@
 #define _AOT_LLVM_H_
 
 #include "aot.h"
+#include "llvm/Config/llvm-config.h"
 #include "llvm-c/Types.h"
 #include "llvm-c/Target.h"
 #include "llvm-c/Core.h"

+ 2 - 0
core/iwasm/interpreter/wasm.h

@@ -186,6 +186,8 @@ typedef struct WASMFunctionImport {
     WASMModule *import_module;
     WASMFunction *import_func_linked;
 #endif
+    bool call_conv_wasm_c_api;
+    bool wasm_c_api_with_env;
 } WASMFunctionImport;
 
 typedef struct WASMGlobalImport {

+ 12 - 1
core/iwasm/interpreter/wasm_interp_classic.c

@@ -753,7 +753,18 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
         return;
     }
 
-    if (!func_import->call_conv_raw) {
+    if (func_import->call_conv_wasm_c_api) {
+        ret = wasm_runtime_invoke_c_api_native(
+          (WASMModuleInstanceCommon *)module_inst,
+          func_import->func_ptr_linked, func_import->func_type,
+          cur_func->param_cell_num, frame->lp,
+          func_import->wasm_c_api_with_env, func_import->attachment);
+        if (ret) {
+            argv_ret[0] = frame->lp[0];
+            argv_ret[1] = frame->lp[1];
+        }
+    }
+    else if (!func_import->call_conv_raw) {
         ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked,
                                          func_import->func_type, func_import->signature,
                                          func_import->attachment,

+ 12 - 1
core/iwasm/interpreter/wasm_interp_fast.c

@@ -826,7 +826,18 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
         return;
     }
 
-    if (!func_import->call_conv_raw) {
+    if (func_import->call_conv_wasm_c_api) {
+        ret = wasm_runtime_invoke_c_api_native(
+          (WASMModuleInstanceCommon *)module_inst,
+          func_import->func_ptr_linked, func_import->func_type,
+          cur_func->param_cell_num, frame->lp,
+          func_import->wasm_c_api_with_env, func_import->attachment);
+        if (ret) {
+            argv_ret[0] = frame->lp[0];
+            argv_ret[1] = frame->lp[1];
+        }
+    }
+    else if (!func_import->call_conv_raw) {
         ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked,
                                          func_import->func_type, func_import->signature,
                                          func_import->attachment,

+ 7 - 17
core/iwasm/interpreter/wasm_loader.c

@@ -2304,7 +2304,7 @@ check_table_index(const WASMModule *module, uint32 table_index,
       !wasm_get_ref_types_flag() &&
 #endif
       table_index != 0) {
-        set_error_buf(error_buf, error_buf_size, "zero flag expected");
+        set_error_buf(error_buf, error_buf_size, "zero byte expected");
         return false;
     }
 
@@ -7472,13 +7472,8 @@ handle_op_block_and_loop:
                 CHECK_MEMORY();
                 /* reserved byte 0x00 */
                 if (*p++ != 0x00) {
-#if WASM_ENABLE_REF_TYPES != 0
                     set_error_buf(error_buf, error_buf_size,
                                   "zero byte expected");
-#else
-                    set_error_buf(error_buf, error_buf_size,
-                                  "zero flag expected");
-#endif
                     goto fail;
                 }
                 PUSH_I32();
@@ -7490,13 +7485,8 @@ handle_op_block_and_loop:
                 CHECK_MEMORY();
                 /* reserved byte 0x00 */
                 if (*p++ != 0x00) {
-#if WASM_ENABLE_REF_TYPES != 0
                     set_error_buf(error_buf, error_buf_size,
                                   "zero byte expected");
-#else
-                    set_error_buf(error_buf, error_buf_size,
-                                  "zero flag expected");
-#endif
                     goto fail;
                 }
                 POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
@@ -7811,7 +7801,7 @@ handle_op_block_and_loop:
                         goto fail_unknown_memory;
 
                     if (*p++ != 0x00)
-                        goto fail_zero_flag_expected;
+                        goto fail_zero_byte_expected;
 
                     if (data_seg_idx >= module->data_seg_count) {
                         set_error_buf_v(error_buf, error_buf_size,
@@ -7848,7 +7838,7 @@ handle_op_block_and_loop:
                 {
                     /* both src and dst memory index should be 0 */
                     if (*(int16*)p != 0x0000)
-                        goto fail_zero_flag_expected;
+                        goto fail_zero_byte_expected;
                     p += 2;
 
                     if (module->import_memory_count == 0 && module->memory_count == 0)
@@ -7862,7 +7852,7 @@ handle_op_block_and_loop:
                 case WASM_OP_MEMORY_FILL:
                 {
                     if (*p++ != 0x00) {
-                        goto fail_zero_flag_expected;
+                        goto fail_zero_byte_expected;
                     }
                     if (module->import_memory_count == 0 && module->memory_count == 0) {
                         goto fail_unknown_memory;
@@ -7872,9 +7862,9 @@ handle_op_block_and_loop:
                     POP_I32();
                     POP_I32();
                     break;
-fail_zero_flag_expected:
+fail_zero_byte_expected:
                     set_error_buf(error_buf, error_buf_size,
-                                  "zero flag expected");
+                                  "zero byte expected");
                     goto fail;
 
 fail_unknown_memory:
@@ -8460,7 +8450,7 @@ fail_data_cnt_sec_require:
                         /* reserved byte 0x00 */
                         if (*p++ != 0x00) {
                             set_error_buf(error_buf, error_buf_size,
-                                          "zero flag expected");
+                                          "zero byte expected");
                             goto fail;
                         }
                         break;

+ 9 - 11
samples/wasm-c-api/CMakeLists.txt

@@ -105,32 +105,30 @@ foreach(EX ${EXAMPLES})
   if (MSVC)
     target_compile_definitions(${EX} PRIVATE WASM_API_EXTERN=)
   endif()
-endforeach()
 
-# wat to wasm
-foreach(EX ${EXAMPLES})
-  set(SRC ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.wat)
+  # wat to wasm
+  set(WAT ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.wat)
 
-  add_custom_target(${EX}_WASM ALL
-    COMMAND ${WAT2WASM} ${SRC} -o ${PROJECT_BINARY_DIR}/${EX}.wasm
-    DEPENDS ${SRC}
+  add_custom_target(${EX}_WASM
+    COMMAND ${WAT2WASM} ${WAT} -o ${PROJECT_BINARY_DIR}/${EX}.wasm
+    DEPENDS ${WAT}
     BYPRODUCTS ${PROJECT_BINARY_DIR}/${EX}.wasm
     VERBATIM
-    SOURCES ${SRC}
   )
+  add_dependencies(${EX} ${EX}_WASM)
 
   # generate .aot file
   if(${WAMR_BUILD_AOT} EQUAL 1)
     if(EXISTS ${WAMRC})
-      add_custom_target(${EX}_AOT ALL
+      add_custom_target(${EX}_AOT
         COMMAND ${WAMRC} -o ${PROJECT_BINARY_DIR}/${EX}.aot
           ${PROJECT_BINARY_DIR}/${EX}.wasm
-        DEPENDS ${PROJECT_BINARY_DIR}/${EX}.wasm
+        DEPENDS ${EX}_WASM
         BYPRODUCTS ${PROJECT_BINARY_DIR}/${EX}.aot
         VERBATIM
-        SOURCES ${SRC}
         COMMENT "generate a aot file ${PROJECT_BINARY_DIR}/${EX}.aot"
       )
+      add_dependencies(${EX} ${EX}_AOT)
     endif()
   endif()
 endforeach()

+ 5 - 1
samples/wasm-c-api/src/callback_chain.c

@@ -83,7 +83,7 @@ DEFINE_FUNCTION(log)
         return NULL;
     }
 
-    if (data[length.of.i32]) {
+    if (data[length.of.i32 - 1]) {
         printf("> Error terminated character\n");
         return NULL;
     }
@@ -188,7 +188,11 @@ main(int argc, const char *argv[])
 
     // Load binary.
     printf("Loading binary...\n");
+#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
+    FILE *file = fopen("callback_chain.aot", "rb");
+#else
     FILE *file = fopen("callback_chain.wasm", "rb");
+#endif
     if (!file) {
         printf("> Error loading module!\n");
         return 1;

+ 25 - 1
samples/wasm-c-api/src/hello.c

@@ -56,15 +56,26 @@ int main(int argc, const char* argv[]) {
 
   wasm_byte_vec_delete(&binary);
 
+  // Create external print functions.
+  printf("Creating callback...\n");
+  own wasm_functype_t* hello_type = wasm_functype_new_0_0();
+  own wasm_func_t* hello_func =
+    wasm_func_new(store, hello_type, hello_callback);
+
+  wasm_functype_delete(hello_type);
+
   // Instantiate.
   printf("Instantiating module...\n");
+  const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) };
   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;
   }
 
+  wasm_func_delete(hello_func);
+
   // Extract export.
   printf("Extracting export...\n");
   own wasm_extern_vec_t exports;
@@ -74,9 +85,22 @@ int main(int argc, const char* argv[]) {
     return 1;
   }
 
+  const wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]);
+  if (run_func == NULL) {
+    printf("> Error accessing export!\n");
+    return 1;
+  }
+
   wasm_module_delete(module);
   wasm_instance_delete(instance);
 
+  // Call.
+  printf("Calling export...\n");
+  if (wasm_func_call(run_func, NULL, NULL)) {
+    printf("> Error calling function!\n");
+    return 1;
+  }
+
   wasm_extern_vec_delete(&exports);
 
   // Shut down.