Răsfoiți Sursa

Eable post-MVP feature wasm-c-api (#315)

lum1n0us 5 ani în urmă
părinte
comite
08d01b65c5

+ 3 - 3
README.md

@@ -1,6 +1,6 @@
 WebAssembly Micro Runtime
 =========================
-[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples-and-demos)
+[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples)
 
 **A [Bytecode Alliance][BA] project**
 
@@ -36,6 +36,7 @@ iwasm VM core
 - [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations)
 - [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory)
 - [Multi-value](https://github.com/WebAssembly/multi-value)
+- [wasm-c-api](https://github.com/WebAssembly/wasm-c-api)
 
 ### Performance and memory usage
 The WAMR performance, footprint and memory usage data are available at the [performance](../../wiki/Performance) wiki page.
@@ -112,8 +113,7 @@ The WAMR [samples](./samples) integrate the iwasm VM core, application manager a
 - **[Simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default.
 - **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application.  It uses **WASI libc** and executes apps in **AoT mode** by default.
 - **[gui](./samples/gui/README.md)**: Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default.
-
-
+- **[wasm-c-api](./samples/wasm-c-api/README.md)**: they are samples from [wasm-c-api proposal](https://github.com/WebAssembly/wasm-c-api) and show supported APIs.
 
 
 Releases and acknowledgments

+ 5 - 0
core/config.h

@@ -127,6 +127,11 @@ enum {
 /* WASM Interpreter labels-as-values feature */
 #define WASM_ENABLE_LABELS_AS_VALUES 1
 
+/* Enable fast interpreter or not */
+#ifndef WASM_ENABLE_FAST_INTERP
+#define WASM_ENABLE_FAST_INTERP 0
+#endif
+
 #if WASM_ENABLE_FAST_INTERP != 0
 #define WASM_ENABLE_ABS_LABEL_ADDR 1
 #define WASM_DEBUG_PREPROCESSOR 0

+ 2745 - 0
core/iwasm/common/wasm_c_api.c

@@ -0,0 +1,2745 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_c_api_internal.h"
+#include "wasm_memory.h"
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#define NOT_REACHED() bh_assert(!"should not be reached")
+
+typedef struct wasm_module_ex_t wasm_module_ex_t;
+
+void
+wasm_module_delete_internal(wasm_module_t *);
+
+void
+wasm_instance_delete_internal(wasm_instance_t *);
+
+static void *
+malloc_internal(size_t size)
+{
+    void *mem = NULL;
+
+    if (size >= UINT32_MAX) {
+        return NULL;
+    }
+
+    mem = wasm_runtime_malloc((uint32)size);
+    if (mem) {
+        memset(mem, 0, size);
+    }
+
+    return mem;
+}
+
+#define FREEIF(p)                                                             \
+    if (p) {                                                                  \
+        wasm_runtime_free(p);                                                 \
+    }
+
+/* Vectors */
+#define INIT_VEC(vector_p, func_prefix, size)                                 \
+    do {                                                                      \
+        vector_p = malloc_internal(sizeof(*(vector_p)));                      \
+        if (!vector_p) {                                                      \
+            goto failed;                                                      \
+        }                                                                     \
+        func_prefix##_new_uninitialized(vector_p, size);                      \
+        if (!(vector_p)->data) {                                              \
+            goto failed;                                                      \
+        }                                                                     \
+    } while (false)
+
+#define DEINIT_VEC(vector_p, delete_func)                                     \
+    if ((vector_p)) {                                                         \
+        if ((vector_p)->data) {                                               \
+            delete_func(vector_p);                                            \
+        }                                                                     \
+        wasm_runtime_free(vector_p);                                          \
+        vector_p = NULL;                                                      \
+    }
+
+#define FREE_VEC_ELEMS(vec, del_func)                                         \
+    for (i = 0; i < (vec)->num_elems; ++i) {                                  \
+        del_func(*((vec)->data + i));                                         \
+        *((vec)->data + i) = NULL;                                            \
+    }
+
+static inline void
+generic_vec_init_data(Vector *out, size_t num_of_elems, size_t size_of_elem)
+{
+    if (!bh_vector_init(out, num_of_elems, size_of_elem)) {
+        memset(out, 0, sizeof(Vector));
+    }
+    else {
+        memset(out->data, 0, num_of_elems * size_of_elem);
+    }
+}
+
+void
+wasm_byte_vec_new_uninitialized(wasm_byte_vec_t *out, size_t size)
+{
+    bh_assert(out);
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_byte_t));
+}
+
+void
+wasm_byte_vec_copy(wasm_byte_vec_t *out, const wasm_byte_vec_t *src)
+{
+    uint32 len = 0;
+
+    bh_assert(out && src);
+
+    generic_vec_init_data((Vector *)out, src->size, src->size_of_elem);
+    if (!out->data) {
+        goto failed;
+    }
+
+    len = src->size * src->size_of_elem;
+    bh_memcpy_s(out->data, len, src->data, len);
+    out->num_elems = src->num_elems;
+    return;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_byte_vec_delete(out);
+}
+
+void
+wasm_byte_vec_new(wasm_byte_vec_t *out, size_t size, const wasm_byte_t *data)
+{
+    size_t size_in_bytes = 0;
+
+    bh_assert(out && data);
+
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_byte_t));
+    if (!out->data) {
+        goto failed;
+    }
+
+    size_in_bytes = size * sizeof(wasm_byte_t);
+    bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes);
+    out->num_elems = size;
+    return;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_byte_vec_delete(out);
+}
+
+void
+wasm_byte_vec_delete(wasm_byte_vec_t *byte_vec)
+{
+    if (byte_vec && byte_vec->data) {
+        bh_vector_destroy((Vector *)byte_vec);
+    }
+}
+
+/* Runtime Environment */
+static void
+wasm_engine_delete_internal(wasm_engine_t *engine)
+{
+    if (engine) {
+        DEINIT_VEC(engine->stores, wasm_store_vec_delete);
+        wasm_runtime_free(engine);
+    }
+
+    wasm_runtime_destroy();
+}
+
+static wasm_engine_t *
+wasm_engine_new_internal(mem_alloc_type_t type,
+                         const MemAllocOption *opts,
+                         runtime_mode_e mode)
+{
+    wasm_engine_t *engine = NULL;
+    /* init runtime */
+    RuntimeInitArgs init_args = { 0 };
+    init_args.mem_alloc_type = type;
+
+    if (type == Alloc_With_Pool) {
+        init_args.mem_alloc_option.pool.heap_buf = opts->pool.heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = opts->pool.heap_size;
+    }
+    else if (type == Alloc_With_Allocator) {
+        init_args.mem_alloc_option.allocator.malloc_func =
+          opts->allocator.malloc_func;
+        init_args.mem_alloc_option.allocator.free_func =
+          opts->allocator.free_func;
+        init_args.mem_alloc_option.allocator.realloc_func =
+          opts->allocator.realloc_func;
+    }
+    else {
+        init_args.mem_alloc_option.pool.heap_buf = NULL;
+        init_args.mem_alloc_option.pool.heap_size = 0;
+    }
+
+    if (!wasm_runtime_full_init(&init_args)) {
+        goto failed;
+    }
+
+#if BH_DEBUG == 1
+    bh_log_set_verbose_level(5);
+#else
+    bh_log_set_verbose_level(3);
+#endif
+
+    /* create wasm_engine_t */
+    engine = malloc_internal(sizeof(wasm_engine_t));
+    if (!engine) {
+        goto failed;
+    }
+
+    /* set running mode */
+    LOG_WARNING("running under mode %d", mode);
+    engine->mode = mode;
+
+    /* create wasm_store_vec_t */
+    INIT_VEC(engine->stores, wasm_store_vec, 1);
+
+    return engine;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_engine_delete_internal(engine);
+    return NULL;
+}
+
+/* global engine instance */
+static wasm_engine_t *singleton_engine = NULL;
+
+static inline runtime_mode_e
+current_runtime_mode()
+{
+    bh_assert(singleton_engine);
+    return singleton_engine->mode;
+}
+
+wasm_engine_t *
+wasm_engine_new()
+{
+    runtime_mode_e mode = INTERP_MODE;
+#if WASM_ENABLE_INTERP == 0 && WASM_ENABLE_AOT != 0
+    mode = AOT_MODE;
+#endif
+
+    if (INTERP_MODE == mode) {
+#if WASM_ENABLE_INTERP == 0
+        bh_assert(!"does not support INTERP_MODE. Please recompile");
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT == 0
+        bh_assert(!"does not support AOT_MODE. Please recompile");
+#endif
+    }
+
+    if (!singleton_engine) {
+        singleton_engine =
+          wasm_engine_new_internal(Alloc_With_System_Allocator, NULL, mode);
+    }
+    return singleton_engine;
+}
+
+wasm_engine_t *
+wasm_engine_new_with_args(mem_alloc_type_t type,
+                          const MemAllocOption *opts,
+                          runtime_mode_e mode)
+{
+    if (!singleton_engine) {
+        singleton_engine = wasm_engine_new_internal(type, opts, mode);
+    }
+    return singleton_engine;
+}
+
+void
+wasm_engine_delete(wasm_engine_t *engine)
+{
+    if (engine) {
+        wasm_engine_delete_internal(engine);
+        singleton_engine = NULL;
+    }
+}
+
+wasm_store_t *
+wasm_store_new(wasm_engine_t *engine)
+{
+    wasm_store_t *store = NULL;
+
+    bh_assert(engine && singleton_engine == engine);
+
+    /* always return the first store */
+    if (bh_vector_size((Vector *)singleton_engine->stores) > 0) {
+        /*
+         * although it is a copy of the first store, but still point to
+         * the wasm_store_t
+         */
+        if (!bh_vector_get((Vector *)singleton_engine->stores, 0, &store)) {
+            goto failed;
+        }
+        return store;
+    }
+
+    store = malloc_internal(sizeof(wasm_store_t));
+    if (!store) {
+        goto failed;
+    }
+
+    /* new a vector, and new its data */
+    INIT_VEC(store->modules, wasm_module_vec, DEFAULT_VECTOR_INIT_LENGTH);
+    INIT_VEC(store->instances, wasm_instance_vec, DEFAULT_VECTOR_INIT_LENGTH);
+
+    /* append to a store list of engine */
+    if (!bh_vector_append((Vector *)singleton_engine->stores, &store)) {
+        goto failed;
+    }
+
+    return store;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_store_delete(store);
+    return NULL;
+}
+
+void
+wasm_store_delete(wasm_store_t *store)
+{
+    if (!store || singleton_engine->stores->num_elems == 0) {
+        return;
+    }
+
+    DEINIT_VEC(store->modules, wasm_module_vec_delete);
+    DEINIT_VEC(store->instances, wasm_instance_vec_delete);
+
+    wasm_runtime_free(store);
+    bh_vector_remove((Vector *)singleton_engine->stores, 0, NULL);
+}
+
+void
+wasm_store_vec_new_uninitialized(wasm_store_vec_t *out, size_t size)
+{
+    bh_assert(out);
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_store_t *));
+}
+
+void
+wasm_store_vec_delete(wasm_store_vec_t *store_vec)
+{
+    size_t i = 0;
+    if (!store_vec || !store_vec->data) {
+        return;
+    }
+
+    FREE_VEC_ELEMS(store_vec, wasm_store_delete);
+    bh_vector_destroy((Vector *)store_vec);
+}
+
+static inline void
+check_engine_and_store(wasm_engine_t *engine, wasm_store_t *store)
+{
+    /* remove it if we are supporting more than one store */
+    bh_assert(engine && store && engine->stores->data[0] == store);
+}
+
+/* Type Representations */
+static wasm_valtype_t *
+wasm_valtype_new_internal(uint8 val_type_rt)
+{
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            return wasm_valtype_new_i32();
+        case VALUE_TYPE_I64:
+            return wasm_valtype_new_i64();
+        case VALUE_TYPE_F32:
+            return wasm_valtype_new_f32();
+        case VALUE_TYPE_F64:
+            return wasm_valtype_new_f64();
+        case VALUE_TYPE_ANY:
+            return wasm_valtype_new_anyref();
+        default:
+            return NULL;
+    }
+}
+
+wasm_valtype_t *
+wasm_valtype_new(wasm_valkind_t kind)
+{
+    wasm_valtype_t *val_type = malloc_internal(sizeof(wasm_valtype_t));
+    if (val_type) {
+        val_type->kind = kind;
+    }
+    return val_type;
+}
+
+void
+wasm_valtype_delete(wasm_valtype_t *val_type)
+{
+    bh_assert(val_type);
+    wasm_runtime_free(val_type);
+}
+
+wasm_valtype_t *
+wasm_valtype_copy(wasm_valtype_t *src)
+{
+    bh_assert(src);
+    return wasm_valtype_new(src->kind);
+}
+
+wasm_valkind_t
+wasm_valtype_kind(const wasm_valtype_t *val_type)
+{
+    bh_assert(val_type);
+    return val_type->kind;
+}
+
+bool
+wasm_valtype_same(const wasm_valtype_t *vt1, const wasm_valtype_t *vt2)
+{
+    if (!vt1 && !vt2) {
+        return true;
+    }
+
+    if (!vt1 || !vt2) {
+        return false;
+    }
+
+    return vt1->kind == vt2->kind;
+}
+
+void
+wasm_valtype_vec_new_uninitialized(wasm_valtype_vec_t *out, size_t size)
+{
+    bh_assert(out);
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_valtype_t *));
+}
+
+void
+wasm_valtype_vec_new_empty(wasm_valtype_vec_t *out)
+{
+    bh_assert(out);
+    memset(out, 0, sizeof(wasm_valtype_vec_t));
+}
+
+void
+wasm_valtype_vec_new(wasm_valtype_vec_t *out,
+                     size_t size,
+                     wasm_valtype_t *const data[])
+{
+    size_t size_in_bytes = 0;
+    bh_assert(out && data);
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_valtype_t *));
+    if (!out->data) {
+        goto failed;
+    }
+
+    size_in_bytes = size * sizeof(wasm_valtype_t *);
+    bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes);
+    out->num_elems = size;
+    return;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_valtype_vec_delete(out);
+}
+
+void
+wasm_valtype_vec_copy(wasm_valtype_vec_t *out, const wasm_valtype_vec_t *src)
+{
+    size_t i = 0;
+
+    bh_assert(out && src);
+
+    generic_vec_init_data((Vector *)out, src->size, src->size_of_elem);
+    if (!out->data) {
+        goto failed;
+    }
+
+    /* clone every wasm_valtype_t */
+    for (i = 0; i < src->num_elems; i++) {
+        wasm_valtype_t *cloned = wasm_valtype_copy(*(src->data + i));
+        if (!cloned) {
+            goto failed;
+        }
+        if (!bh_vector_append((Vector *)out, &cloned)) {
+            goto failed;
+        }
+    }
+
+    return;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_valtype_vec_delete(out);
+}
+
+void
+wasm_valtype_vec_delete(wasm_valtype_vec_t *val_type_vec)
+{
+    size_t i = 0;
+    if (!val_type_vec || !val_type_vec->data) {
+        return;
+    }
+
+    FREE_VEC_ELEMS(val_type_vec, wasm_valtype_delete);
+    bh_vector_destroy((Vector *)val_type_vec);
+}
+
+static wasm_functype_t *
+wasm_functype_new_internal(WASMType *type_rt)
+{
+    wasm_functype_t *func_type = NULL;
+    uint32 i = 0;
+
+    bh_assert(type_rt);
+
+    func_type = malloc_internal(sizeof(wasm_functype_t));
+    if (!func_type) {
+        goto failed;
+    }
+
+    /* WASMType->types[0 : type_rt->param_count) -> func_type->params */
+    INIT_VEC(func_type->params, wasm_valtype_vec, type_rt->param_count);
+    for (i = 0; i < type_rt->param_count; ++i) {
+        wasm_valtype_t *param_type =
+          wasm_valtype_new_internal(*(type_rt->types + i));
+        if (!param_type) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)func_type->params, &param_type)) {
+            goto failed;
+        }
+    }
+
+    /* WASMType->types[type_rt->param_count : type_rt->result_count) -> func_type->results */
+    INIT_VEC(func_type->results, wasm_valtype_vec, type_rt->result_count);
+    for (i = type_rt->param_count; i < type_rt->result_count; ++i) {
+        wasm_valtype_t *result_type =
+          wasm_valtype_new_internal(*(type_rt->types + i));
+        if (!result_type) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)func_type->results, &result_type)) {
+            goto failed;
+        }
+    }
+
+    return func_type;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_functype_delete(func_type);
+    return NULL;
+}
+
+wasm_functype_t *
+wasm_functype_new(wasm_valtype_vec_t *params, wasm_valtype_vec_t *results)
+{
+    wasm_functype_t *func_type = NULL;
+
+    bh_assert(params);
+    bh_assert(results);
+
+    func_type = malloc_internal(sizeof(wasm_functype_t));
+    if (!func_type) {
+        goto failed;
+    }
+
+    func_type->extern_kind = WASM_EXTERN_FUNC;
+
+    func_type->params = malloc_internal(sizeof(wasm_valtype_vec_t));
+    if (!func_type->params) {
+        goto failed;
+    }
+
+    /* transfer ownership of contents of params and results */
+    bh_memcpy_s(func_type->params, sizeof(wasm_valtype_vec_t), params,
+                sizeof(wasm_valtype_vec_t));
+
+    func_type->results = malloc_internal(sizeof(wasm_valtype_vec_t));
+    if (!func_type->results) {
+        goto failed;
+    }
+
+    bh_memcpy_s(func_type->results, sizeof(wasm_valtype_vec_t), results,
+                sizeof(wasm_valtype_vec_t));
+
+    return func_type;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    FREEIF(func_type->params);
+    FREEIF(func_type->results);
+    FREEIF(func_type);
+    return NULL;
+}
+
+wasm_functype_t *
+wasm_functype_copy(wasm_functype_t *src)
+{
+    wasm_functype_t *dst = NULL;
+
+    bh_assert(src);
+
+    dst = malloc_internal(sizeof(wasm_functype_t));
+    if (!dst) {
+        goto failed;
+    }
+
+    dst->extern_kind = src->extern_kind;
+
+    dst->params = malloc_internal(sizeof(wasm_valtype_vec_t));
+    if (!dst->params) {
+        goto failed;
+    }
+
+    wasm_valtype_vec_copy(dst->params, src->params);
+    if (!dst->params) {
+        goto failed;
+    }
+
+    dst->results = malloc_internal(sizeof(wasm_valtype_vec_t));
+    if (!dst->results) {
+        goto failed;
+    }
+
+    wasm_valtype_vec_copy(dst->results, src->results);
+    if (!dst->results) {
+        goto failed;
+    }
+
+    return dst;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_functype_delete(dst);
+    return NULL;
+}
+
+void
+wasm_functype_delete(wasm_functype_t *func_type)
+{
+    if (!func_type) {
+        return;
+    }
+
+    if (func_type->params) {
+        wasm_valtype_vec_delete(func_type->params);
+        wasm_runtime_free(func_type->params);
+        func_type->params = NULL;
+    }
+
+    if (func_type->results) {
+        wasm_valtype_vec_delete(func_type->results);
+        wasm_runtime_free(func_type->results);
+        func_type->results = NULL;
+    }
+
+    wasm_runtime_free(func_type);
+}
+
+const wasm_valtype_vec_t *
+wasm_functype_params(const wasm_functype_t *func_type)
+{
+    bh_assert(func_type);
+    return func_type->params;
+}
+
+const wasm_valtype_vec_t *
+wasm_functype_results(const wasm_functype_t *func_type)
+{
+    bh_assert(func_type);
+    return func_type->results;
+}
+
+wasm_globaltype_t *
+wasm_globaltype_new(wasm_valtype_t *val_type, wasm_mutability_t mut)
+{
+    wasm_globaltype_t *global_type = NULL;
+
+    bh_assert(val_type);
+
+    global_type = malloc_internal(sizeof(wasm_globaltype_t));
+    if (!global_type) {
+        goto failed;
+    }
+
+    global_type->val_type = val_type;
+    global_type->mutability = mut;
+
+    return global_type;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_globaltype_delete(global_type);
+    return NULL;
+}
+
+wasm_globaltype_t *
+wasm_globaltype_new_internal(uint8 val_type_rt, bool is_mutable)
+{
+    wasm_globaltype_t *global_type = NULL;
+
+    global_type = malloc_internal(sizeof(wasm_globaltype_t));
+    if (!global_type) {
+        goto failed;
+    }
+
+    global_type->val_type = wasm_valtype_new_internal(val_type_rt);
+    if (!global_type->val_type) {
+        goto failed;
+    }
+
+    global_type->mutability = is_mutable ? WASM_VAR : WASM_CONST;
+
+    return global_type;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_globaltype_delete(global_type);
+    return NULL;
+}
+
+void
+wasm_globaltype_delete(wasm_globaltype_t *global_type)
+{
+    if (!global_type) {
+        return;
+    }
+
+    if (global_type->val_type) {
+        wasm_valtype_delete(global_type->val_type);
+        global_type->val_type = NULL;
+    }
+
+    wasm_runtime_free(global_type);
+}
+
+wasm_globaltype_t *
+wasm_globaltype_copy(wasm_globaltype_t *src)
+{
+    wasm_globaltype_t *dst = NULL;
+
+    bh_assert(src);
+
+    dst = malloc_internal(sizeof(wasm_globaltype_t));
+    if (!dst) {
+        goto failed;
+    }
+
+    dst->val_type = wasm_valtype_copy(src->val_type);
+    if (!dst->val_type) {
+        goto failed;
+    }
+
+    dst->mutability = src->mutability;
+
+    return dst;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_globaltype_delete(dst);
+    return NULL;
+}
+
+const wasm_valtype_t *
+wasm_globaltype_content(const wasm_globaltype_t *global_type)
+{
+    bh_assert(global_type);
+    return global_type->val_type;
+}
+
+wasm_mutability_t
+wasm_globaltype_mutability(const wasm_globaltype_t *global_type)
+{
+    bh_assert(global_type);
+    return global_type->mutability;
+}
+
+bool
+wasm_globaltype_same(const wasm_globaltype_t *gt1,
+                     const wasm_globaltype_t *gt2)
+{
+    if (!gt1 && !gt2) {
+        return true;
+    }
+
+    if (!gt1 || !gt2) {
+        return false;
+    }
+
+    return wasm_valtype_same(gt1->val_type, gt2->val_type)
+           || gt1->mutability == gt2->mutability;
+}
+
+wasm_tabletype_t *
+wasm_tabletype_new(wasm_valtype_t *val_type, const wasm_limits_t *limits)
+{
+    return NULL;
+}
+
+void
+wasm_tabletype_delete(wasm_tabletype_t *table_type)
+{}
+
+wasm_memorytype_t *
+wasm_memorytype_new(const wasm_limits_t *limits)
+{
+    return NULL;
+}
+
+void
+wasm_memorytype_delete(wasm_memorytype_t *memory_type)
+{}
+
+/* Runtime Objects */
+
+void
+wasm_val_delete(wasm_val_t *v)
+{
+    /* do nothing */
+}
+
+void
+wasm_val_copy(wasm_val_t *out, const wasm_val_t *src)
+{
+    bh_assert(out && src);
+    bh_memcpy_s(out, sizeof(wasm_val_t), src, sizeof(wasm_val_t));
+}
+
+bool
+wasm_val_same(const wasm_val_t *v1, const wasm_val_t *v2)
+{
+    if (!v1 && !v2) {
+        return true;
+    }
+
+    if (!v1 || !v2) {
+        return false;
+    }
+
+    if (v1->kind != v2->kind) {
+        return false;
+    }
+
+    switch (v1->kind) {
+        case WASM_I32:
+            return v1->of.i32 == v2->of.i32;
+        case WASM_I64:
+            return v1->of.i64 == v2->of.i64;
+        case WASM_F32:
+            return v1->of.f32 == v2->of.f32;
+        case WASM_F64:
+            return v1->of.f64 == v2->of.f64;
+        case WASM_FUNCREF:
+            return v1->of.ref == v2->of.ref;
+        default:
+            break;
+    }
+    return false;
+}
+
+wasm_trap_t *
+wasm_trap_new(wasm_store_t *store, const wasm_message_t *message)
+{
+    wasm_trap_t *trap;
+
+    bh_assert(store && message);
+
+    trap = malloc_internal(sizeof(wasm_trap_t));
+    if (!trap) {
+        goto failed;
+    }
+
+    wasm_byte_vec_new(trap->message, message->num_elems, message->data);
+    if (!trap->message->data) {
+        goto failed;
+    }
+
+    return trap;
+
+failed:
+    wasm_trap_delete(trap);
+    return NULL;
+}
+
+void
+wasm_trap_delete(wasm_trap_t *trap)
+{
+    if (!trap) {
+        return;
+    }
+
+    if (trap->message) {
+        wasm_byte_vec_delete(trap->message);
+    }
+
+    wasm_runtime_free(trap);
+}
+
+void
+wasm_trap_message(const wasm_trap_t *trap, wasm_message_t *out)
+{
+    bh_assert(trap && out);
+    wasm_byte_vec_copy(out, trap->message);
+}
+
+struct wasm_module_ex_t {
+    struct WASMModuleCommon *module_comm_rt;
+    wasm_byte_vec_t *binary;
+};
+
+static inline wasm_module_t *
+module_ext_to_module(wasm_module_ex_t *module_ex)
+{
+    return (wasm_module_t *)module_ex;
+}
+
+static inline wasm_module_ex_t *
+module_to_module_ext(wasm_module_t *module)
+{
+    return (wasm_module_ex_t *)module;
+}
+
+wasm_module_t *
+wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
+{
+    char error[128] = { 0 };
+    wasm_module_ex_t *module_ex = NULL;
+    PackageType pkg_type = Package_Type_Unknown;
+
+    check_engine_and_store(singleton_engine, store);
+    bh_assert(binary && binary->data && binary->size);
+
+    pkg_type = get_package_type((uint8 *)binary->data, binary->size);
+    if (Package_Type_Unknown == pkg_type
+        || (Wasm_Module_Bytecode == pkg_type
+            && INTERP_MODE != current_runtime_mode())
+        || (Wasm_Module_AoT == pkg_type
+            && INTERP_MODE == current_runtime_mode())) {
+        LOG_WARNING(
+          "current runtime mode %d doesn\'t support the package type "
+          "%d",
+          current_runtime_mode(), pkg_type);
+        goto failed;
+    }
+
+    module_ex = malloc_internal(sizeof(wasm_module_ex_t));
+    if (!module_ex) {
+        goto failed;
+    }
+
+    module_ex->binary = malloc_internal(sizeof(wasm_byte_vec_t));
+    if (!module_ex->binary) {
+        goto failed;
+    }
+
+    wasm_byte_vec_copy(module_ex->binary, binary);
+    if (!module_ex->binary->data) {
+        goto failed;
+    }
+
+    module_ex->module_comm_rt =
+      wasm_runtime_load((uint8 *)module_ex->binary->data,
+                        module_ex->binary->size, error, (uint32)sizeof(error));
+    if (!(module_ex->module_comm_rt)) {
+        LOG_ERROR(error);
+        goto failed;
+    }
+
+    /* add it to a watching list in store */
+    if (!bh_vector_append((Vector *)store->modules, &module_ex)) {
+        goto failed;
+    }
+
+    return module_ext_to_module(module_ex);
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_module_delete_internal(module_ext_to_module(module_ex));
+    return NULL;
+}
+
+void
+wasm_module_delete_internal(wasm_module_t *module)
+{
+    wasm_module_ex_t *module_ex;
+    if (!module) {
+        return;
+    }
+
+    module_ex = module_to_module_ext(module);
+    if (module_ex->binary) {
+        wasm_byte_vec_delete(module_ex->binary);
+        wasm_runtime_free(module_ex->binary);
+        module_ex->binary = NULL;
+    }
+
+    if (module_ex->module_comm_rt) {
+        wasm_runtime_unload(module_ex->module_comm_rt);
+        module_ex->module_comm_rt = NULL;
+    }
+
+    wasm_runtime_free(module_ex);
+}
+
+/* will release module when releasing the store */
+void
+wasm_module_delete(wasm_module_t *module)
+{
+    /* pass */
+}
+
+void
+wasm_module_vec_new_uninitialized(wasm_module_vec_t *out, size_t size)
+{
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_module_t *));
+}
+
+void
+wasm_module_vec_delete(wasm_module_vec_t *module_vec)
+{
+    size_t i = 0;
+    if (!module_vec || !module_vec->data) {
+        return;
+    }
+
+    FREE_VEC_ELEMS(module_vec, wasm_module_delete_internal);
+    bh_vector_destroy((Vector *)module_vec);
+}
+
+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;
+    void *argv_p = (void *)argv;
+
+    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_p;
+                argv_p = (uint32 *)argv_p + 1;
+                argc++;
+                break;
+            case WASM_I64:
+                param->kind = WASM_I64;
+                param->of.i64 = *(uint64 *)argv_p;
+                argv_p = (uint64 *)argv_p + 1;
+                argc++;
+                break;
+            case WASM_F32:
+                param->kind = WASM_F32;
+                param->of.f32 = *(float32 *)argv_p;
+                argv_p = (float32 *)argv_p + 1;
+                argc++;
+                break;
+            case WASM_F64:
+                param->kind = WASM_F64;
+                param->of.f64 = *(float64 *)argv_p;
+                argv_p = (float64 *)argv_p + 1;
+                argc++;
+                break;
+            default:
+                NOT_REACHED();
+                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;
+    void *argv_p = out;
+
+    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:
+                *(uint32 *)argv_p = result->of.i32;
+                argv_p = (uint32 *)argv_p + 1;
+                argc++;
+                break;
+            case WASM_I64:
+                *(uint64 *)argv_p = result->of.i64;
+                argv_p = (uint64 *)argv_p + 1;
+                argc++;
+                break;
+            case WASM_F32:
+                *(float32 *)argv_p = result->of.f32;
+                argv_p = (float32 *)argv_p + 1;
+                argc++;
+                break;
+            case WASM_F64:
+                *(float64 *)argv_p = result->of.f64;
+                argv_p = (float64 *)argv_p + 1;
+                argc++;
+                break;
+            default:
+                NOT_REACHED();
+                goto failed;
+        }
+    }
+
+    return argc;
+failed:
+    return 0;
+}
+
+static void
+native_func_trampoline(wasm_exec_env_t exec_env, uint64 *argv)
+{
+    wasm_val_t *params = NULL;
+    wasm_val_t *results = NULL;
+    uint32 argc = 0;
+    const wasm_func_t *func = NULL;
+    wasm_trap_t *trap = NULL;
+
+    bh_assert(argv);
+
+    func = wasm_runtime_get_function_attachment(exec_env);
+    bh_assert(func);
+
+    params = malloc_internal(wasm_func_param_arity(func) * sizeof(wasm_val_t));
+    if (!params) {
+        goto failed;
+    }
+
+    results =
+      malloc_internal(wasm_func_result_arity(func) * sizeof(wasm_val_t));
+    if (!results) {
+        goto failed;
+    }
+
+    /* argv -> const wasm_val_t params[] */
+    argc =
+      argv_to_params(argv, wasm_functype_params(wasm_func_type(func)), params);
+    if (wasm_func_param_arity(func) && !argc) {
+        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_name_t *message = NULL;
+        wasm_trap_message(trap, message);
+        LOG_WARNING("got a trap %s", message->data);
+        wasm_name_delete(message);
+    }
+
+    /* there is no result or there is an exception */
+    if (trap || !wasm_func_result_arity(func)) {
+        memset(argv, 0, wasm_func_param_arity(func) * sizeof(uint64));
+    }
+
+    /* wasm_val_t results[] -> argv */
+    argc = results_to_argv(results,
+                           wasm_functype_results(wasm_func_type(func)), argv);
+    if (wasm_func_result_arity(func) && !argc) {
+        goto failed;
+    }
+
+failed:
+    FREEIF(params);
+    FREEIF(results);
+    return;
+}
+
+wasm_func_t *
+wasm_func_new(wasm_store_t *store,
+              const wasm_functype_t *func_type,
+              wasm_func_callback_t callback)
+{
+    wasm_func_t *func = NULL;
+
+    check_engine_and_store(singleton_engine, store);
+    bh_assert(func_type);
+
+    func = malloc_internal(sizeof(wasm_func_t));
+    if (!func) {
+        goto failed;
+    }
+
+    func->kind = WASM_EXTERN_FUNC;
+    func->with_env = false;
+    func->u.cb = callback;
+
+    func->func_type = wasm_functype_copy((wasm_functype_t *)func_type);
+    if (!func->func_type) {
+        goto failed;
+    }
+
+    return func;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_func_delete(func);
+    return NULL;
+}
+
+wasm_func_t *
+wasm_func_new_with_env(wasm_store_t *store,
+                       const wasm_functype_t *func_type,
+                       wasm_func_callback_with_env_t callback,
+                       void *env,
+                       void (*finalizer)(void *))
+{
+    wasm_func_t *func = NULL;
+
+    check_engine_and_store(singleton_engine, store);
+    bh_assert(func_type);
+
+    func = malloc_internal(sizeof(wasm_func_t));
+    if (!func) {
+        goto failed;
+    }
+
+    func->kind = WASM_EXTERN_FUNC;
+    func->with_env = true;
+    func->u.cb_env.cb = callback;
+    func->u.cb_env.env = env;
+    func->u.cb_env.finalizer = finalizer;
+
+    func->func_type = wasm_functype_copy((wasm_functype_t *)func_type);
+    if (!func->func_type) {
+        goto failed;
+    }
+
+    return func;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_func_delete(func);
+    return NULL;
+}
+
+static wasm_func_t *
+wasm_func_new_internal(wasm_store_t *store,
+                       uint16 func_idx_rt,
+                       WASMModuleInstanceCommon *inst_comm_rt)
+{
+    wasm_func_t *func = NULL;
+    WASMType *type_rt = NULL;
+
+    check_engine_and_store(singleton_engine, store);
+    bh_assert(inst_comm_rt);
+
+    func = malloc_internal(sizeof(wasm_func_t));
+    if (!func) {
+        goto failed;
+    }
+
+    func->kind = WASM_EXTERN_FUNC;
+
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        bh_assert(func_idx_rt
+                  < ((WASMModuleInstance *)inst_comm_rt)->function_count);
+        WASMFunctionInstance *func_interp =
+          ((WASMModuleInstance *)inst_comm_rt)->functions + func_idx_rt;
+        type_rt = func_interp->is_import_func
+                    ? func_interp->u.func_import->func_type
+                    : func_interp->u.func->func_type;
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        /* use same index to trace the function type in AOTFuncType **func_types */
+        AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+        AOTFunctionInstance *func_aot =
+          (AOTFunctionInstance *)inst_aot->export_funcs.ptr + func_idx_rt;
+        type_rt = func_aot->is_import_func ? func_aot->u.func_import->func_type
+                                           : func_aot->u.func.func_type;
+#endif
+    }
+
+    if (!type_rt) {
+        goto failed;
+    }
+
+    func->func_type = wasm_functype_new_internal(type_rt);
+    if (!func->func_type) {
+        goto failed;
+    }
+
+    /* will add name information when processing "exports" */
+    func->module_name = NULL;
+    func->name = NULL;
+    func->func_idx_rt = func_idx_rt;
+    func->inst_comm_rt = inst_comm_rt;
+    return func;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_func_delete(func);
+    return NULL;
+}
+
+void
+wasm_func_delete(wasm_func_t *func)
+{
+    if (!func) {
+        return;
+    }
+
+    if (func->func_type) {
+        wasm_functype_delete(func->func_type);
+        func->func_type = NULL;
+    }
+
+    if (func->with_env) {
+        if (func->u.cb_env.finalizer) {
+            func->u.cb_env.finalizer(func->u.cb_env.env);
+            func->u.cb_env.finalizer = NULL;
+            func->u.cb_env.env = NULL;
+        }
+    }
+
+    wasm_runtime_free(func);
+}
+
+wasm_func_t *
+wasm_func_copy(const wasm_func_t *func)
+{
+    wasm_func_t *cloned = NULL;
+
+    bh_assert(func);
+
+    cloned = malloc_internal(sizeof(wasm_func_t));
+    if (!cloned) {
+        goto failed;
+    }
+
+    cloned->kind = func->kind;
+    cloned->with_env = func->with_env;
+    if (cloned->with_env) {
+        cloned->u.cb_env.cb = func->u.cb_env.cb;
+        cloned->u.cb_env.env = func->u.cb_env.env;
+        cloned->u.cb_env.finalizer = func->u.cb_env.finalizer;
+    }
+    else {
+        cloned->u.cb = func->u.cb;
+    }
+
+    cloned->func_idx_rt = func->func_idx_rt;
+    cloned->inst_comm_rt = func->inst_comm_rt;
+    cloned->func_type = wasm_functype_copy(func->func_type);
+    if (!cloned->func_type) {
+        goto failed;
+    }
+
+    return cloned;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_func_delete(cloned);
+    return NULL;
+}
+
+wasm_functype_t *
+wasm_func_type(const wasm_func_t *func)
+{
+    bh_assert(func);
+    return func->func_type;
+}
+
+static uint32
+params_to_argv(const wasm_val_t *params,
+               const wasm_valtype_vec_t *param_defs,
+               size_t param_arity,
+               uint32 *out)
+{
+    size_t i = 0;
+    uint32 argc = 0;
+    const wasm_val_t *param = NULL;
+
+    if (!param_arity) {
+        return 0;
+    }
+
+    bh_assert(params && param_defs && out);
+    bh_assert(param_defs->num_elems == param_arity);
+
+    for (i = 0; out && i < param_arity; ++i) {
+        param = params + 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;
+                break;
+            case WASM_I64:
+                *(int64 *)out = param->of.i64;
+                out += 2;
+                argc += 2;
+                break;
+            case WASM_F32:
+                *(float32 *)out = param->of.f32;
+                out += 1;
+                argc += 1;
+                break;
+            case WASM_F64:
+                *(float64 *)out = param->of.f64;
+                out += 2;
+                argc += 2;
+                break;
+            default:
+                LOG_DEBUG("unexpected parameter val type %d", param->kind);
+                goto failed;
+        }
+    }
+
+    return argc;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return 0;
+}
+
+static uint32
+argv_to_results(const uint32 *results,
+                const wasm_valtype_vec_t *result_defs,
+                size_t result_arity,
+                wasm_val_t *out)
+{
+    size_t i = 0;
+    uint32 argc = 0;
+    const uint32 *result = results;
+    const wasm_valtype_t *def = NULL;
+
+    if (!result_arity) {
+        return 0;
+    }
+
+    bh_assert(results && result_defs && out);
+    bh_assert(result_arity == result_defs->num_elems);
+
+    for (i = 0; out && i < result_arity; i++) {
+        def = *(result_defs->data + i);
+
+        switch (def->kind) {
+            case WASM_I32:
+                out->kind = WASM_I32;
+                out->of.i32 = *(int32 *)result;
+                result += 1;
+                break;
+            case WASM_I64:
+                out->kind = WASM_I64;
+                out->of.i64 = *(int64 *)result;
+                result += 2;
+                break;
+            case WASM_F32:
+                out->kind = WASM_F32;
+                out->of.f32 = *(float32 *)result;
+                result += 1;
+                break;
+            case WASM_F64:
+                out->kind = WASM_F64;
+                out->of.f64 = *(float64 *)result;
+                result += 2;
+                break;
+            default:
+                LOG_DEBUG("unexpected parameter val type %d", def->kind);
+                goto failed;
+        }
+        out++;
+        argc++;
+    }
+
+    return argc;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return 0;
+}
+
+wasm_trap_t *
+wasm_func_call(const wasm_func_t *func,
+               const wasm_val_t params[],
+               wasm_val_t results[])
+{
+    /* parameters count as if all are uint32 */
+    /* a int64 or float64 parameter means 2 */
+    uint32 argc = 0;
+    /* a parameter list and a return value list */
+    uint32 *argv = NULL;
+    WASMFunctionInstanceCommon *func_comm_rt = NULL;
+    size_t param_count = 0;
+    size_t result_count = 0;
+
+    bh_assert(func && func->func_type && func->inst_comm_rt);
+
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->functions
+                       + func->func_idx_rt;
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        AOTModuleInstance *inst_aot = (AOTModuleInstance *)func->inst_comm_rt;
+        func_comm_rt = (AOTFunctionInstance *)inst_aot->export_funcs.ptr
+                       + func->func_idx_rt;
+#endif
+    }
+    if (!func_comm_rt) {
+        goto failed;
+    }
+
+    param_count = wasm_func_param_arity(func);
+    result_count = wasm_func_result_arity(func);
+    argv = malloc_internal(
+      sizeof(uint64)
+      * (param_count > result_count ? param_count : result_count));
+    if (!argv) {
+        goto failed;
+    }
+
+    /* copy parametes */
+    argc = params_to_argv(params, wasm_functype_params(wasm_func_type(func)),
+                          wasm_func_param_arity(func), argv);
+    if (wasm_func_param_arity(func) && !argc) {
+        goto failed;
+    }
+
+    if (!wasm_runtime_create_exec_env_and_call_wasm(
+          func->inst_comm_rt, func_comm_rt, argc, argv)) {
+        LOG_DEBUG("wasm_runtime_create_exec_env_and_call_wasm failed");
+        goto failed;
+    }
+
+    /* copy results */
+    argc = argv_to_results(argv, wasm_functype_results(wasm_func_type(func)),
+                           wasm_func_result_arity(func), results);
+    if (wasm_func_result_arity(func) && !argc) {
+        goto failed;
+    }
+
+    FREEIF(argv);
+    /* should return trap */
+    return NULL;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    FREEIF(argv);
+    return NULL;
+}
+
+size_t
+wasm_func_param_arity(const wasm_func_t *func)
+{
+    bh_assert(func && func->func_type && func->func_type->params);
+    return func->func_type->params->num_elems;
+}
+
+size_t
+wasm_func_result_arity(const wasm_func_t *func)
+{
+    bh_assert(func && func->func_type && func->func_type->results);
+    return func->func_type->results->num_elems;
+}
+
+wasm_extern_t *
+wasm_func_as_extern(wasm_func_t *func)
+{
+    return (wasm_extern_t *)func;
+}
+
+wasm_global_t *
+wasm_global_new(wasm_store_t *store,
+                const wasm_globaltype_t *global_type,
+                const wasm_val_t *init)
+{
+    wasm_global_t *global = NULL;
+
+    check_engine_and_store(singleton_engine, store);
+    bh_assert(store && global_type && init);
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global) {
+        goto failed;
+    }
+
+    global->kind = WASM_EXTERN_GLOBAL;
+    global->type = wasm_globaltype_copy((wasm_globaltype_t *)global_type);
+    if (!global->type) {
+        goto failed;
+    }
+
+    global->init = malloc_internal(sizeof(wasm_val_t));
+    if (!global->init) {
+        goto failed;
+    }
+
+    wasm_val_copy(global->init, init);
+    /* TODO: how to check if above is failed */
+
+    return global;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
+/* almost same with wasm_global_new */
+wasm_global_t *
+wasm_global_copy(const wasm_global_t *src)
+{
+    wasm_global_t *global = NULL;
+
+    bh_assert(src);
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global) {
+        goto failed;
+    }
+
+    global->kind = WASM_EXTERN_GLOBAL;
+    global->type = wasm_globaltype_copy((wasm_globaltype_t *)src->type);
+    if (!global->type) {
+        goto failed;
+    }
+
+    global->init = malloc_internal(sizeof(wasm_val_t));
+    if (!global->init) {
+        goto failed;
+    }
+
+    wasm_val_copy(global->init, src->init);
+
+    global->global_idx_rt = src->global_idx_rt;
+    global->inst_comm_rt = src->inst_comm_rt;
+
+    return global;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
+void
+wasm_global_delete(wasm_global_t *global)
+{
+    if (!global) {
+        return;
+    }
+
+    if (global->init) {
+        wasm_val_delete(global->init);
+        wasm_runtime_free(global->init);
+        global->init = NULL;
+    }
+
+    if (global->type) {
+        wasm_globaltype_delete(global->type);
+        global->type = NULL;
+    }
+
+    wasm_runtime_free(global);
+}
+
+bool
+wasm_global_same(const wasm_global_t *g1, const wasm_global_t *g2)
+{
+    if (!g1 && !g2) {
+        return true;
+    }
+
+    if (!g1 || !g2) {
+        return false;
+    }
+
+    return g1->kind == g2->kind && wasm_globaltype_same(g1->type, g2->type)
+           && wasm_val_same(g1->init, g2->init);
+}
+
+#if WASM_ENABLE_INTERP != 0
+static bool
+interp_global_set(const WASMModuleInstance *inst_interp,
+                  uint16 global_idx_rt,
+                  const wasm_val_t *v)
+{
+    const WASMGlobalInstance *global_interp =
+      inst_interp->globals + global_idx_rt;
+    uint8 val_type_rt = global_interp->type;
+    uint8 *data = inst_interp->global_data + global_interp->data_offset;
+    bool ret = true;
+
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            bh_assert(WASM_I32 == v->kind);
+            *((int32 *)data) = v->of.i32;
+            break;
+        case VALUE_TYPE_F32:
+            bh_assert(WASM_F32 == v->kind);
+            *((float32 *)data) = v->of.f32;
+            break;
+        case VALUE_TYPE_I64:
+            bh_assert(WASM_I64 == v->kind);
+            *((int64 *)data) = v->of.i64;
+            break;
+        case VALUE_TYPE_F64:
+            bh_assert(WASM_F64 == v->kind);
+            *((float64 *)data) = v->of.f64;
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+            break;
+    }
+
+    return ret;
+}
+
+static bool
+interp_global_get(const WASMModuleInstance *inst_interp,
+                  uint16 global_idx_rt,
+                  wasm_val_t *out)
+{
+    WASMGlobalInstance *global_interp = inst_interp->globals + global_idx_rt;
+    uint8 val_type_rt = global_interp->type;
+    uint8 *data = inst_interp->global_data + global_interp->data_offset;
+    bool ret = true;
+
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            out->kind = WASM_I32;
+            out->of.i32 = *((int32 *)data);
+            break;
+        case VALUE_TYPE_F32:
+            out->kind = WASM_F32;
+            out->of.f32 = *((float32 *)data);
+            break;
+        case VALUE_TYPE_I64:
+            out->kind = WASM_I64;
+            out->of.i64 = *((int64 *)data);
+            break;
+        case VALUE_TYPE_F64:
+            out->kind = WASM_F64;
+            out->of.f64 = *((float64 *)data);
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+    }
+    return ret;
+}
+#endif
+
+#if WASM_ENABLE_AOT != 0
+static bool
+aot_global_set(const AOTModuleInstance *inst_aot,
+               uint16 global_idx_rt,
+               const wasm_val_t *v)
+{
+    AOTModule *module_aot = inst_aot->aot_module.ptr;
+    uint8 val_type_rt = 0;
+    uint32 data_offset = 0;
+    void *data = NULL;
+    bool ret = true;
+
+    if (global_idx_rt < module_aot->import_global_count) {
+        data_offset = module_aot->import_globals[global_idx_rt].data_offset;
+        val_type_rt = module_aot->import_globals[global_idx_rt].type;
+    }
+    else {
+        data_offset =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .data_offset;
+        val_type_rt =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .type;
+    }
+
+    data = inst_aot->global_data.ptr + data_offset;
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            bh_assert(WASM_I32 == v->kind);
+            *((int32 *)data) = v->of.i32;
+            break;
+        case VALUE_TYPE_F32:
+            bh_assert(WASM_F32 == v->kind);
+            *((float32 *)data) = v->of.f32;
+            break;
+        case VALUE_TYPE_I64:
+            bh_assert(WASM_I64 == v->kind);
+            *((int64 *)data) = v->of.i64;
+            break;
+        case VALUE_TYPE_F64:
+            bh_assert(WASM_F64 == v->kind);
+            *((float64 *)data) = v->of.f64;
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+    }
+    return ret;
+}
+
+static bool
+aot_global_get(const AOTModuleInstance *inst_aot,
+               uint16 global_idx_rt,
+               wasm_val_t *out)
+{
+    AOTModule *module_aot = inst_aot->aot_module.ptr;
+    uint8 val_type_rt = 0;
+    uint32 data_offset = 0;
+    void *data = NULL;
+    bool ret = true;
+
+    if (global_idx_rt < module_aot->import_global_count) {
+        data_offset = module_aot->import_globals[global_idx_rt].data_offset;
+        val_type_rt = module_aot->import_globals[global_idx_rt].type;
+    }
+    else {
+        data_offset =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .data_offset;
+        val_type_rt =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .type;
+    }
+
+    data = inst_aot->global_data.ptr + data_offset;
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            out->kind = WASM_I32;
+            out->of.i32 = *((int32 *)data);
+            break;
+        case VALUE_TYPE_F32:
+            out->kind = WASM_F32;
+            out->of.f32 = *((float32 *)data);
+            break;
+        case VALUE_TYPE_I64:
+            out->kind = WASM_I64;
+            out->of.i64 = *((int64 *)data);
+            break;
+        case VALUE_TYPE_F64:
+            out->kind = WASM_F64;
+            out->of.f64 = *((float64 *)data);
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+    }
+    return ret;
+}
+#endif
+
+void
+wasm_global_set(wasm_global_t *global, const wasm_val_t *v)
+{
+    bh_assert(global && v);
+
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        (void)interp_global_set((WASMModuleInstance *)global->inst_comm_rt,
+                                global->global_idx_rt, v);
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        (void)aot_global_set((AOTModuleInstance *)global->inst_comm_rt,
+                             global->global_idx_rt, v);
+#endif
+    }
+}
+
+void
+wasm_global_get(const wasm_global_t *global, wasm_val_t *out)
+{
+    bh_assert(global && out);
+
+    memset(out, 0, sizeof(wasm_val_t));
+
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        (void)interp_global_get((WASMModuleInstance *)global->inst_comm_rt,
+                                global->global_idx_rt, out);
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        (void)aot_global_get((AOTModuleInstance *)global->inst_comm_rt,
+                             global->global_idx_rt, out);
+#endif
+    }
+
+    bh_assert(global->init->kind == out->kind);
+}
+
+static wasm_global_t *
+wasm_global_new_internal(wasm_store_t *store,
+                         uint16 global_idx_rt,
+                         WASMModuleInstanceCommon *inst_comm_rt)
+{
+    wasm_global_t *global = NULL;
+    uint8 val_type_rt = 0;
+    bool is_mutable = 0;
+
+    check_engine_and_store(singleton_engine, store);
+    bh_assert(inst_comm_rt);
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global) {
+        goto failed;
+    }
+
+    /*
+     * global->module_name = NULL;
+     * global->name = NULL;
+     */
+    global->kind = WASM_EXTERN_GLOBAL;
+
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        WASMGlobalInstance *global_interp =
+          ((WASMModuleInstance *)inst_comm_rt)->globals + global_idx_rt;
+        val_type_rt = global_interp->type;
+        is_mutable = global_interp->is_mutable;
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+        AOTModule *module_aot = inst_aot->aot_module.ptr;
+        if (global_idx_rt < module_aot->import_global_count) {
+            AOTImportGlobal *global_import_aot =
+              module_aot->import_globals + global_idx_rt;
+            val_type_rt = global_import_aot->type;
+            is_mutable = global_import_aot->is_mutable;
+        }
+        else {
+            AOTGlobal *global_aot =
+              module_aot->globals
+              + (global_idx_rt - module_aot->import_global_count);
+            val_type_rt = global_aot->type;
+            is_mutable = global_aot->is_mutable;
+        }
+#endif
+    }
+
+    global->type = wasm_globaltype_new_internal(val_type_rt, is_mutable);
+    if (!global->type) {
+        goto failed;
+    }
+
+    global->init = malloc_internal(sizeof(wasm_val_t));
+    if (!global->init) {
+        goto failed;
+    }
+
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        interp_global_get((WASMModuleInstance *)inst_comm_rt, global_idx_rt,
+                          global->init);
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        aot_global_get((AOTModuleInstance *)inst_comm_rt, global_idx_rt,
+                       global->init);
+#endif
+    }
+
+    global->inst_comm_rt = inst_comm_rt;
+    global->global_idx_rt = global_idx_rt;
+
+    return global;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
+wasm_globaltype_t *
+wasm_global_type(const wasm_global_t *global)
+{
+    bh_assert(global);
+    return global->type;
+}
+
+wasm_extern_t *
+wasm_global_as_extern(wasm_global_t *global)
+{
+    return (wasm_extern_t *)global;
+}
+
+void
+wasm_table_delete(wasm_table_t *table)
+{}
+
+void
+wasm_memory_delete(wasm_memory_t *memory)
+{}
+
+#if WASM_ENABLE_INTERP != 0
+static bool
+interp_link_func(const wasm_instance_t *inst,
+                 const WASMModule *module_interp,
+                 uint16 func_idx_rt,
+                 wasm_func_t *import)
+{
+    WASMImport *imported_func_interp = NULL;
+    wasm_func_t *cloned = NULL;
+
+    bh_assert(inst && module_interp && import);
+    bh_assert(func_idx_rt < module_interp->import_function_count);
+    bh_assert(WASM_EXTERN_FUNC == import->kind);
+
+    imported_func_interp = module_interp->import_functions + func_idx_rt;
+    bh_assert(imported_func_interp);
+
+    cloned = wasm_func_copy(import);
+    if (!cloned || !bh_vector_append((Vector *)inst->imports, &cloned)) {
+        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;
+    import->func_idx_rt = func_idx_rt;
+
+    return true;
+}
+
+static bool
+interp_link_global(const WASMModule *module_interp,
+                   uint16 global_idx_rt,
+                   wasm_global_t *import)
+{
+    WASMImport *imported_global_interp = NULL;
+
+    bh_assert(module_interp && import);
+    bh_assert(global_idx_rt < module_interp->import_global_count);
+    bh_assert(WASM_EXTERN_GLOBAL == import->kind);
+
+    imported_global_interp = module_interp->import_globals + global_idx_rt;
+    bh_assert(imported_global_interp);
+
+    /* set init value */
+    switch (wasm_valtype_kind(import->type->val_type)) {
+        case WASM_I32:
+            bh_assert(VALUE_TYPE_I32 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.i32 =
+              import->init->of.i32;
+            break;
+        case WASM_I64:
+            bh_assert(VALUE_TYPE_I64 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.i64 =
+              import->init->of.i64;
+            break;
+        case WASM_F32:
+            bh_assert(VALUE_TYPE_F32 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.f32 =
+              import->init->of.f32;
+            break;
+        case WASM_F64:
+            bh_assert(VALUE_TYPE_F64 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.f64 =
+              import->init->of.f64;
+            break;
+        default:
+            return false;
+    }
+
+    import->global_idx_rt = global_idx_rt;
+    return true;
+}
+
+static bool
+interp_link_memory(const WASMModule *module_interp,
+                   uint16 memory_inst_index,
+                   wasm_memory_t *import)
+{
+    return false;
+}
+
+static bool
+interp_link_table(const WASMModule *module_interp,
+                  uint16 table_inst_index,
+                  wasm_table_t *import)
+{
+    return false;
+}
+
+static int32
+interp_link(const wasm_instance_t *inst,
+            const WASMModule *module_interp,
+            wasm_extern_t *imports[])
+{
+    uint32 i = 0;
+    uint32 import_func_i = 0;
+    uint32 import_global_i = 0;
+    uint32 import_table_i = 0;
+    uint32 import_memory_i = 0;
+    wasm_func_t *func = NULL;
+    wasm_global_t *global = NULL;
+
+    bh_assert(inst && module_interp && imports);
+
+    for (i = 0; i < module_interp->import_count; ++i) {
+        wasm_extern_t *import = imports[i];
+        WASMImport *import_rt = module_interp->imports + i;
+
+        switch (import_rt->kind) {
+            case IMPORT_KIND_FUNC:
+                func = wasm_extern_as_func(import);
+                if (!interp_link_func(inst, module_interp, import_func_i++,
+                                      func)) {
+                    goto failed;
+                }
+
+                break;
+            case IMPORT_KIND_GLOBAL:
+                global = wasm_extern_as_global(import);
+                if (!interp_link_global(module_interp, import_global_i++,
+                                        global)) {
+                    goto failed;
+                }
+
+                break;
+            case IMPORT_KIND_MEMORY:
+                if (!interp_link_memory(module_interp, import_memory_i++,
+                                        wasm_extern_as_memory(import))) {
+                    goto failed;
+                };
+                break;
+            case IMPORT_KIND_TABLE:
+                if (!interp_link_table(module_interp, import_table_i++,
+                                       wasm_extern_as_table(import))) {
+                    goto failed;
+                }
+                break;
+            default:
+                NOT_REACHED();
+                break;
+        }
+    }
+
+    return module_interp->import_count;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return -1;
+}
+
+static bool
+interp_process_export(wasm_store_t *store,
+                      const WASMModuleInstance *inst_interp,
+                      wasm_extern_vec_t *externals)
+{
+    WASMExport *exports = NULL;
+    WASMExport *export = NULL;
+    wasm_func_t *func = NULL;
+    wasm_global_t *global = NULL;
+    wasm_extern_t *external = NULL;
+    uint32 export_cnt = 0;
+    uint32 i = 0;
+
+    bh_assert(store && inst_interp && externals);
+
+    exports = inst_interp->module->exports;
+    export_cnt = inst_interp->module->export_count;
+
+    for (i = 0; i < export_cnt; ++i) {
+        export = exports + i;
+
+        switch (export->kind) {
+            case EXPORT_KIND_FUNC:
+                func = wasm_func_new_internal(
+                  store, export->index,
+                  (WASMModuleInstanceCommon *)inst_interp);
+                if (!func) {
+                    goto failed;
+                }
+
+                external = wasm_func_as_extern(func);
+                break;
+            case EXPORT_KIND_GLOBAL:
+                global = wasm_global_new_internal(
+                  store, export->index,
+                  (WASMModuleInstanceCommon *)inst_interp);
+                if (!global) {
+                    goto failed;
+                }
+
+                external = wasm_global_as_extern(global);
+                break;
+            // TODO:
+            case EXPORT_KIND_MEMORY:
+            case EXPORT_KIND_TABLE:
+                break;
+            default:
+                goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)externals, &external)) {
+            goto failed;
+        }
+    }
+
+    return true;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return false;
+}
+#endif /* WASM_ENABLE_INTERP */
+
+#if WASM_ENABLE_AOT != 0
+static bool
+aot_link_func(const wasm_instance_t *inst,
+              const AOTModule *module_aot,
+              uint32 import_func_idx_rt,
+              wasm_func_t *import)
+{
+    AOTImportFunc *import_aot_func = NULL;
+    wasm_func_t *cloned = NULL;
+
+    bh_assert(inst && module_aot && import);
+
+    import_aot_func = module_aot->import_funcs + import_func_idx_rt;
+    bh_assert(import_aot_func);
+
+    cloned = wasm_func_copy(import);
+    if (!cloned || !bh_vector_append((Vector *)inst->imports, &cloned)) {
+        return false;
+    }
+
+    import_aot_func->call_conv_raw = true;
+    import_aot_func->attachment = wasm_func_copy(import);
+    import_aot_func->func_ptr_linked = native_func_trampoline;
+    import->func_idx_rt = import_func_idx_rt;
+
+    return true;
+}
+
+static bool
+aot_link_global(const AOTModule *module_aot,
+                uint16 global_idx_rt,
+                wasm_global_t *import)
+{
+    AOTImportGlobal *import_aot_global = NULL;
+    const wasm_valtype_t *val_type = NULL;
+
+    bh_assert(module_aot && import);
+
+    import_aot_global = module_aot->import_globals + global_idx_rt;
+    bh_assert(import_aot_global);
+
+    val_type = wasm_globaltype_content(wasm_global_type(import));
+    bh_assert(val_type);
+
+    switch (wasm_valtype_kind(val_type)) {
+        case WASM_I32:
+            bh_assert(VALUE_TYPE_I32 == import_aot_global->type);
+            import_aot_global->global_data_linked.i32 = import->init->of.i32;
+            break;
+        case WASM_I64:
+            bh_assert(VALUE_TYPE_I64 == import_aot_global->type);
+            import_aot_global->global_data_linked.i64 = import->init->of.i64;
+            break;
+        case WASM_F32:
+            bh_assert(VALUE_TYPE_F32 == import_aot_global->type);
+            import_aot_global->global_data_linked.f32 = import->init->of.f32;
+            break;
+        case WASM_F64:
+            bh_assert(VALUE_TYPE_F64 == import_aot_global->type);
+            import_aot_global->global_data_linked.f64 = import->init->of.f64;
+            break;
+        default:
+            goto failed;
+    }
+
+    import->global_idx_rt = global_idx_rt;
+    return true;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return false;
+}
+
+static int32
+aot_link(const wasm_instance_t *inst,
+         const AOTModule *module_aot,
+         wasm_extern_t *imports[])
+{
+    uint32 i = 0;
+    uint32 import_func_i = 0;
+    uint32 import_global_i = 0;
+    wasm_extern_t *import = NULL;
+    wasm_func_t *func = NULL;
+    wasm_global_t *global = NULL;
+
+    bh_assert(inst && module_aot && imports);
+
+    while (import_func_i < module_aot->import_func_count
+           || import_global_i < module_aot->import_global_count) {
+        import = imports[i++];
+
+        bh_assert(import);
+
+        switch (wasm_extern_kind(import)) {
+            case WASM_EXTERN_FUNC:
+                bh_assert(import_func_i < module_aot->import_func_count);
+                func = wasm_extern_as_func((wasm_extern_t *)import);
+                if (!aot_link_func(inst, module_aot, import_func_i++, func)) {
+                    goto failed;
+                }
+
+                break;
+            case WASM_EXTERN_GLOBAL:
+                bh_assert(import_global_i < module_aot->import_global_count);
+                global = wasm_extern_as_global((wasm_extern_t *)import);
+                if (!aot_link_global(module_aot, import_global_i++, global)) {
+                    goto failed;
+                }
+
+                break;
+            case WASM_EXTERN_MEMORY:
+                break;
+            case WASM_EXTERN_TABLE:
+                break;
+            default:
+                goto failed;
+        }
+    }
+
+    return i;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return -1;
+}
+
+static bool
+aot_process_export(wasm_store_t *store,
+                   const AOTModuleInstance *inst_aot,
+                   wasm_extern_vec_t *externals)
+{
+    uint32 i = 0;
+    uint32 export_func_i = 0;
+    wasm_extern_t *external = NULL;
+    AOTModule *module_aot = NULL;
+
+    bh_assert(store && inst_aot && externals);
+
+    module_aot = (AOTModule *)inst_aot->aot_module.ptr;
+    bh_assert(module_aot);
+
+    for (i = 0; i < module_aot->export_count; ++i) {
+        AOTExport *export = module_aot->exports + i;
+        wasm_func_t *func = NULL;
+        wasm_global_t *global = NULL;
+
+        switch (export->kind) {
+            case EXPORT_KIND_FUNC:
+                func =
+                  wasm_func_new_internal(store, export_func_i++,
+                                         (WASMModuleInstanceCommon *)inst_aot);
+                if (!func) {
+                    goto failed;
+                }
+
+                external = wasm_func_as_extern(func);
+                break;
+            case EXPORT_KIND_GLOBAL:
+                global = wasm_global_new_internal(
+                  store, export->index, (WASMModuleInstanceCommon *)inst_aot);
+                if (!global) {
+                    goto failed;
+                }
+
+                external = wasm_global_as_extern(global);
+                break;
+            case EXPORT_KIND_MEMORY:
+            case EXPORT_KIND_TABLE:
+                break;
+            default:
+                NOT_REACHED();
+                goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)externals, &external)) {
+            goto failed;
+        }
+    }
+
+    return true;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return false;
+}
+#endif /* WASM_ENABLE_AOT */
+
+wasm_instance_t *
+wasm_instance_new(wasm_store_t *store,
+                  const wasm_module_t *module,
+                  const wasm_extern_t *const imports[],
+                  wasm_trap_t **traps)
+{
+    char error[128] = { 0 };
+    const uint32 stack_size = 16 * 1024;
+    const uint32 heap_size = 16 * 1024;
+    int32 import_count = 0;
+    wasm_instance_t *instance = NULL;
+    uint32 i = 0;
+    (void)traps;
+
+    check_engine_and_store(singleton_engine, store);
+
+    instance = malloc_internal(sizeof(wasm_instance_t));
+    if (!instance) {
+        goto failed;
+    }
+
+    /* link module and imports */
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        import_count = ((WASMModule *)*module)->import_count;
+        INIT_VEC(instance->imports, wasm_extern_vec, import_count);
+        if (!instance->imports) {
+            goto failed;
+        }
+
+        import_count = interp_link(instance, (WASMModule *)*module,
+                                   (wasm_extern_t **)imports);
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        import_count = ((AOTModule *)*module)->import_func_count
+                       + ((AOTModule *)*module)->import_global_count
+                       + ((AOTModule *)*module)->import_memory_count
+                       + ((AOTModule *)*module)->import_table_count;
+        INIT_VEC(instance->imports, wasm_extern_vec, import_count);
+        if (!instance->imports) {
+            goto failed;
+        }
+
+        import_count =
+          aot_link(instance, (AOTModule *)*module, (wasm_extern_t **)imports);
+#endif
+    }
+    if (import_count < 0) {
+        goto failed;
+    }
+
+    instance->inst_comm_rt = wasm_runtime_instantiate(
+      *module, stack_size, heap_size, error, sizeof(error));
+    if (!instance->inst_comm_rt) {
+        LOG_ERROR(error);
+        goto failed;
+    }
+
+    /* fill in inst */
+    for (i = 0; i < (uint32)import_count; ++i) {
+        wasm_extern_t *import = (wasm_extern_t *)imports[i];
+        switch (import->kind) {
+            case WASM_EXTERN_FUNC:
+                wasm_extern_as_func(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            case WASM_EXTERN_GLOBAL:
+                wasm_extern_as_global(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            case WASM_EXTERN_MEMORY:
+                wasm_extern_as_memory(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            case WASM_EXTERN_TABLE:
+                wasm_extern_as_table(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            default:
+                goto failed;
+        }
+    }
+
+    /* build the exports list */
+    if (INTERP_MODE == current_runtime_mode()) {
+#if WASM_ENABLE_INTERP != 0
+        uint32 export_cnt =
+          ((WASMModuleInstance *)instance->inst_comm_rt)->module->export_count;
+
+        INIT_VEC(instance->exports, wasm_extern_vec, export_cnt);
+
+        if (!interp_process_export(
+              store, (WASMModuleInstance *)instance->inst_comm_rt,
+              instance->exports)) {
+            goto failed;
+        }
+#endif
+    }
+    else {
+#if WASM_ENABLE_AOT != 0
+        uint32 export_cnt =
+          ((AOTModuleInstance *)instance->inst_comm_rt)->export_func_count;
+
+        INIT_VEC(instance->exports, wasm_extern_vec, export_cnt);
+
+        if (!aot_process_export(store,
+                                (AOTModuleInstance *)instance->inst_comm_rt,
+                                instance->exports)) {
+            goto failed;
+        }
+#endif
+    }
+
+    /* add it to a watching list in store */
+    if (!bh_vector_append((Vector *)store->instances, &instance)) {
+        goto failed;
+    }
+
+    return instance;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_instance_delete_internal(instance);
+    return NULL;
+}
+
+void
+wasm_instance_delete_internal(wasm_instance_t *instance)
+{
+    if (!instance) {
+        return;
+    }
+
+    DEINIT_VEC(instance->imports, wasm_extern_vec_delete);
+    DEINIT_VEC(instance->exports, wasm_extern_vec_delete);
+
+    if (instance->inst_comm_rt) {
+        wasm_runtime_deinstantiate(instance->inst_comm_rt);
+        instance->inst_comm_rt = NULL;
+    }
+    wasm_runtime_free(instance);
+}
+
+/* will release instance when releasing the store */
+void
+wasm_instance_delete(wasm_instance_t *module)
+{
+    /* pass */
+}
+
+void
+wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out)
+{
+    bh_assert(instance && out);
+    wasm_extern_vec_copy(out, instance->exports);
+}
+
+void
+wasm_instance_vec_new_uninitialized(wasm_instance_vec_t *out, size_t size)
+{
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_instance_t));
+}
+
+void
+wasm_instance_vec_delete(wasm_instance_vec_t *instance_vec)
+{
+    size_t i = 0;
+    if (!instance_vec || !instance_vec->data) {
+        return;
+    }
+
+    FREE_VEC_ELEMS(instance_vec, wasm_instance_delete_internal);
+    bh_vector_destroy((Vector *)instance_vec);
+}
+
+wasm_extern_t *
+wasm_extern_copy(const wasm_extern_t *src)
+{
+    wasm_extern_t *dst = NULL;
+    wasm_func_t *func = NULL;
+    wasm_global_t *global = NULL;
+    bh_assert(src);
+
+    switch (wasm_extern_kind(src)) {
+        case WASM_EXTERN_FUNC:
+            func = wasm_func_copy(wasm_extern_as_func_const(src));
+            dst = wasm_func_as_extern(func);
+            break;
+        case WASM_EXTERN_GLOBAL:
+            global = wasm_global_copy(wasm_extern_as_global_const(src));
+            dst = wasm_global_as_extern(global);
+            break;
+        case WASM_EXTERN_MEMORY:
+        case WASM_EXTERN_TABLE:
+        default:
+            break;
+    }
+
+    if (!dst) {
+        goto failed;
+    }
+
+    return dst;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_extern_delete(dst);
+    return NULL;
+}
+
+void
+wasm_extern_delete(wasm_extern_t *external)
+{
+    if (!external) {
+        return;
+    }
+
+    switch (wasm_extern_kind(external)) {
+        case WASM_EXTERN_FUNC:
+            wasm_func_delete(wasm_extern_as_func(external));
+            break;
+        case WASM_EXTERN_GLOBAL:
+            wasm_global_delete(wasm_extern_as_global(external));
+            break;
+        case WASM_EXTERN_MEMORY:
+        case WASM_EXTERN_TABLE:
+        default:
+            break;
+    }
+}
+
+wasm_externkind_t
+wasm_extern_kind(const wasm_extern_t *extrenal)
+{
+    return extrenal->kind;
+}
+
+wasm_func_t *
+wasm_extern_as_func(wasm_extern_t *external)
+{
+    return (wasm_func_t *)external;
+}
+
+const wasm_func_t *
+wasm_extern_as_func_const(const wasm_extern_t *external)
+{
+    return (const wasm_func_t *)external;
+}
+
+wasm_global_t *
+wasm_extern_as_global(wasm_extern_t *external)
+{
+    return (wasm_global_t *)external;
+}
+
+const wasm_global_t *
+wasm_extern_as_global_const(const wasm_extern_t *external)
+{
+    return (const wasm_global_t *)external;
+}
+
+wasm_memory_t *
+wasm_extern_as_memory(wasm_extern_t *external)
+{
+    return (wasm_memory_t *)external;
+}
+
+const wasm_memory_t *
+wasm_extern_as_memory_const(const wasm_extern_t *external)
+{
+    return (const wasm_memory_t *)external;
+}
+
+wasm_table_t *
+wasm_extern_as_table(wasm_extern_t *external)
+{
+    return (wasm_table_t *)external;
+}
+
+const wasm_table_t *
+wasm_extern_as_table_const(const wasm_extern_t *external)
+{
+    return (const wasm_table_t *)external;
+}
+
+void
+wasm_extern_vec_copy(wasm_extern_vec_t *out, const wasm_extern_vec_t *src)
+{
+    size_t i = 0;
+    bh_assert(out && src);
+
+    generic_vec_init_data((Vector *)out, src->size, src->size_of_elem);
+    if (!out->data) {
+        goto failed;
+    }
+
+    for (i = 0; i < src->num_elems; ++i) {
+        wasm_extern_t *orig = *(src->data + i);
+        wasm_extern_t *cloned = wasm_extern_copy(orig);
+        if (!cloned) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)out, &cloned)) {
+            goto failed;
+        }
+    }
+
+    return;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_extern_vec_delete(out);
+    return;
+}
+
+void
+wasm_extern_vec_new_uninitialized(wasm_extern_vec_t *out, size_t size)
+{
+    generic_vec_init_data((Vector *)out, size, sizeof(wasm_extern_t *));
+}
+
+void
+wasm_extern_vec_delete(wasm_extern_vec_t *extern_vec)
+{
+    size_t i = 0;
+    if (!extern_vec || !extern_vec->data) {
+        return;
+    }
+
+    FREE_VEC_ELEMS(extern_vec, wasm_extern_delete);
+    bh_vector_destroy((Vector *)extern_vec);
+}

+ 180 - 0
core/iwasm/common/wasm_c_api_internal.h

@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_C_API_INTERNAL_H
+#define _WASM_C_API_INTERNAL_H
+
+#include "wasm_c_api.h"
+#include "wasm_runtime_common.h"
+
+#ifndef own
+#define own
+#endif
+
+/* Vectors */
+/* we will malloc resource for the vector's data field */
+/* we will release resource of data */
+/* caller needs to take care resource for the vector itself */
+#define DEFAULT_VECTOR_INIT_LENGTH (64)
+
+WASM_DECLARE_VEC(store, *)
+WASM_DECLARE_VEC(module, *)
+WASM_DECLARE_VEC(instance, *)
+
+/* Runtime Environment */
+typedef enum runtime_mode_e {
+    INTERP_MODE = 0,
+    JIT_MODE,
+    AOT_MODE
+} runtime_mode_e;
+
+struct wasm_engine_t {
+    // support one store for now
+    wasm_store_vec_t *stores;
+    // Interpreter by deault
+    runtime_mode_e mode;
+};
+
+struct wasm_store_t {
+    wasm_module_vec_t *modules;
+    wasm_instance_vec_t *instances;
+};
+
+/* Type Representations */
+struct wasm_valtype_t {
+    wasm_valkind_t kind;
+};
+
+struct wasm_functype_t {
+    uint32 extern_kind;
+    // gona to new and delete own
+    wasm_valtype_vec_t *params;
+    wasm_valtype_vec_t *results;
+};
+
+struct wasm_globaltype_t {
+    uint32 extern_kind;
+    // gona to new and delete own
+    wasm_valtype_t *val_type;
+    wasm_mutability_t mutability;
+};
+
+struct wasm_tabletype_t {
+    uint32 extern_kind;
+    // always be WASM_FUNCREF
+    wasm_valtype_t *type;
+    wasm_limits_t *limits;
+};
+
+struct wasm_memorytype_t {
+    uint32 extern_kind;
+    wasm_limits_t *limits;
+};
+
+struct wasm_externtype_t {
+    uint32 extern_kind;
+    uint8 data[1];
+};
+
+struct wasm_import_type_t {
+    uint32 extern_kind;
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+};
+
+struct wasm_export_type_t {
+    uint32 extern_kind;
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+};
+
+/* Runtime Objects */
+struct wasm_ref_t {};
+
+struct wasm_trap_t {
+    wasm_byte_vec_t *message;
+};
+
+struct wasm_func_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_functype_t *func_type;
+
+    bool with_env;
+    union {
+        wasm_func_callback_t cb;
+        struct callback_ext {
+            void *env;
+            wasm_func_callback_with_env_t cb;
+            void (*finalizer)(void *);
+        } cb_env;
+    } u;
+    /*
+     * an index in both functions runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 func_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_global_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_globaltype_t *type;
+    wasm_val_t *init;
+    /*
+     * an index in both global runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 global_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_memory_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_memorytype_t *type;
+    /*
+     * an index in both memory runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 memory_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_table_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_tabletype_t *type;
+    /*
+     * an index in both table runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 table_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_extern_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+    uint8 data[1];
+};
+
+struct wasm_instance_t {
+    wasm_extern_vec_t *imports;
+    wasm_extern_vec_t *exports;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+#endif /* _WASM_C_API_INTERNAL_H */

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

@@ -67,14 +67,11 @@ typedef struct WASMRegisteredModule {
 } WASMRegisteredModule;
 #endif
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
 typedef struct WASMMemoryInstanceCommon {
     uint32 module_type;
     uint8 memory_inst_data[1];
 } WASMMemoryInstanceCommon;
 
-#endif
-
 typedef package_type_t PackageType;
 typedef wasm_section_t WASMSection, AOTSection;
 

+ 0 - 4
core/iwasm/common/wasm_shared_memory.c

@@ -3,8 +3,6 @@
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
-
 #include "bh_log.h"
 #include "wasm_shared_memory.h"
 
@@ -120,5 +118,3 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
     (void)ret;
     return node;
 }
-
-#endif /* end of WASM_ENABLE_SHARED_MEMORY */

+ 679 - 0
core/iwasm/include/wasm_c_api.h

@@ -0,0 +1,679 @@
+// WebAssembly C API
+
+#ifndef WASM_H
+#define WASM_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef WASM_API_EXTERN
+#ifdef _WIN32
+#define WASM_API_EXTERN __declspec(dllimport)
+#else
+#define WASM_API_EXTERN
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Auxiliaries
+
+// Machine types
+#if (__STDC_VERSION__ > 199901L)
+inline void assertions() {
+  static_assert(sizeof(float) == sizeof(uint32_t), "incompatible float type");
+  static_assert(sizeof(double) == sizeof(uint64_t), "incompatible double type");
+  static_assert(sizeof(intptr_t) == sizeof(uint32_t) ||
+                sizeof(intptr_t) == sizeof(uint64_t),
+                "incompatible pointer type");
+}
+#endif /* __STDC_VERSION__  > 199901L */
+
+typedef char byte_t;
+typedef float float32_t;
+typedef double float64_t;
+
+
+// Ownership
+
+#define own
+
+// The qualifier `own` is used to indicate ownership of data in this API.
+// It is intended to be interpreted similar to a `const` qualifier:
+//
+// - `own wasm_xxx_t*` owns the pointed-to data
+// - `own wasm_xxx_t` distributes to all fields of a struct or union `xxx`
+// - `own wasm_xxx_vec_t` owns the vector as well as its elements(!)
+// - an `own` function parameter passes ownership from caller to callee
+// - an `own` function result passes ownership from callee to caller
+// - an exception are `own` pointer parameters named `out`, which are copy-back
+//   output parameters passing back ownership from callee to caller
+//
+// Own data is created by `wasm_xxx_new` functions and some others.
+// It must be released with the corresponding `wasm_xxx_delete` function.
+//
+// Deleting a reference does not necessarily delete the underlying object,
+// it merely indicates that this owner no longer uses it.
+//
+// For vectors, `const wasm_xxx_vec_t` is used informally to indicate that
+// neither the vector nor its elements should be modified.
+// TODO: introduce proper `wasm_xxx_const_vec_t`?
+
+
+#define WASM_DECLARE_OWN(name) \
+  typedef struct wasm_##name##_t wasm_##name##_t; \
+  \
+  WASM_API_EXTERN void wasm_##name##_delete(own wasm_##name##_t*);
+
+
+// Vectors
+// size: capacity
+// num_elems: current number of elements
+// size_of_elem: size of one element
+#define WASM_DECLARE_VEC(name, ptr_or_none) \
+  typedef struct wasm_##name##_vec_t { \
+    size_t size; \
+    wasm_##name##_t ptr_or_none* data; \
+    size_t num_elems; \
+    size_t size_of_elem; \
+  } wasm_##name##_vec_t; \
+  \
+  WASM_API_EXTERN void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t* out); \
+  WASM_API_EXTERN void wasm_##name##_vec_new_uninitialized( \
+    own wasm_##name##_vec_t* out, size_t); \
+  WASM_API_EXTERN void wasm_##name##_vec_new( \
+    own wasm_##name##_vec_t* out, \
+    size_t, own wasm_##name##_t ptr_or_none const[]); \
+  WASM_API_EXTERN void wasm_##name##_vec_copy( \
+    own wasm_##name##_vec_t* out, const wasm_##name##_vec_t*); \
+  WASM_API_EXTERN void wasm_##name##_vec_delete(own wasm_##name##_vec_t*);
+
+
+// Byte vectors
+
+typedef byte_t wasm_byte_t;
+WASM_DECLARE_VEC(byte, )
+
+typedef wasm_byte_vec_t wasm_name_t;
+
+#define wasm_name wasm_byte_vec
+#define wasm_name_new wasm_byte_vec_new
+#define wasm_name_new_empty wasm_byte_vec_new_empty
+#define wasm_name_new_new_uninitialized wasm_byte_vec_new_uninitialized
+#define wasm_name_copy wasm_byte_vec_copy
+#define wasm_name_delete wasm_byte_vec_delete
+
+static inline void wasm_name_new_from_string(
+  own wasm_name_t* out, const char* s
+) {
+  wasm_name_new(out, strlen(s) + 1, s);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Runtime Environment
+
+// Engine
+
+WASM_DECLARE_OWN(engine)
+
+WASM_API_EXTERN own wasm_engine_t* wasm_engine_new();
+
+
+// Store
+
+WASM_DECLARE_OWN(store)
+
+WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Type Representations
+
+// Type attributes
+
+typedef uint8_t wasm_mutability_t;
+enum wasm_mutability_enum {
+  WASM_CONST,
+  WASM_VAR,
+};
+
+typedef struct wasm_limits_t {
+  uint32_t min;
+  uint32_t max;
+} wasm_limits_t;
+
+static const uint32_t wasm_limits_max_default = 0xffffffff;
+
+
+// Generic
+
+#define WASM_DECLARE_TYPE(name) \
+  WASM_DECLARE_OWN(name) \
+  WASM_DECLARE_VEC(name, *) \
+  \
+  WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_copy(wasm_##name##_t*);
+
+
+// Value Types
+
+WASM_DECLARE_TYPE(valtype)
+
+typedef uint8_t wasm_valkind_t;
+enum wasm_valkind_enum {
+  WASM_I32,
+  WASM_I64,
+  WASM_F32,
+  WASM_F64,
+  WASM_ANYREF = 128,
+  WASM_FUNCREF,
+};
+
+WASM_API_EXTERN own wasm_valtype_t* wasm_valtype_new(wasm_valkind_t);
+
+WASM_API_EXTERN wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*);
+
+static inline bool wasm_valkind_is_num(wasm_valkind_t k) {
+  return k < WASM_ANYREF;
+}
+static inline bool wasm_valkind_is_ref(wasm_valkind_t k) {
+  return k >= WASM_ANYREF;
+}
+
+static inline bool wasm_valtype_is_num(const wasm_valtype_t* t) {
+  return wasm_valkind_is_num(wasm_valtype_kind(t));
+}
+static inline bool wasm_valtype_is_ref(const wasm_valtype_t* t) {
+  return wasm_valkind_is_ref(wasm_valtype_kind(t));
+}
+
+
+// Function Types
+
+WASM_DECLARE_TYPE(functype)
+
+WASM_API_EXTERN own wasm_functype_t* wasm_functype_new(
+  own wasm_valtype_vec_t* params, own wasm_valtype_vec_t* results);
+
+WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t*);
+WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t*);
+
+
+// Global Types
+
+WASM_DECLARE_TYPE(globaltype)
+
+WASM_API_EXTERN own wasm_globaltype_t* wasm_globaltype_new(
+  own wasm_valtype_t*, wasm_mutability_t);
+
+WASM_API_EXTERN const wasm_valtype_t* wasm_globaltype_content(const wasm_globaltype_t*);
+WASM_API_EXTERN wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t*);
+
+
+// Table Types
+
+WASM_DECLARE_TYPE(tabletype)
+
+WASM_API_EXTERN own wasm_tabletype_t* wasm_tabletype_new(
+  own wasm_valtype_t*, const wasm_limits_t*);
+
+WASM_API_EXTERN const wasm_valtype_t* wasm_tabletype_element(const wasm_tabletype_t*);
+WASM_API_EXTERN const wasm_limits_t* wasm_tabletype_limits(const wasm_tabletype_t*);
+
+
+// Memory Types
+
+WASM_DECLARE_TYPE(memorytype)
+
+WASM_API_EXTERN own wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t*);
+
+WASM_API_EXTERN const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t*);
+
+
+// Extern Types
+
+WASM_DECLARE_TYPE(externtype)
+
+typedef uint8_t wasm_externkind_t;
+enum wasm_externkind_enum {
+  WASM_EXTERN_FUNC,
+  WASM_EXTERN_GLOBAL,
+  WASM_EXTERN_TABLE,
+  WASM_EXTERN_MEMORY,
+};
+
+WASM_API_EXTERN wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t*);
+
+WASM_API_EXTERN wasm_externtype_t* wasm_functype_as_externtype(wasm_functype_t*);
+WASM_API_EXTERN wasm_externtype_t* wasm_globaltype_as_externtype(wasm_globaltype_t*);
+WASM_API_EXTERN wasm_externtype_t* wasm_tabletype_as_externtype(wasm_tabletype_t*);
+WASM_API_EXTERN wasm_externtype_t* wasm_memorytype_as_externtype(wasm_memorytype_t*);
+
+WASM_API_EXTERN wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t*);
+WASM_API_EXTERN wasm_globaltype_t* wasm_externtype_as_globaltype(wasm_externtype_t*);
+WASM_API_EXTERN wasm_tabletype_t* wasm_externtype_as_tabletype(wasm_externtype_t*);
+WASM_API_EXTERN wasm_memorytype_t* wasm_externtype_as_memorytype(wasm_externtype_t*);
+
+WASM_API_EXTERN const wasm_externtype_t* wasm_functype_as_externtype_const(const wasm_functype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_globaltype_as_externtype_const(const wasm_globaltype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_tabletype_as_externtype_const(const wasm_tabletype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_memorytype_as_externtype_const(const wasm_memorytype_t*);
+
+WASM_API_EXTERN const wasm_functype_t* wasm_externtype_as_functype_const(const wasm_externtype_t*);
+WASM_API_EXTERN const wasm_globaltype_t* wasm_externtype_as_globaltype_const(const wasm_externtype_t*);
+WASM_API_EXTERN const wasm_tabletype_t* wasm_externtype_as_tabletype_const(const wasm_externtype_t*);
+WASM_API_EXTERN const wasm_memorytype_t* wasm_externtype_as_memorytype_const(const wasm_externtype_t*);
+
+
+// Import Types
+
+WASM_DECLARE_TYPE(importtype)
+
+WASM_API_EXTERN own wasm_importtype_t* wasm_importtype_new(
+  own wasm_name_t* module, own wasm_name_t* name, own wasm_externtype_t*);
+
+WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
+WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
+
+
+// Export Types
+
+WASM_DECLARE_TYPE(exporttype)
+
+WASM_API_EXTERN own wasm_exporttype_t* wasm_exporttype_new(
+  own wasm_name_t*, own wasm_externtype_t*);
+
+WASM_API_EXTERN const wasm_name_t* wasm_exporttype_name(const wasm_exporttype_t*);
+WASM_API_EXTERN const wasm_externtype_t* wasm_exporttype_type(const wasm_exporttype_t*);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Runtime Objects
+
+// Values
+
+struct wasm_ref_t;
+
+typedef struct wasm_val_t {
+  wasm_valkind_t kind;
+  union {
+    int32_t i32;
+    int64_t i64;
+    float32_t f32;
+    float64_t f64;
+    struct wasm_ref_t* ref;
+  } of;
+} wasm_val_t;
+
+WASM_API_EXTERN void wasm_val_delete(own wasm_val_t* v);
+WASM_API_EXTERN void wasm_val_copy(own wasm_val_t* out, const wasm_val_t*);
+
+WASM_DECLARE_VEC(val, )
+
+
+// References
+
+#define WASM_DECLARE_REF_BASE(name) \
+  WASM_DECLARE_OWN(name) \
+  \
+  WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t*); \
+  WASM_API_EXTERN bool wasm_##name##_same(const wasm_##name##_t*, const wasm_##name##_t*);
+
+#define WASM_DECLARE_REF(name) \
+  WASM_DECLARE_REF_BASE(name) \
+  \
+  WASM_API_EXTERN wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \
+  WASM_API_EXTERN wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \
+  WASM_API_EXTERN const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t*); \
+  WASM_API_EXTERN const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t*);
+
+#define WASM_DECLARE_SHARABLE_REF(name) \
+  WASM_DECLARE_REF(name) \
+  WASM_DECLARE_OWN(shared_##name) \
+  \
+  WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); \
+  WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*);
+
+
+WASM_DECLARE_REF_BASE(ref)
+
+// Traps
+
+typedef wasm_name_t wasm_message_t;  // null terminated
+
+WASM_DECLARE_REF_BASE(trap)
+
+WASM_API_EXTERN own wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t*);
+
+WASM_API_EXTERN void wasm_trap_message(const wasm_trap_t*, own wasm_message_t* out);
+
+// Modules
+#ifndef WASM_MODULE_T_DEFINED
+#define WASM_MODULE_T_DEFINED
+struct WASMModuleCommon;
+typedef struct WASMModuleCommon *wasm_module_t;
+#endif
+
+WASM_API_EXTERN own wasm_module_t* wasm_module_new(
+  wasm_store_t*, const wasm_byte_vec_t* binary);
+
+WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);
+
+WASM_API_EXTERN void wasm_module_delete(own wasm_module_t*);
+
+WASM_API_EXTERN own wasm_module_t* wasm_module_copy(const wasm_module_t*);
+WASM_API_EXTERN bool wasm_module_same(const wasm_module_t*, const wasm_module_t*);
+
+WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
+WASM_API_EXTERN void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out);
+
+WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
+WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
+
+
+// Function Instances
+
+WASM_DECLARE_REF(func)
+
+typedef own wasm_trap_t* (*wasm_func_callback_t)(
+  const wasm_val_t args[], wasm_val_t results[]);
+typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)(
+  void* env, const wasm_val_t args[], wasm_val_t results[]);
+
+WASM_API_EXTERN own wasm_func_t* wasm_func_new(
+  wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t);
+WASM_API_EXTERN own wasm_func_t* wasm_func_new_with_env(
+  wasm_store_t*, const wasm_functype_t* type, wasm_func_callback_with_env_t,
+  void* env, void (*finalizer)(void*));
+
+WASM_API_EXTERN own wasm_functype_t* wasm_func_type(const wasm_func_t*);
+WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*);
+WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*);
+
+WASM_API_EXTERN own wasm_trap_t* wasm_func_call(
+  const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]);
+
+
+// Global Instances
+
+WASM_DECLARE_REF_BASE(global)
+
+WASM_API_EXTERN own wasm_global_t* wasm_global_new(
+  wasm_store_t*, const wasm_globaltype_t*, const wasm_val_t*);
+
+WASM_API_EXTERN own wasm_globaltype_t* wasm_global_type(const wasm_global_t*);
+
+WASM_API_EXTERN void wasm_global_get(const wasm_global_t*, own wasm_val_t* out);
+WASM_API_EXTERN void wasm_global_set(wasm_global_t*, const wasm_val_t*);
+
+
+// Table Instances
+
+WASM_DECLARE_REF_BASE(table)
+
+typedef uint32_t wasm_table_size_t;
+
+WASM_API_EXTERN own wasm_table_t* wasm_table_new(
+  wasm_store_t*, const wasm_tabletype_t*, wasm_ref_t* init);
+
+WASM_API_EXTERN own wasm_tabletype_t* wasm_table_type(const wasm_table_t*);
+
+WASM_API_EXTERN own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index);
+WASM_API_EXTERN bool wasm_table_set(wasm_table_t*, wasm_table_size_t index, wasm_ref_t*);
+
+WASM_API_EXTERN wasm_table_size_t wasm_table_size(const wasm_table_t*);
+WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init);
+
+
+// Memory Instances
+
+WASM_DECLARE_REF_BASE(memory)
+
+typedef uint32_t wasm_memory_pages_t;
+
+static const size_t MEMORY_PAGE_SIZE = 0x10000;
+
+WASM_API_EXTERN own wasm_memory_t* wasm_memory_new(wasm_store_t*, const wasm_memorytype_t*);
+
+WASM_API_EXTERN own wasm_memorytype_t* wasm_memory_type(const wasm_memory_t*);
+
+WASM_API_EXTERN byte_t* wasm_memory_data(wasm_memory_t*);
+WASM_API_EXTERN size_t wasm_memory_data_size(const wasm_memory_t*);
+
+WASM_API_EXTERN wasm_memory_pages_t wasm_memory_size(const wasm_memory_t*);
+WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
+
+
+// Externals
+
+WASM_DECLARE_REF_BASE(extern)
+WASM_DECLARE_VEC(extern, *)
+
+WASM_API_EXTERN wasm_externkind_t wasm_extern_kind(const wasm_extern_t*);
+WASM_API_EXTERN own wasm_externtype_t* wasm_extern_type(const wasm_extern_t*);
+
+WASM_API_EXTERN wasm_extern_t* wasm_func_as_extern(wasm_func_t*);
+WASM_API_EXTERN wasm_extern_t* wasm_global_as_extern(wasm_global_t*);
+WASM_API_EXTERN wasm_extern_t* wasm_table_as_extern(wasm_table_t*);
+WASM_API_EXTERN wasm_extern_t* wasm_memory_as_extern(wasm_memory_t*);
+
+WASM_API_EXTERN wasm_func_t* wasm_extern_as_func(wasm_extern_t*);
+WASM_API_EXTERN wasm_global_t* wasm_extern_as_global(wasm_extern_t*);
+WASM_API_EXTERN wasm_table_t* wasm_extern_as_table(wasm_extern_t*);
+WASM_API_EXTERN wasm_memory_t* wasm_extern_as_memory(wasm_extern_t*);
+
+WASM_API_EXTERN const wasm_extern_t* wasm_func_as_extern_const(const wasm_func_t*);
+WASM_API_EXTERN const wasm_extern_t* wasm_global_as_extern_const(const wasm_global_t*);
+WASM_API_EXTERN const wasm_extern_t* wasm_table_as_extern_const(const wasm_table_t*);
+WASM_API_EXTERN const wasm_extern_t* wasm_memory_as_extern_const(const wasm_memory_t*);
+
+WASM_API_EXTERN const wasm_func_t* wasm_extern_as_func_const(const wasm_extern_t*);
+WASM_API_EXTERN const wasm_global_t* wasm_extern_as_global_const(const wasm_extern_t*);
+WASM_API_EXTERN const wasm_table_t* wasm_extern_as_table_const(const wasm_extern_t*);
+WASM_API_EXTERN const wasm_memory_t* wasm_extern_as_memory_const(const wasm_extern_t*);
+
+
+// Module Instances
+
+WASM_DECLARE_REF_BASE(instance)
+
+WASM_API_EXTERN own wasm_instance_t* wasm_instance_new(
+  wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[],
+  own wasm_trap_t**
+);
+
+WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Convenience
+
+// Value Type construction short-hands
+
+static inline own wasm_valtype_t* wasm_valtype_new_i32() {
+  return wasm_valtype_new(WASM_I32);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_i64() {
+  return wasm_valtype_new(WASM_I64);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_f32() {
+  return wasm_valtype_new(WASM_F32);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_f64() {
+  return wasm_valtype_new(WASM_F64);
+}
+
+static inline own wasm_valtype_t* wasm_valtype_new_anyref() {
+  return wasm_valtype_new(WASM_ANYREF);
+}
+static inline own wasm_valtype_t* wasm_valtype_new_funcref() {
+  return wasm_valtype_new(WASM_FUNCREF);
+}
+
+
+// Function Types construction short-hands
+
+static inline own wasm_functype_t* wasm_functype_new_0_0() {
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new_empty(&params);
+  wasm_valtype_vec_new_empty(&results);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_1_0(
+  own wasm_valtype_t* p
+) {
+  wasm_valtype_t* ps[1] = {p};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 1, ps);
+  wasm_valtype_vec_new_empty(&results);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_2_0(
+  own wasm_valtype_t* p1, own wasm_valtype_t* p2
+) {
+  wasm_valtype_t* ps[2] = {p1, p2};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 2, ps);
+  wasm_valtype_vec_new_empty(&results);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_3_0(
+  own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3
+) {
+  wasm_valtype_t* ps[3] = {p1, p2, p3};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 3, ps);
+  wasm_valtype_vec_new_empty(&results);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_0_1(
+  own wasm_valtype_t* r
+) {
+  wasm_valtype_t* rs[1] = {r};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new_empty(&params);
+  wasm_valtype_vec_new(&results, 1, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_1_1(
+  own wasm_valtype_t* p, own wasm_valtype_t* r
+) {
+  wasm_valtype_t* ps[1] = {p};
+  wasm_valtype_t* rs[1] = {r};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 1, ps);
+  wasm_valtype_vec_new(&results, 1, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_2_1(
+  own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* r
+) {
+  wasm_valtype_t* ps[2] = {p1, p2};
+  wasm_valtype_t* rs[1] = {r};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 2, ps);
+  wasm_valtype_vec_new(&results, 1, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_3_1(
+  own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
+  own wasm_valtype_t* r
+) {
+  wasm_valtype_t* ps[3] = {p1, p2, p3};
+  wasm_valtype_t* rs[1] = {r};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 3, ps);
+  wasm_valtype_vec_new(&results, 1, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_0_2(
+  own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+  wasm_valtype_t* rs[2] = {r1, r2};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new_empty(&params);
+  wasm_valtype_vec_new(&results, 2, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_1_2(
+  own wasm_valtype_t* p, own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+  wasm_valtype_t* ps[1] = {p};
+  wasm_valtype_t* rs[2] = {r1, r2};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 1, ps);
+  wasm_valtype_vec_new(&results, 2, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_2_2(
+  own wasm_valtype_t* p1, own wasm_valtype_t* p2,
+  own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+  wasm_valtype_t* ps[2] = {p1, p2};
+  wasm_valtype_t* rs[2] = {r1, r2};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 2, ps);
+  wasm_valtype_vec_new(&results, 2, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+static inline own wasm_functype_t* wasm_functype_new_3_2(
+  own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3,
+  own wasm_valtype_t* r1, own wasm_valtype_t* r2
+) {
+  wasm_valtype_t* ps[3] = {p1, p2, p3};
+  wasm_valtype_t* rs[2] = {r1, r2};
+  wasm_valtype_vec_t params, results;
+  wasm_valtype_vec_new(&params, 3, ps);
+  wasm_valtype_vec_new(&results, 2, rs);
+  return wasm_functype_new(&params, &results);
+}
+
+
+// Value construction short-hands
+
+static inline void wasm_val_init_ptr(own wasm_val_t* out, void* p) {
+#if UINTPTR_MAX == UINT32_MAX
+  out->kind = WASM_I32;
+  out->of.i32 = (intptr_t)p;
+#elif UINTPTR_MAX == UINT64_MAX
+  out->kind = WASM_I64;
+  out->of.i64 = (intptr_t)p;
+#endif
+}
+
+static inline void* wasm_val_ptr(const wasm_val_t* val) {
+#if UINTPTR_MAX == UINT32_MAX
+  return (void*)(intptr_t)val->of.i32;
+#elif UINTPTR_MAX == UINT64_MAX
+  return (void*)(intptr_t)val->of.i64;
+#endif
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#undef own
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // #ifdef WASM_H

+ 3 - 0
core/iwasm/include/wasm_export.h

@@ -43,10 +43,13 @@ extern "C" {
 #define native_raw_set_return(val) *raw_ret = (val)
 
 
+#ifndef WASM_MODULE_T_DEFINED
+#define WASM_MODULE_T_DEFINED
 /* Uninstantiated WASM module loaded from WASM binary file
    or AoT binary file*/
 struct WASMModuleCommon;
 typedef struct WASMModuleCommon *wasm_module_t;
+#endif
 
 /* Instantiated WASM module */
 struct WASMModuleInstanceCommon;

+ 2 - 0
core/iwasm/interpreter/wasm_loader.c

@@ -1095,9 +1095,11 @@ load_global_import(const WASMModule *parent_module,
 #endif
 
     if (!ret) {
+#if WASM_ENABLE_SPEC_TEST != 0
         set_error_buf_v(error_buf, error_buf_size,
                         "unknown import or incompatible import type");
         return false;
+#endif
     }
 
     global->module_name = sub_module_name;

+ 0 - 3
core/iwasm/interpreter/wasm_runtime.c

@@ -995,9 +995,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
                                        error_buf, error_buf_size))) {
         return NULL;
     }
-
-    LOG_DEBUG("Instantiate a module %p -> %p", module, module_inst);
-
     memset(module_inst, 0, (uint32)sizeof(WASMModuleInstance));
 
     module_inst->module = module;

+ 1 - 0
core/shared/utils/bh_platform.h

@@ -15,6 +15,7 @@
 #include "bh_list.h"
 #include "bh_log.h"
 #include "bh_queue.h"
+#include "bh_vector.h"
 #include "runtime_timer.h"
 
 

+ 19 - 19
core/shared/utils/bh_vector.c

@@ -27,7 +27,7 @@ extend_vector(Vector *vector, uint32 length)
 {
     uint8 *data;
 
-    if (length <= vector->max_elements)
+    if (length <= vector->max_elems)
         return true;
 
     if (length < vector->size_elem * 3 / 2)
@@ -37,10 +37,10 @@ extend_vector(Vector *vector, uint32 length)
         return false;
     }
 
-    memcpy(data, vector->data, vector->size_elem * vector->max_elements);
+    memcpy(data, vector->data, vector->size_elem * vector->max_elems);
     BH_FREE(vector->data);
     vector->data = data;
-    vector->max_elements = length;
+    vector->max_elems = length;
     return true;
 }
 
@@ -62,8 +62,8 @@ bh_vector_init(Vector *vector, uint32 init_length, uint32 size_elem)
     }
 
     vector->size_elem = size_elem;
-    vector->max_elements = init_length;
-    vector->num_elements = 0;
+    vector->max_elems = init_length;
+    vector->num_elems = 0;
     return true;
 }
 
@@ -75,7 +75,7 @@ bh_vector_set(Vector *vector, uint32 index, const void *elem_buf)
         return false;
     }
 
-    if (index >= vector->num_elements) {
+    if (index >= vector->num_elems) {
         LOG_ERROR("Set vector elem failed: invalid elem index.\n");
         return false;
     }
@@ -92,7 +92,7 @@ bool bh_vector_get(const Vector *vector, uint32 index, void *elem_buf)
         return false;
     }
 
-    if (index >= vector->num_elements) {
+    if (index >= vector->num_elems) {
         LOG_ERROR("Get vector elem failed: invalid elem index.\n");
         return false;
     }
@@ -112,24 +112,24 @@ bool bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf)
         return false;
     }
 
-    if (index >= vector->num_elements) {
+    if (index >= vector->num_elems) {
         LOG_ERROR("Insert vector elem failed: invalid elem index.\n");
         return false;
     }
 
-    if (!extend_vector(vector, vector->num_elements + 1)) {
+    if (!extend_vector(vector, vector->num_elems + 1)) {
         LOG_ERROR("Insert vector elem failed: extend vector failed.\n");
         return false;
     }
 
-    p = vector->data + vector->size_elem * vector->num_elements;
-    for (i = vector->num_elements - 1; i > index; i--) {
+    p = vector->data + vector->size_elem * vector->num_elems;
+    for (i = vector->num_elems - 1; i > index; i--) {
         memcpy(p, p - vector->size_elem, vector->size_elem);
         p -= vector->size_elem;
     }
 
     memcpy(p, elem_buf, vector->size_elem);
-    vector->num_elements++;
+    vector->num_elems++;
     return true;
 }
 
@@ -140,14 +140,14 @@ bool bh_vector_append(Vector *vector, const void *elem_buf)
         return false;
     }
 
-    if (!extend_vector(vector, vector->num_elements + 1)) {
+    if (!extend_vector(vector, vector->num_elems + 1)) {
         LOG_ERROR("Append ector elem failed: extend vector failed.\n");
         return false;
     }
 
-    memcpy(vector->data + vector->size_elem * vector->num_elements,
+    memcpy(vector->data + vector->size_elem * vector->num_elems,
            elem_buf, vector->size_elem);
-    vector->num_elements++;
+    vector->num_elems++;
     return true;
 }
 
@@ -162,7 +162,7 @@ bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
         return false;
     }
 
-    if (index >= vector->num_elements) {
+    if (index >= vector->num_elems) {
         LOG_ERROR("Remove vector elem failed: invalid elem index.\n");
         return false;
     }
@@ -173,19 +173,19 @@ bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
         memcpy(old_elem_buf, p, vector->size_elem);
     }
 
-    for (i = index; i < vector->num_elements - 1; i++) {
+    for (i = index; i < vector->num_elems - 1; i++) {
         memcpy(p, p + vector->size_elem, vector->size_elem);
         p += vector->size_elem;
     }
 
-    vector->num_elements--;
+    vector->num_elems--;
     return true;
 }
 
 uint32
 bh_vector_size(const Vector *vector)
 {
-    return vector ? vector->num_elements : 0;
+    return vector ? vector->num_elems : 0;
 }
 
 bool

+ 5 - 5
core/shared/utils/bh_vector.h

@@ -15,14 +15,14 @@ extern "C" {
 #define DEFAULT_VECTOR_INIT_SIZE 8
 
 typedef struct Vector {
-    /* size of each element */
-    uint32 size_elem;
     /* max element number */
-    uint32 max_elements;
-    /* current element num */
-    uint32 num_elements;
+    size_t max_elems;
     /* vector data allocated */
     uint8 *data;
+    /* current element num */
+    size_t num_elems;
+    /* size of each element */
+    size_t size_elem;
 } Vector;
 
 /**

+ 77 - 0
doc/wasm_c_api.md

@@ -0,0 +1,77 @@
+All samples come from the commit 340fd9528cc3b26d22fe30ee1628c8c3f2b8c53b
+of [wasm-c-api][https://github.com/WebAssembly/wasm-c-api].
+
+Every user should be familiar with *APIs* listed in
+[wasm.h][https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h].
+
+all [examples][https://github.com/WebAssembly/wasm-c-api/tree/master/example] are
+very helpful for learning.
+
+Currently, we support partial of *APIs* and are going to support the rest of
+them in next releases.
+
+Supported APIs:
+
+``` c
+/* wasm_bytevec_t APIs ... */
+
+wasm_engine_t *wasm_engine_new();
+wasm_engine_t *wasm_engine_new_with_args(mem_alloc_type_t, const MemAllocOption*, runtime_mode_e);
+void wasm_engine_delete(wasm_engine_t *);
+
+wasm_store_t *wasm_store_new(wasm_engine_t *);
+void wasm_store_delete(wasm_store_t *);
+
+/* wasm_valtype_t APIs ... */
+/* wasm_valtype_vec_t APIs ... */
+/* wasm_functype_vec_t APIs ... */
+/* wasm_globaltype_vec_t APIs ... */
+/* wasm_val_t APIs ... */
+/* wasm_trap_t partial APIs ... */
+
+wasm_module_t *wasm_module_new(wasm_store_t *, const wasm_byte_vec_t *);
+void wasm_module_delete(wasm_module_t *);
+
+wasm_func_t *wasm_func_new(wasm_store_t *, const wasm_functype_t *, wasm_func_callback_t);
+wasm_func_t *wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *, wasm_func_callback_with_env_t, void *env, void (*finalizer)(void *));
+void wasm_func_delete(wasm_func_t *);
+wasm_fucn_t *wasm_func_copy(const wasm_func_t *);
+wasm_functype_t *wasm_func_type(const wasm_func_t *);
+wasm_trap_t * wasm_func_call(const wasm_func_t *, const wasm_val_t params[], wasm_val_t results[]);
+size_t wasm_func_param_arity(const wasm_func_t *);
+size_t wasm_func_result_arity(const wasm_func_t *);
+
+wasm_global_t *wasm_global_new(wasm_store_t *, const wasm_globaltype_t *, const wasm_val_t *);
+wasm_global_t * wasm_global_copy(const wasm_global_t *);
+void wasm_global_delete(wasm_global_t *);
+bool wasm_global_same(const wasm_global_t *, const wasm_global_t *);
+void wasm_global_set(wasm_global_t *, const wasm_val_t *);
+void wasm_global_get(const wasm_global_t *, wasm_val_t *out);
+wasm_globaltype_t * wasm_global_type(const wasm_global_t *);
+
+wasm_instance_t *wasm_instance_new(wasm_store_t *, const wasm_module_t *, const wasm_extern_t *const imports[], wasm_trap_t **traps);
+void wasm_instance_delete(wasm_instance_t *);
+void wasm_instance_exports(const wasm_instance_t *, wasm_extern_vec_t *out);
+
+/* wasm_extern_t APIs */
+```
+
+Unsupported APIs:
+
+``` c
+/* wasm_tabletype_t APIs */
+/* wasm_memorytype_t APIs */
+/* wasm_externtype_t APIs */
+/* wasm_importtype_t APIs */
+/* wasm_exporttype_t APIs */
+/* wasm_ref_t APIs */
+/* wasm_shared_##name##_t APIs */
+
+WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);
+WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
+WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
+WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
+
+/* wasm_table_t APIs */
+/* wasm_memory_t APIs */
+```

+ 1 - 2
samples/multi-module/CMakeLists.txt

@@ -3,7 +3,6 @@
 
 cmake_minimum_required(VERSION 2.8)
 project(multi_module)
-set(CMAKE_VERBOSE_MAKEFILE on)
 
 ################  runtime settings  ################
 set(WAMR_BUILD_PLATFORM "linux")
@@ -18,7 +17,7 @@ set(WAMR_BUILD_INTERP 1)
 set(WAMR_BUILD_AOT 0)
 set(WAMR_BUILD_JIT 0)
 set(WAMR_BUILD_LIBC_BUILTIN 1)
-set(WAMR_BUILD_LIBC_WASI 1)
+set(WAMR_BUILD_LIBC_WASI 0)
 set(WAMR_BUILD_FAST_INTERP 0)
 set(WAMR_BUILD_MULTI_MODULE 1)
 

+ 89 - 0
samples/wasm-c-api/CMakeLists.txt

@@ -0,0 +1,89 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.8)
+project(c-api)
+
+if(NOT CMAKE_BUILD_TYPE)
+  set(CMAKE_BUILD_TYPE Release)
+endif()
+################  runtime settings  ################
+set(WAMR_BUILD_PLATFORM "linux")
+
+# Resetdefault linker flags
+set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+# WAMR features switch
+set(WAMR_BUILD_TARGET "X86_64")
+
+if(NOT DEFINED WAMR_BUILD_INTERP)
+  set(WAMR_BUILD_INTERP 1)
+endif()
+
+if(NOT DEFINED WAMR_BUILD_AOT)
+  set(WAMR_BUILD_AOT 0)
+endif()
+
+if(NOT DEFINED WAMR_BUILD_JOT)
+  set(WAMR_BUILD_JIT 0)
+endif()
+
+set(WAMR_BUILD_LIBC_BUILTIN 1)
+set(WAMR_BUILD_LIBC_WASI 0)
+
+if(NOT DEFINED WAMR_BUILD_FAST_INTERP)
+  set(WAMR_BUILD_FAST_INTERP 0)
+endif()
+
+# compiling and linking flags
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -mindirect-branch-register")
+
+# build out vmlib
+set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
+set(WAMRC ${WAMR_ROOT_DIR}/wamr-compiler/build/wamrc)
+include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
+
+add_library(vmlib STATIC ${WAMR_RUNTIME_LIB_SOURCE})
+################################################
+
+################  application related  ################
+file(GLOB SOURCES src/*.c)
+add_library(c-api ${SOURCES})
+target_include_directories(c-api
+  PRIVATE ${C_API_PATH}/include
+)
+target_link_libraries(c-api PRIVATE vmlib -lpthread -lm)
+
+foreach(SRC ${SOURCES})
+  get_filename_component(APPNAME ${SRC} NAME_WE)
+
+  # build executable for each .c
+  add_executable(${APPNAME} ${SRC})
+  message("create executable about ${APPNAME}")
+  target_link_libraries(${APPNAME} c-api)
+
+  # copy .wasm
+  add_custom_command(TARGET ${APPNAME} POST_BUILD
+      COMMAND ${CMAKE_COMMAND} -E copy
+                  ${CMAKE_CURRENT_SOURCE_DIR}/src/${APPNAME}.wasm
+                  ${PROJECT_BINARY_DIR}/
+      BYPRODUCTS ${APPNAME}.wasm
+      COMMENT "Copy ${SRC} to the output directory"
+  )
+
+  # generate .aot file
+  if(${WAMR_BUILD_AOT} EQUAL 1)
+    if(EXISTS ${WAMRC})
+      add_custom_command(TARGET ${APPNAME} POST_BUILD
+          COMMAND ${WAMRC} -o ${APPNAME}.aot
+              ${CMAKE_CURRENT_SOURCE_DIR}/src/${APPNAME}.wasm
+          BYPRODUCTS ${APPNAME}.aot
+          COMMENT "generate a aot file ${APPNAME}.aot"
+      )
+    endif()
+  endif()
+
+endforeach(SRC ${SOURCES})
+################################################

+ 39 - 0
samples/wasm-c-api/README.md

@@ -0,0 +1,39 @@
+WAMR supports *wasm-c-api* in both *interpreter* mode and *aot* mode. By default,
+all samples are compiled and run in "interpreter" mode.
+
+``` shell
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make
+$ # it will build a library with c-api supporting.
+$ # Also copy *.wasm from ../src/
+$ # and generate executable files
+$ # now, it is ok to run samples
+$ ./hello
+$ ...
+$ ./global
+$ ...
+$ ./callback
+$ ...
+```
+
+They can be compiled and run in *aot* mode when some compiling flags are given.
+
+``` shell
+$ mkdir build
+$ cd build
+$ cmake -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 ..
+$ make
+$ # it will build a library with c-api supporting.
+$ # Also copy *.wasm from ../src/
+$ # and transform *.wasm to *.aot
+$ # and generate executable files
+$ # now, it is ok to run samples
+$ ./hello
+$ ...
+$ ./global
+$ ...
+$ ./callback
+$ ...
+```

+ 168 - 0
samples/wasm-c-api/src/callback.c

@@ -0,0 +1,168 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "wasm_c_api.h"
+
+#define own
+
+// Print a Wasm value
+void wasm_val_print(wasm_val_t val) {
+  switch (val.kind) {
+    case WASM_I32: {
+      printf("%" PRIu32, val.of.i32);
+    } break;
+    case WASM_I64: {
+      printf("%" PRIu64, val.of.i64);
+    } break;
+    case WASM_F32: {
+      printf("%f", val.of.f32);
+    } break;
+    case WASM_F64: {
+      printf("%g", val.of.f64);
+    } break;
+    case WASM_ANYREF:
+    case WASM_FUNCREF: {
+      if (val.of.ref == NULL) {
+        printf("null");
+      } else {
+        printf("ref(%p)", val.of.ref);
+      }
+    } break;
+  }
+}
+
+// A function to be called from Wasm code.
+own wasm_trap_t* print_callback(
+  const wasm_val_t args[], wasm_val_t results[]
+) {
+  printf("Calling back...\n> ");
+  wasm_val_print(args[0]);
+  printf("\n");
+
+  wasm_val_copy(&results[0], &args[0]);
+  return NULL;
+}
+
+
+// A function closure.
+own wasm_trap_t* closure_callback(
+  void* env, const wasm_val_t args[], wasm_val_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;
+  return NULL;
+}
+
+
+int main(int argc, const char* argv[]) {
+  // Initialize.
+  printf("Initializing...\n");
+  wasm_engine_t* engine = wasm_engine_new();
+  wasm_store_t* store = wasm_store_new(engine);
+
+  // Load binary.
+  printf("Loading binary...\n");
+  FILE* file = fopen("callback.wasm", "rb");
+  if (!file) {
+    printf("> Error loading module!\n");
+    return 1;
+  }
+  fseek(file, 0L, SEEK_END);
+  size_t file_size = ftell(file);
+  fseek(file, 0L, SEEK_SET);
+  wasm_byte_vec_t binary;
+  wasm_byte_vec_new_uninitialized(&binary, file_size);
+  if (fread(binary.data, file_size, 1, file) != 1) {
+    printf("> Error loading module!\n");
+    return 1;
+  }
+  fclose(file);
+
+  // Compile.
+  printf("Compiling module...\n");
+  own wasm_module_t* module = wasm_module_new(store, &binary);
+  if (!module) {
+    printf("> Error compiling module!\n");
+    return 1;
+  }
+
+  wasm_byte_vec_delete(&binary);
+
+  // Create external print functions.
+  printf("Creating callback...\n");
+  own wasm_functype_t* print_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32());
+  own wasm_func_t* print_func = wasm_func_new(store, print_type, print_callback);
+
+  int i = 42;
+  own wasm_functype_t* closure_type = wasm_functype_new_0_1(wasm_valtype_new_i32());
+  own wasm_func_t* closure_func = wasm_func_new_with_env(store, closure_type, closure_callback, &i, NULL);
+
+  wasm_functype_delete(print_type);
+  wasm_functype_delete(closure_type);
+
+  // Instantiate.
+  printf("Instantiating module...\n");
+  const wasm_extern_t* imports[] = {
+    wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func)
+  };
+  own wasm_instance_t* instance =
+    wasm_instance_new(store, module, imports, NULL);
+  if (!instance) {
+    printf("> Error instantiating module!\n");
+    return 1;
+  }
+
+  wasm_func_delete(print_func);
+  wasm_func_delete(closure_func);
+
+  // Extract export.
+  printf("Extracting export...\n");
+  own wasm_extern_vec_t exports;
+  wasm_instance_exports(instance, &exports);
+  if (exports.size == 0) {
+    printf("> Error accessing exports!\n");
+    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");
+  wasm_val_t args[2];
+  args[0].kind = WASM_I32;
+  args[0].of.i32 = 3;
+  args[1].kind = WASM_I32;
+  args[1].of.i32 = 4;
+  wasm_val_t results[1];
+  if (wasm_func_call(run_func, args, results)) {
+    printf("> Error calling function!\n");
+    return 1;
+  }
+
+  wasm_extern_vec_delete(&exports);
+
+  // Print result.
+  printf("Printing result...\n");
+  printf("> %u\n", results[0].of.i32);
+
+  // Shut down.
+  printf("Shutting down...\n");
+  wasm_store_delete(store);
+  wasm_engine_delete(engine);
+
+  // All done.
+  printf("Done.\n");
+  return 0;
+}

BIN
samples/wasm-c-api/src/callback.wasm


+ 10 - 0
samples/wasm-c-api/src/callback.wat

@@ -0,0 +1,10 @@
+(module
+  (func $print (import "" "print") (param i32) (result i32))
+  (func $closure (import "" "closure") (result i32))
+  (func (export "run") (param $x i32) (param $y i32) (result i32)
+    (i32.add
+      (call $print (i32.add (local.get $x) (local.get $y)))
+      (call $closure)
+    )
+  )
+)

+ 236 - 0
samples/wasm-c-api/src/global.c

@@ -0,0 +1,236 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "wasm_c_api.h"
+
+#define own
+
+wasm_global_t* get_export_global(const wasm_extern_vec_t* exports, size_t i) {
+  if (exports->size <= i || !wasm_extern_as_global(exports->data[i])) {
+    printf("> Error accessing global export %zu!\n", i);
+    exit(1);
+  }
+  return wasm_extern_as_global(exports->data[i]);
+}
+
+wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) {
+  if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) {
+    printf("> Error accessing function export %zu!\n", i);
+    exit(1);
+  }
+  return wasm_extern_as_func(exports->data[i]);
+}
+
+
+#define check(val, type, expected) \
+  if (val.of.type != expected) { \
+    printf("> Error reading value\n"); \
+    exit(1); \
+  }
+
+#define check_global(global, type, expected) \
+  { \
+    wasm_val_t val; \
+    wasm_global_get(global, &val); \
+    check(val, type, expected); \
+  }
+
+#define check_call(func, type, expected) \
+  { \
+    wasm_val_t results[1]; \
+    wasm_func_call(func, NULL, results); \
+    check(results[0], type, expected); \
+  }
+
+
+int main(int argc, const char* argv[]) {
+  // Initialize.
+  printf("Initializing...\n");
+  wasm_engine_t* engine = wasm_engine_new();
+  wasm_store_t* store = wasm_store_new(engine);
+
+  // Load binary.
+  printf("Loading binary...\n");
+#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
+  FILE* file = fopen("global.aot", "rb");
+#else
+  FILE* file = fopen("global.wasm", "rb");
+#endif
+  if (!file) {
+    printf("> Error loading module!\n");
+    return 1;
+  }
+  fseek(file, 0L, SEEK_END);
+  size_t file_size = ftell(file);
+  fseek(file, 0L, SEEK_SET);
+  wasm_byte_vec_t binary;
+  wasm_byte_vec_new_uninitialized(&binary, file_size);
+  if (fread(binary.data, file_size, 1, file) != 1) {
+    printf("> Error loading module!\n");
+    return 1;
+  }
+  fclose(file);
+
+  // Compile.
+  printf("Compiling module...\n");
+  own wasm_module_t* module = wasm_module_new(store, &binary);
+  if (!module) {
+    printf("> Error compiling module!\n");
+    return 1;
+  }
+
+  wasm_byte_vec_delete(&binary);
+
+  // Create external globals.
+  printf("Creating globals...\n");
+  own wasm_globaltype_t* const_f32_type = wasm_globaltype_new(
+    wasm_valtype_new(WASM_F32), WASM_CONST);
+  own wasm_globaltype_t* const_i64_type = wasm_globaltype_new(
+    wasm_valtype_new(WASM_I64), WASM_CONST);
+  own wasm_globaltype_t* var_f32_type = wasm_globaltype_new(
+    wasm_valtype_new(WASM_F32), WASM_VAR);
+  own wasm_globaltype_t* var_i64_type = wasm_globaltype_new(
+    wasm_valtype_new(WASM_I64), WASM_VAR);
+
+  wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}};
+  own wasm_global_t* const_f32_import =
+    wasm_global_new(store, const_f32_type, &val_f32_1);
+  wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}};
+  own wasm_global_t* const_i64_import =
+    wasm_global_new(store, const_i64_type, &val_i64_2);
+  wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}};
+  own wasm_global_t* var_f32_import =
+    wasm_global_new(store, var_f32_type, &val_f32_3);
+  wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}};
+  own wasm_global_t* var_i64_import =
+    wasm_global_new(store, var_i64_type, &val_i64_4);
+
+  wasm_globaltype_delete(const_f32_type);
+  wasm_globaltype_delete(const_i64_type);
+  wasm_globaltype_delete(var_f32_type);
+  wasm_globaltype_delete(var_i64_type);
+
+  // Instantiate.
+  printf("Instantiating module...\n");
+  const wasm_extern_t* imports[] = {
+    wasm_global_as_extern(const_f32_import),
+    wasm_global_as_extern(const_i64_import),
+    wasm_global_as_extern(var_f32_import),
+    wasm_global_as_extern(var_i64_import)
+  };
+  own wasm_instance_t* instance =
+    wasm_instance_new(store, module, imports, NULL);
+  if (!instance) {
+    printf("> Error instantiating module!\n");
+    return 1;
+  }
+
+  wasm_module_delete(module);
+
+  // Extract export.
+  printf("Extracting exports...\n");
+  own wasm_extern_vec_t exports;
+  wasm_instance_exports(instance, &exports);
+  size_t i = 0;
+  wasm_global_t* const_f32_export = get_export_global(&exports, i++);
+  wasm_global_t* const_i64_export = get_export_global(&exports, i++);
+  wasm_global_t* var_f32_export = get_export_global(&exports, i++);
+  wasm_global_t* var_i64_export = get_export_global(&exports, i++);
+  wasm_func_t* get_const_f32_import = get_export_func(&exports, i++);
+  wasm_func_t* get_const_i64_import = get_export_func(&exports, i++);
+  wasm_func_t* get_var_f32_import = get_export_func(&exports, i++);
+  wasm_func_t* get_var_i64_import = get_export_func(&exports, i++);
+  wasm_func_t* get_const_f32_export = get_export_func(&exports, i++);
+  wasm_func_t* get_const_i64_export = get_export_func(&exports, i++);
+  wasm_func_t* get_var_f32_export = get_export_func(&exports, i++);
+  wasm_func_t* get_var_i64_export = get_export_func(&exports, i++);
+  wasm_func_t* set_var_f32_import = get_export_func(&exports, i++);
+  wasm_func_t* set_var_i64_import = get_export_func(&exports, i++);
+  wasm_func_t* set_var_f32_export = get_export_func(&exports, i++);
+  wasm_func_t* set_var_i64_export = get_export_func(&exports, i++);
+
+  // Try cloning.
+  own wasm_global_t* copy = wasm_global_copy(var_f32_import);
+  assert(wasm_global_same(var_f32_import, copy));
+  wasm_global_delete(copy);
+
+  // Interact.
+  printf("Accessing globals...\n");
+
+  // Check initial values.
+  check_global(const_f32_import, f32, 1);
+  check_global(const_i64_import, i64, 2);
+  check_global(var_f32_import, f32, 3);
+  check_global(var_i64_import, i64, 4);
+  check_global(const_f32_export, f32, 5);
+  check_global(const_i64_export, i64, 6);
+  check_global(var_f32_export, f32, 7);
+  check_global(var_i64_export, i64, 8);
+
+  check_call(get_const_f32_import, f32, 1);
+  check_call(get_const_i64_import, i64, 2);
+  check_call(get_var_f32_import, f32, 3);
+  check_call(get_var_i64_import, i64, 4);
+  check_call(get_const_f32_export, f32, 5);
+  check_call(get_const_i64_export, i64, 6);
+  check_call(get_var_f32_export, f32, 7);
+  check_call(get_var_i64_export, i64, 8);
+
+  // Modify variables through API and check again.
+  wasm_val_t val33 = {.kind = WASM_F32, .of = {.f32 = 33}};
+  wasm_global_set(var_f32_import, &val33);
+  wasm_val_t val34 = {.kind = WASM_I64, .of = {.i64 = 34}};
+  wasm_global_set(var_i64_import, &val34);
+  wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37}};
+  wasm_global_set(var_f32_export, &val37);
+  wasm_val_t val38 = {.kind = WASM_I64, .of = {.i64 = 38}};
+  wasm_global_set(var_i64_export, &val38);
+
+  check_global(var_f32_import, f32, 33);
+  check_global(var_i64_import, i64, 34);
+  check_global(var_f32_export, f32, 37);
+  check_global(var_i64_export, i64, 38);
+
+  check_call(get_var_f32_import, f32, 33);
+  check_call(get_var_i64_import, i64, 34);
+  check_call(get_var_f32_export, f32, 37);
+  check_call(get_var_i64_export, i64, 38);
+
+  // Modify variables through calls and check again.
+  wasm_val_t args73[] = { {.kind = WASM_F32, .of = {.f32 = 73}} };
+  wasm_func_call(set_var_f32_import, args73, NULL);
+  wasm_val_t args74[] = { {.kind = WASM_I64, .of = {.i64 = 74}} };
+  wasm_func_call(set_var_i64_import, args74, NULL);
+  wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77}} };
+  wasm_func_call(set_var_f32_export, args77, NULL);
+  wasm_val_t args78[] = { {.kind = WASM_I64, .of = {.i64 = 78}} };
+  wasm_func_call(set_var_i64_export, args78, NULL);
+
+  check_global(var_f32_import, f32, 73);
+  check_global(var_i64_import, i64, 74);
+  check_global(var_f32_export, f32, 77);
+  check_global(var_i64_export, i64, 78);
+
+  check_call(get_var_f32_import, f32, 73);
+  check_call(get_var_i64_import, i64, 74);
+  check_call(get_var_f32_export, f32, 77);
+  check_call(get_var_i64_export, i64, 78);
+
+  wasm_global_delete(const_f32_import);
+  wasm_global_delete(const_i64_import);
+  wasm_global_delete(var_f32_import);
+  wasm_global_delete(var_i64_import);
+  wasm_extern_vec_delete(&exports);
+  wasm_instance_delete(instance);
+
+  // Shut down.
+  printf("Shutting down...\n");
+  wasm_store_delete(store);
+  wasm_engine_delete(engine);
+
+  // All done.
+  printf("Done.\n");
+  return 0;
+}

BIN
samples/wasm-c-api/src/global.wasm


+ 27 - 0
samples/wasm-c-api/src/global.wat

@@ -0,0 +1,27 @@
+(module
+  (global $f32_import (import "" "const f32") f32)
+  (global $i64_import (import "" "const i64") i64)
+  (global $mut_f32_import (import "" "var f32") (mut f32))
+  (global $mut_i64_import (import "" "var i64") (mut i64))
+
+  (global $f32_export (export "const f32") f32 (f32.const 5))
+  (global $i64_export (export "const i64") i64 (i64.const 6))
+  (global $mut_f32_export (export "var f32") (mut f32) (f32.const 7))
+  (global $mut_i64_export (export "var i64") (mut i64) (i64.const 8))
+
+  (func (export "get const f32 import") (result f32) (global.get $f32_import))
+  (func (export "get const i64 import") (result i64) (global.get $i64_import))
+  (func (export "get var f32 import") (result f32) (global.get $mut_f32_import))
+  (func (export "get var i64 import") (result i64) (global.get $mut_i64_import))
+
+  (func (export "get const f32 export") (result f32) (global.get $f32_export))
+  (func (export "get const i64 export") (result i64) (global.get $i64_export))
+  (func (export "get var f32 export") (result f32) (global.get $mut_f32_export))
+  (func (export "get var i64 export") (result i64) (global.get $mut_i64_export))
+
+  (func (export "set var f32 import") (param f32) (global.set $mut_f32_import (local.get 0)))
+  (func (export "set var i64 import") (param i64) (global.set $mut_i64_import (local.get 0)))
+
+  (func (export "set var f32 export") (param f32) (global.set $mut_f32_export (local.get 0)))
+  (func (export "set var f64 export") (param i64) (global.set $mut_i64_export (local.get 0)))
+)

+ 112 - 0
samples/wasm-c-api/src/hello.c

@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "wasm_c_api.h"
+
+#define own
+
+// A function to be called from Wasm code.
+own wasm_trap_t* hello_callback(
+  const wasm_val_t args[], wasm_val_t results[]
+) {
+  printf("Calling back...\n");
+  printf("> Hello World!\n");
+  return NULL;
+}
+
+
+int main(int argc, const char* argv[]) {
+  // Initialize.
+  printf("Initializing...\n");
+  wasm_engine_t* engine = wasm_engine_new();
+  wasm_store_t* store = wasm_store_new(engine);
+
+  // Load binary.
+  printf("Loading binary...\n");
+#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
+  FILE* file = fopen("hello.aot", "rb");
+#else
+  FILE* file = fopen("hello.wasm", "rb");
+#endif
+  if (!file) {
+    printf("> Error loading module!\n");
+    return 1;
+  }
+  fseek(file, 0L, SEEK_END);
+  size_t file_size = ftell(file);
+  fseek(file, 0L, SEEK_SET);
+  wasm_byte_vec_t binary;
+  wasm_byte_vec_new_uninitialized(&binary, file_size);
+  if (fread(binary.data, file_size, 1, file) != 1) {
+    printf("> Error loading module!\n");
+    return 1;
+  }
+  fclose(file);
+
+  // Compile.
+  printf("Compiling module...\n");
+  own wasm_module_t* module = wasm_module_new(store, &binary);
+  if (!module) {
+    printf("> Error compiling module!\n");
+    return 1;
+  }
+
+  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, 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;
+  wasm_instance_exports(instance, &exports);
+  if (exports.size == 0) {
+    printf("> Error accessing exports!\n");
+    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.
+  printf("Shutting down...\n");
+  wasm_store_delete(store);
+  wasm_engine_delete(engine);
+
+  // All done.
+  printf("Done.\n");
+  return 0;
+}

BIN
samples/wasm-c-api/src/hello.wasm


+ 4 - 0
samples/wasm-c-api/src/hello.wat

@@ -0,0 +1,4 @@
+(module
+  (func $hello (import "" "hello"))
+  (func (export "run") (call $hello))
+)