Quellcode durchsuchen

[instantiation linking] Create and import WASMGlobalInstance (#3914)

liang.he vor 1 Jahr
Ursprung
Commit
b18cb3b2cb

+ 8 - 2
core/iwasm/aot/aot_loader.c

@@ -2144,9 +2144,11 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
     AOTImportGlobal *import_globals;
     uint64 size;
     uint32 i, data_offset = 0;
+#if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_LIBC_BUILTIN != 0
     WASMGlobalImport tmp_global;
 #endif
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
 
     /* Allocate memory */
     size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count;
@@ -2167,6 +2169,7 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
             return false;
         }
 
+#if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_LIBC_BUILTIN != 0
         if (wasm_native_lookup_libc_builtin_global(
                 import_globals[i].module_name, import_globals[i].global_name,
@@ -2182,9 +2185,12 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
                 tmp_global.global_data_linked;
             import_globals[i].is_linked = true;
         }
-#else
-        import_globals[i].is_linked = false;
+        else
 #endif
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
+        {
+            import_globals[i].is_linked = false;
+        }
 
         import_globals[i].size =
             wasm_value_type_size(import_globals[i].type.val_type);

+ 200 - 94
core/iwasm/aot/aot_runtime.c

@@ -60,6 +60,7 @@ bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0);
 bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_base_addr_adj)
                  == 8);
 bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_start_off) == 16);
+bh_static_assert(offsetof(AOTModuleInstanceExtra, globals) == 24);
 
 bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3);
 
@@ -80,6 +81,14 @@ bh_static_assert(offsetof(AOTTinyFrame, func_index) == sizeof(uint32) * 0);
 bh_static_assert(offsetof(AOTTinyFrame, ip_offset) == sizeof(uint32) * 1);
 bh_static_assert(sizeof(AOTTinyFrame) == sizeof(uint32) * 2);
 
+bh_static_assert(offsetof(AOTGlobalInstance, initial_value) == 8);
+bh_static_assert(offsetof(AOTGlobalInstance, import_module_inst)
+                 == 8 + sizeof(WASMValue));
+bh_static_assert(offsetof(AOTGlobalInstance, import_global_inst)
+                 == 8 + sizeof(WASMValue) + 8);
+bh_static_assert(offsetof(AOTGlobalInstance, ref_type)
+                 == 8 + sizeof(WASMValue) + 16);
+
 static void
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 {
@@ -283,10 +292,20 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
                                         error_buf, error_buf_size)) {
                 return false;
             }
+
+            /*TODO: via WASMGlobalInstance->init_value ? */
             if (init_expr->u.global_index < module->import_global_count) {
+#if WASM_ENABLE_MULTI_MODULE != 0
                 PUT_REF_TO_ADDR(
                     addr, module->import_globals[init_expr->u.global_index]
                               .global_data_linked.gc_obj);
+#else
+                AOTModuleInstanceExtra *e =
+                    (AOTModuleInstanceExtra *)module_inst->e;
+                AOTGlobalInstance *global =
+                    e->globals + init_expr->u.global_index;
+                PUT_REF_TO_ADDR(addr, global->initial_value.gc_obj);
+#endif
             }
             else {
                 uint32 global_idx =
@@ -444,69 +463,142 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
 }
 #endif /* end of WASM_ENABLE_GC != 0 */
 
-static bool
-global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
-                   char *error_buf, uint32 error_buf_size)
+static AOTGlobalInstance *
+globals_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
+                    const WASMExternInstance *imports, uint32 import_count,
+                    char *error_buf, uint32 error_buf_size)
 {
     uint32 i;
-    InitializerExpression *init_expr;
     uint8 *p = module_inst->global_data;
-    AOTImportGlobal *import_global = module->import_globals;
-    AOTGlobal *global = module->globals;
+
+    uint64 total_size =
+        sizeof(AOTGlobalInstance)
+        * (uint64)(module->global_count + module->import_global_count);
+    AOTGlobalInstance *globals =
+        runtime_malloc(total_size, error_buf, error_buf_size);
+    if (!globals) {
+        return NULL;
+    }
 
     /* Initialize import global data */
-    for (i = 0; i < module->import_global_count; i++, import_global++) {
-        bh_assert(import_global->data_offset
+    AOTGlobalInstance *global = globals;
+    AOTImportGlobal *import_global_type = module->import_globals;
+    for (i = 0; i < module->import_global_count;
+         i++, import_global_type++, global++) {
+        global->type = import_global_type->type.val_type;
+        global->is_mutable = import_global_type->type.is_mutable;
+
+        bh_assert(import_global_type->data_offset
                   == (uint32)(p - module_inst->global_data));
-        init_global_data(p, import_global->type.val_type,
-                         &import_global->global_data_linked);
-        p += import_global->size;
+        global->data_offset = import_global_type->data_offset;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+        init_global_data(p, import_global_type->type.val_type,
+                         &import_global_type->global_data_linked);
+#else
+        const WASMExternInstance *extern_inst =
+            wasm_runtime_get_extern_instance(imports, import_count,
+                                             WASM_IMPORT_EXPORT_KIND_GLOBAL, i);
+        if (!extern_inst) {
+            LOG_ERROR("missing an import global(%s, %s)",
+                      import_global_type->module_name,
+                      import_global_type->global_name);
+            goto fail;
+        }
+
+        /* just in case */
+#ifndef NDEBUG
+        if (strcmp(import_global_type->global_name, extern_inst->field_name)) {
+            LOG_ERROR(
+                "mismatched import global name: expect \"%s\", got \"%s\"",
+                import_global_type->global_name, extern_inst->field_name);
+            goto fail;
+        }
+#endif
+
+        bh_memcpy_s(&global->initial_value, sizeof(WASMValue),
+                    &extern_inst->u.global->initial_value, sizeof(WASMValue));
+        global->import_module_inst =
+            (WASMModuleInstance *)extern_inst->dep_inst;
+        /* write into global_data */
+        init_global_data(p, global->type, &global->initial_value);
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
+
+        p += import_global_type->size;
     }
 
     /* Initialize defined global data */
-    for (i = 0; i < module->global_count; i++, global++) {
-        uint8 flag;
-        bh_assert(global->data_offset
+    AOTGlobal *global_type = module->globals;
+    for (i = 0; i < module->global_count; i++, global_type++, global++) {
+        global->type = global_type->type.val_type;
+        global->is_mutable = global_type->type.is_mutable;
+
+        bh_assert(global_type->data_offset
                   == (uint32)(p - module_inst->global_data));
-        init_expr = &global->init_expr;
-        flag = init_expr->init_expr_type;
+        global->data_offset = global_type->data_offset;
+
+        InitializerExpression *init_expr = &global_type->init_expr;
+        uint8 flag = init_expr->init_expr_type;
         switch (flag) {
             case INIT_EXPR_TYPE_GET_GLOBAL:
             {
                 if (!check_global_init_expr(module, init_expr->u.global_index,
                                             error_buf, error_buf_size)) {
-                    return false;
+                    goto fail;
                 }
-#if WASM_ENABLE_GC == 0
-                init_global_data(
-                    p, global->type.val_type,
-                    &module->import_globals[init_expr->u.global_index]
-                         .global_data_linked);
-#else
-                if (init_expr->u.global_index < module->import_global_count) {
+
+                uint32 global_index_in_expr = init_expr->u.global_index;
+                if (global_index_in_expr < module->import_global_count) {
+#if WASM_ENABLE_MULTI_MODULE != 0
+                    /* from WASMImportGlobal or WASMGlobal to global_data */
                     init_global_data(
-                        p, global->type.val_type,
-                        &module->import_globals[init_expr->u.global_index]
+                        p, global_type->type.val_type,
+                        &module->import_globals[global_index_in_expr]
                              .global_data_linked);
+#else
+                    /*
+                     * from WASMImportGlobal to WASMGlobalInstance
+                     * to global_data
+                     */
+                    global->initial_value =
+                        globals[global_index_in_expr].initial_value;
+                    init_global_data(p, global_type->type.val_type,
+                                     &global->initial_value);
+#endif /* WASM_ENABLE_MULTI_MODULE != 0*/
                 }
                 else {
-                    uint32 global_idx =
-                        init_expr->u.global_index - module->import_global_count;
-                    init_global_data(p, global->type.val_type,
-                                     &module->globals[global_idx].init_expr.u);
+#if WASM_ENABLE_GC == 0
+                    bh_assert(false
+                              && "only GC mode support using non-import global "
+                                 "in a constant expression");
+#endif
+                    uint32 adjusted_global_index_in_expr =
+                        global_index_in_expr - module->import_global_count;
+
+                    /*
+                     * from WASMGlobal to WASMGlobalInstance
+                     * to global_data
+                     */
+                    global->initial_value =
+                        module->globals[adjusted_global_index_in_expr]
+                            .init_expr.u;
+                    init_global_data(p, global_type->type.val_type,
+                                     &global->initial_value);
                 }
-#endif
+
                 break;
             }
 #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
             case INIT_EXPR_TYPE_REFNULL_CONST:
             {
+                /* no need to assign global->initial_value */
                 *(uint32 *)p = NULL_REF;
                 break;
             }
 #elif WASM_ENABLE_GC != 0
             case INIT_EXPR_TYPE_REFNULL_CONST:
             {
+                /* no need to assign global->initial_value */
                 WASMObjectRef gc_obj = NULL_REF;
                 PUT_REF_TO_ADDR(p, gc_obj);
                 break;
@@ -522,7 +614,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                     if (!(func_obj =
                               aot_create_func_obj(module_inst, func_idx, false,
                                                   error_buf, error_buf_size))) {
-                        return false;
+                        goto fail;
                     }
                 }
 
@@ -559,7 +651,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                           module->type_count, &module->rtt_type_lock))) {
                     set_error_buf(error_buf, error_buf_size,
                                   "create rtt object failed");
-                    return false;
+                    goto fail;
                 }
 
                 if (!(struct_obj = wasm_struct_obj_new_internal(
@@ -568,7 +660,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                           rtt_type))) {
                     set_error_buf(error_buf, error_buf_size,
                                   "create struct object failed");
-                    return false;
+                    goto fail;
                 }
 
                 if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
@@ -620,7 +712,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                           module->type_count, &module->rtt_type_lock))) {
                     set_error_buf(error_buf, error_buf_size,
                                   "create rtt object failed");
-                    return false;
+                    goto fail;
                 }
 
                 if (!(array_obj = wasm_array_obj_new_internal(
@@ -629,7 +721,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                           rtt_type, len, arr_init_val))) {
                     set_error_buf(error_buf, error_buf_size,
                                   "create array object failed");
-                    return false;
+                    goto fail;
                 }
 
                 if (flag == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
@@ -650,16 +742,22 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 #endif /* end of WASM_ENABLE_GC != 0 */
             default:
             {
-                init_global_data(p, global->type.val_type, &init_expr->u);
+                global->initial_value = init_expr->u;
+                init_global_data(p, global->type, &global->initial_value);
                 break;
             }
         }
-        p += global->size;
+
+        p += global_type->size;
     }
 
     bh_assert(module_inst->global_data_size
               == (uint32)(p - module_inst->global_data));
-    return true;
+
+    return globals;
+fail:
+    wasm_runtime_free(globals);
+    return NULL;
 }
 
 /**
@@ -839,7 +937,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
         /* Resolve table data base offset */
         /* TODO: The table64 current implementation assumes table max size
          * UINT32_MAX, so the offset conversion here is safe */
-        uint32 base_offset;
+        uint32 base_offset = 0;
         if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
             uint32 global_index = table_seg->offset.u.global_index;
             uint32 global_data_offset;
@@ -849,13 +947,10 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                 return false;
             }
 
-            if (global_index < module->import_global_count)
-                global_data_offset =
-                    module->import_globals[global_index].data_offset;
-            else
-                global_data_offset =
-                    module->globals[global_index - module->import_global_count]
-                        .data_offset;
+            /* since we have transfer data_offset into WASMGlobalInstance */
+            AOTModuleInstanceExtra *e =
+                (AOTModuleInstanceExtra *)module_inst->e;
+            global_data_offset = e->globals[global_index].data_offset;
 
             base_offset =
                 *(uint32 *)(module_inst->global_data + global_data_offset);
@@ -967,7 +1062,7 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
 #else
         wasm_runtime_free(memory);
 #endif
-#endif
+#endif /* WASM_ENABLE_MULTI_MODULE == 0 */
     }
 
     for (; mem_index < module->memory_count; mem_index++) {
@@ -2002,26 +2097,6 @@ fail:
     return ret;
 }
 
-static bool
-check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size)
-{
-    uint32 i;
-
-    /* init_func_ptrs() will go through import functions */
-
-    for (i = 0; i < module->import_global_count; i++) {
-        AOTImportGlobal *global = module->import_globals + i;
-        if (!global->is_linked) {
-            set_error_buf_v(error_buf, error_buf_size,
-                            "failed to link import global (%s, %s)",
-                            global->module_name, global->global_name);
-            return false;
-        }
-    }
-
-    return true;
-}
-
 AOTModuleInstance *
 aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
                 WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
@@ -2193,8 +2268,14 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         + module_inst_mem_inst_size;
     module_inst->global_data = p;
     module_inst->global_data_size = module->global_data_size;
-    if (!global_instantiate(module_inst, module, error_buf, error_buf_size))
-        goto fail;
+    extra->global_count = module->import_global_count + module->global_count;
+    if (extra->global_count > 0) {
+        extra->globals =
+            globals_instantiate(module_inst, module, imports, import_count,
+                                error_buf, error_buf_size);
+        if (!extra->globals)
+            goto fail;
+    }
 
     /* __heap_base */
     uint8 *aux_heap_base_global_data = NULL;
@@ -2223,9 +2304,6 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     if (!init_func_ptrs(module_inst, module, error_buf, error_buf_size))
         goto fail;
 
-    if (!check_linked_symbol(module, error_buf, error_buf_size))
-        goto fail;
-
     if (!create_exports(module_inst, module, error_buf, error_buf_size))
         goto fail;
 
@@ -2343,10 +2421,11 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
             &tbl_init_size, &tbl_max_size);
 
         if (!wasm_elem_is_declarative(table_init_data->mode)
-            && !wasm_reftype_is_subtype_of(
-                table_init_data->elem_type, table_init_data->elem_ref_type,
-                table->elem_type, table->elem_ref_type.elem_ref_type,
-                module->types, module->type_count)) {
+            && !wasm_reftype_is_subtype_of((uint8)table_init_data->elem_type,
+                                           table_init_data->elem_ref_type,
+                                           table->elem_type,
+                                           table->elem_ref_type.elem_ref_type,
+                                           module->types, module->type_count)) {
             set_error_buf(error_buf, error_buf_size,
                           "type mismatch: elements segment does not fit");
             goto fail;
@@ -2371,30 +2450,21 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         /* init vec(funcidx) or vec(expr) */
         if (table_init_data->offset.init_expr_type
             == INIT_EXPR_TYPE_GET_GLOBAL) {
-            uint32 data_offset;
+            uint32 data_offset = 0;
             if (!check_global_init_expr(module,
                                         table_init_data->offset.u.global_index,
                                         error_buf, error_buf_size)) {
                 goto fail;
             }
 
-            if (table_init_data->offset.u.global_index
-                < module->import_global_count) {
-                data_offset =
-                    module
-                        ->import_globals[table_init_data->offset.u.global_index]
-                        .data_offset;
-            }
-            else {
-                data_offset =
-                    module
-                        ->globals[table_init_data->offset.u.global_index
-                                  - module->import_global_count]
-                        .data_offset;
-            }
+            /* since we have transfer data_offset into WASMGlobalInstance */
+            AOTModuleInstanceExtra *e =
+                (AOTModuleInstanceExtra *)module_inst->e;
+            data_offset =
+                e->globals[table_init_data->offset.u.global_index].data_offset;
 
             table_init_data->offset.u.i32 =
-                *(uint32 *)(module_inst->global_data + data_offset);
+                *(int32 *)(module_inst->global_data + data_offset);
         }
 
         /* check offset since length might negative */
@@ -2416,7 +2486,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
             goto fail;
         }
 
-        for (j = 0; j < module->table_init_data_list[i]->value_count; j++) {
+        for (j = 0; j < table_init_data->value_count; j++) {
             if (!assign_table_init_value(
                     module_inst, module, &table_init_data->init_values[j],
                     table_data + table_init_data->offset.u.i32 + j, error_buf,
@@ -2539,6 +2609,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
         wasm_runtime_free(extra->functions);
     }
 
+    if (extra->globals) {
+        wasm_runtime_free(extra->globals);
+    }
+
     if (module_inst->func_ptrs)
         wasm_runtime_free(module_inst->func_ptrs);
 
@@ -5788,4 +5862,36 @@ aot_destroy_table(AOTTableInstance *table)
         return;
 
     wasm_runtime_free(table);
+}
+
+AOTGlobalInstance *
+aot_create_global(const AOTModule *module, AOTModuleInstance *dep_inst,
+                  WASMGlobalType *type)
+{
+    AOTGlobalInstance *global =
+        runtime_malloc(sizeof(AOTGlobalInstance), NULL, 0);
+    if (!global) {
+        return NULL;
+    }
+
+    global->type = type->val_type;
+    global->is_mutable = type->is_mutable;
+    global->import_module_inst = dep_inst;
+    /* empty global. set value later by wasm_set_global_value */
+    return global;
+}
+
+void
+aot_set_global_value(AOTGlobalInstance *global, const WASMValue *value)
+{
+    global->initial_value = *value;
+}
+
+void
+aot_destroy_global(AOTGlobalInstance *global)
+{
+    if (!global)
+        return;
+
+    wasm_runtime_free(global);
 }

+ 19 - 4
core/iwasm/aot/aot_runtime.h

@@ -37,6 +37,11 @@ extern "C" {
 #define WASM_FEATURE_FRAME_NO_FUNC_IDX (1 << 13)
 #define WASM_FEATURE_MULTI_MODULE (1 << 14)
 
+#define AOTGlobalInstance WASMGlobalInstance
+#define AOTMemoryInstance WASMMemoryInstance
+#define AOTTableInstance WASMTableInstance
+#define AOTModuleInstance WASMModuleInstance
+
 typedef enum AOTSectionType {
     AOT_SECTION_TYPE_TARGET_INFO = 0,
     AOT_SECTION_TYPE_INIT_DATA = 1,
@@ -127,6 +132,9 @@ typedef struct AOTModuleInstanceExtra {
     DefPointer(uint8 *, shared_heap_base_addr_adj);
     MemBound shared_heap_start_off;
 
+    DefPointer(AOTGlobalInstance *, globals);
+    uint32 global_count;
+
     WASMModuleInstanceExtraCommon common;
 
     /**
@@ -137,6 +145,7 @@ typedef struct AOTModuleInstanceExtra {
     ExportFuncMap *export_func_maps;
     AOTFunctionInstance **functions;
     uint32 function_count;
+
 #if WASM_ENABLE_MULTI_MODULE != 0
     bh_list sub_module_inst_list_head;
     bh_list *sub_module_inst_list;
@@ -363,10 +372,6 @@ typedef struct AOTModule {
 #endif
 } AOTModule;
 
-#define AOTMemoryInstance WASMMemoryInstance
-#define AOTTableInstance WASMTableInstance
-#define AOTModuleInstance WASMModuleInstance
-
 #if WASM_ENABLE_MULTI_MODULE != 0
 #define AOTSubModInstNode WASMSubModInstNode
 #endif
@@ -917,6 +922,16 @@ aot_set_table_elem(const AOTModule *module, AOTTableInstance *table,
 void
 aot_destroy_table(AOTTableInstance *table);
 
+AOTGlobalInstance *
+aot_create_global(const AOTModule *module, AOTModuleInstance *dep_inst,
+                  WASMGlobalType *type);
+
+void
+aot_set_global_value(AOTGlobalInstance *global, const WASMValue *value);
+
+void
+aot_destroy_global(AOTGlobalInstance *global);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 14 - 0
core/iwasm/common/wasm_native.h

@@ -110,6 +110,20 @@ void *
 wasm_native_lookup_quick_aot_entry(const WASMFuncType *func_type);
 #endif
 
+#if WASM_ENABLE_SPEC_TEST != 0
+bool
+wasm_runtime_create_extern_inst_for_spec_test(wasm_module_t module,
+                                              wasm_import_t *import_type,
+                                              WASMExternInstance *out);
+#endif
+
+#if WASM_ENABLE_WASI_TEST != 0
+bool
+wasm_runtime_create_extern_inst_for_wasi_test(wasm_module_t module,
+                                              wasm_import_t *import_type,
+                                              WASMExternInstance *out);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 197 - 101
core/iwasm/common/wasm_runtime_common.c

@@ -2051,40 +2051,38 @@ wasm_runtime_set_module_inst(WASMExecEnv *exec_env,
     wasm_exec_env_set_module_inst(exec_env, module_inst);
 }
 
-bool
+WASMGlobalInstance *
 wasm_runtime_get_export_global_inst(WASMModuleInstanceCommon *const module_inst,
-                                    char const *name,
-                                    wasm_global_inst_t *global_inst)
+                                    char const *name)
 {
+    if (!module_inst || !name) {
+        return NULL;
+    }
+
 #if WASM_ENABLE_INTERP != 0
     if (module_inst->module_type == Wasm_Module_Bytecode) {
         const WASMModuleInstance *wasm_module_inst =
             (const WASMModuleInstance *)module_inst;
         const WASMModule *wasm_module = wasm_module_inst->module;
-        uint32 i;
-        for (i = 0; i < wasm_module->export_count; i++) {
+
+        for (uint32 i = 0; i < wasm_module->export_count; i++) {
             const WASMExport *wasm_export = &wasm_module->exports[i];
-            if ((wasm_export->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL)
-                && !strcmp(wasm_export->name, name)) {
-                const WASMModuleInstanceExtra *e =
-                    (WASMModuleInstanceExtra *)wasm_module_inst->e;
-                const WASMGlobalInstance *global =
-                    &e->globals[wasm_export->index];
-                global_inst->kind = val_type_to_val_kind(global->type);
-                global_inst->is_mutable = global->is_mutable;
-#if WASM_ENABLE_MULTI_MODULE == 0
-                global_inst->global_data =
-                    wasm_module_inst->global_data + global->data_offset;
-#else
-                global_inst->global_data =
-                    global->import_global_inst
-                        ? global->import_module_inst->global_data
-                              + global->import_global_inst->data_offset
-                        : wasm_module_inst->global_data + global->data_offset;
-#endif
-                return true;
+
+            if (wasm_export->kind != WASM_IMPORT_EXPORT_KIND_GLOBAL) {
+                continue;
+            }
+
+            if (strcmp(wasm_export->name, name)) {
+                continue;
             }
+
+            WASMModuleInstanceExtra *e =
+                (WASMModuleInstanceExtra *)wasm_module_inst->e;
+            WASMGlobalInstance *global = &e->globals[wasm_export->index];
+            return global;
         }
+
+        return NULL;
     }
 #endif
 #if WASM_ENABLE_AOT != 0
@@ -2095,21 +2093,26 @@ wasm_runtime_get_export_global_inst(WASMModuleInstanceCommon *const module_inst,
         uint32 i;
         for (i = 0; i < aot_module->export_count; i++) {
             const AOTExport *aot_export = &aot_module->exports[i];
-            if ((aot_export->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL)
-                && !strcmp(aot_export->name, name)) {
-                const AOTGlobal *global =
-                    &aot_module->globals[aot_export->index];
-                global_inst->kind = val_type_to_val_kind(global->type.val_type);
-                global_inst->is_mutable = global->type.is_mutable;
-                global_inst->global_data =
-                    aot_module_inst->global_data + global->data_offset;
-                return true;
+
+            if (aot_export->kind != WASM_IMPORT_EXPORT_KIND_GLOBAL) {
+                continue;
+            }
+
+            if (strcmp(aot_export->name, name)) {
+                continue;
             }
+
+            AOTModuleInstanceExtra *e =
+                (AOTModuleInstanceExtra *)aot_module_inst->e;
+            AOTGlobalInstance *global = &e->globals[aot_export->index];
+            return global;
         }
+
+        return NULL;
     }
 #endif
 
-    return false;
+    return NULL;
 }
 
 WASMTableInstance *
@@ -7837,8 +7840,9 @@ wasm_table_inst_t
 wasm_runtime_create_table(WASMModuleCommon *const module,
                           wasm_table_type_t const type)
 {
-    if (!module || !type)
+    if (!module || !type) {
         return NULL;
+    }
 
 #if WASM_ENABLE_INTERP != 0
     if (module->module_type == Wasm_Module_Bytecode) {
@@ -7852,7 +7856,6 @@ wasm_runtime_create_table(WASMModuleCommon *const module,
     }
 #endif
 
-    LOG_ERROR("create table failed, invalid module type");
     return NULL;
 }
 
@@ -7896,6 +7899,125 @@ wasm_runtime_destroy_table(WASMModuleCommon *const module,
     LOG_ERROR("destroy table failed, invalid module type");
 }
 
+WASMGlobalInstance *
+wasm_runtime_create_global_internal(WASMModuleCommon *const module,
+                                    WASMModuleInstanceCommon *dep_inst,
+                                    WASMGlobalType *const type)
+{
+    if (!module || !type)
+        return NULL;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        return wasm_create_global((WASMModule *)module,
+                                  (WASMModuleInstance *)dep_inst, type);
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        return aot_create_global((AOTModule *)module,
+                                 (AOTModuleInstance *)dep_inst, type);
+    }
+#endif
+
+    return NULL;
+}
+
+void
+wasm_runtime_set_global_value(WASMModuleCommon *module,
+                              WASMGlobalInstance *global, WASMValue *value)
+{
+    if (!global || !value)
+        return;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        wasm_set_global_value(global, value);
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        aot_set_global_value(global, value);
+    }
+#endif
+}
+
+WASMGlobalInstance *
+wasm_runtime_create_global(WASMModuleCommon *const module,
+                           WASMGlobalType *const type, const wasm_val_t *value)
+{
+    WASMGlobalInstance *global =
+        wasm_runtime_create_global_internal(module, NULL, type);
+    if (!global)
+        return NULL;
+
+    /* TODO: make a small function about conversion */
+    WASMValue init_value = { 0 };
+    /* wasm_val_t to WASMValue */
+    switch (value->kind) {
+        case WASM_I32:
+        {
+            init_value.i32 = value->of.i32;
+            break;
+        }
+        case WASM_I64:
+        {
+            init_value.i64 = value->of.i64;
+            break;
+        }
+        case WASM_F32:
+        {
+            init_value.f32 = value->of.f32;
+            break;
+        }
+        case WASM_F64:
+        {
+            init_value.f64 = value->of.f64;
+            break;
+        }
+        // case WASM_V128:
+        // {
+        //     bh_assert(false && "V128 not supported yet");
+        //     break;
+        // }
+        // case WASM_EXTERNREF:
+        // case WASM_FUNCREF:
+        default:
+        {
+            bh_assert(false && "unsupported value type");
+            break;
+        }
+    }
+
+    wasm_runtime_set_global_value(module, global, &init_value);
+
+    return global;
+}
+
+void
+wasm_runtime_destroy_global(WASMModuleCommon *const module,
+                            WASMGlobalInstance *global)
+{
+    if (!module)
+        return;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        wasm_destroy_global(global);
+        return;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        aot_destroy_global(global);
+        return;
+    }
+#endif
+}
+
 /*TODO: take us(below) out when have a linker */
 WASMModuleInstanceCommon *
 wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
@@ -7942,59 +8064,24 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
      * WASMExternInstance->u.memory content
      *
      * WASModuleInstance->tables[i].elems takes
-     * the ownership of WASMExternInstance->u.table
+     * the ownership of WASMExternInstance->u.table as WASMTableInstance
      *
      * WASMModuleInstance->e->globals[i] copies the content of
      * WASMExternInstance->u.global
      */
     if (imports) {
+        for (uint32 i = 0; i < import_count; i++) {
+            if (imports[i].kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) {
+                wasm_runtime_destroy_global(module, imports[i].u.global);
+            }
+        }
+
         wasm_runtime_free(imports);
     }
 
     return inst;
 }
 
-bool
-wasm_runtime_create_extern_inst(WASMModuleCommon *module,
-                                wasm_import_t *import_type,
-                                WASMExternInstance *out)
-{
-    if (!out)
-        return false;
-
-    LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name,
-              import_type->name, import_type->kind);
-
-    out->module_name = import_type->module_name;
-    out->field_name = import_type->name;
-    out->kind = import_type->kind;
-
-    if (import_type->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
-        out->u.memory =
-            wasm_runtime_create_memory(module, import_type->u.memory_type);
-        if (!out->u.memory) {
-            LOG_ERROR("create memory failed\n");
-            return false;
-        }
-    }
-    else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_TABLE) {
-        wasm_table_inst_t table =
-            wasm_runtime_create_table(module, import_type->u.table_type);
-        out->u.table = table;
-        if (!out->u.table) {
-            LOG_ERROR("create table failed\n");
-            return false;
-        }
-    }
-    else {
-        LOG_DEBUG("unimplemented import(%s,%s) kind %d",
-                  import_type->module_name, import_type->name,
-                  import_type->kind);
-    }
-
-    return true;
-}
-
 void
 wasm_runtime_destroy_extern_inst(WASMModuleCommon *module,
                                  WASMExternInstance *extern_inst)
@@ -8006,6 +8093,14 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module,
         wasm_runtime_destroy_memory(module, extern_inst->u.memory);
         extern_inst->u.memory = NULL;
     }
+    else if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_TABLE) {
+        wasm_runtime_destroy_table(module, extern_inst->u.table);
+        extern_inst->u.table = NULL;
+    }
+    else if (extern_inst->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) {
+        wasm_runtime_destroy_global(module, extern_inst->u.global);
+        extern_inst->u.global = NULL;
+    }
     else {
         LOG_DEBUG("unimplemented import(%s,%s) kind %d",
                   extern_inst->module_name, extern_inst->field_name,
@@ -8016,11 +8111,12 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module,
     extern_inst->field_name = NULL;
 }
 
+#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_WASI_TEST != 0
 /*
  * Be aware that it will remove all items in the list, regardless of whether
  * they were created by the runtime (for built-ins) or by users.
  */
-void
+static void
 wasm_runtime_destroy_imports(WASMModuleCommon *module,
                              WASMExternInstance *extern_inst_list)
 {
@@ -8032,12 +8128,15 @@ wasm_runtime_destroy_imports(WASMModuleCommon *module,
         wasm_runtime_destroy_extern_inst(module, extern_inst_list + i);
     }
 }
+#endif /* WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_WASI_TEST != 0 */
 
 bool
-wasm_runtime_create_imports(WASMModuleCommon *module,
-                            bool (*module_name_filter)(const char *),
-                            WASMExternInstance *out, uint32 out_len)
+wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module,
+                                         WASMExternInstance *out,
+                                         uint32 out_len)
 {
+    LOG_DEBUG("create imports with builtin");
+
     int32 import_count_s = wasm_runtime_get_import_count(module);
 
     if (import_count_s < 0)
@@ -8057,35 +8156,32 @@ wasm_runtime_create_imports(WASMModuleCommon *module,
         wasm_import_t import_type = { 0 };
         wasm_runtime_get_import_type(module, i, &import_type);
 
-        if (module_name_filter
-            && !module_name_filter(import_type.module_name)) {
-            LOG_DEBUG("skip import(%s,%s)", import_type.module_name,
-                      import_type.name);
-            continue;
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+        WASMExternInstance *extern_instance = out + i;
+#if WASM_ENABLE_SPEC_TEST != 0
+        if (!wasm_runtime_create_extern_inst_for_spec_test(module, &import_type,
+                                                           extern_instance)) {
+            wasm_runtime_destroy_imports(module, out);
+            LOG_ERROR("create imports for spec test failed");
+            return false;
         }
+#endif
 
-        WASMExternInstance *extern_instance = out + i;
-        if (!wasm_runtime_create_extern_inst(module, &import_type,
-                                             extern_instance)) {
+#if WASM_ENABLE_WASI_TEST != 0
+        if (!wasm_runtime_create_extern_inst_for_wasi_test(module, &import_type,
+                                                           extern_instance)) {
             wasm_runtime_destroy_imports(module, out);
-            LOG_ERROR("create import failed");
+            LOG_ERROR("create imports for wasi test failed");
             return false;
         }
+#endif
+        (void)extern_instance;
+#endif
     }
 
     return true;
 }
 
-bool
-wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module,
-                                         WASMExternInstance *out,
-                                         uint32 out_len)
-{
-    LOG_DEBUG("create imports with builtin");
-    return wasm_runtime_create_imports(module, wasm_runtime_is_built_in_module,
-                                       out, out_len);
-}
-
 #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
 
 /*

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

@@ -1230,6 +1230,19 @@ wasm_runtime_get_extern_instance(const WASMExternInstance *imports,
                                  uint32 import_count,
                                  wasm_import_export_kind_t kind, uint32 index);
 
+struct WASMGlobalInstance *
+wasm_runtime_create_global_internal(wasm_module_t const module,
+                                    wasm_module_inst_t dep_inst,
+                                    wasm_global_type_t type);
+
+void
+wasm_runtime_set_global_value(wasm_module_t const module,
+                              wasm_global_inst_t global, WASMValue *value);
+
+struct WASMTableInstance *
+wasm_runtime_create_table_internal(WASMModuleCommon *const module,
+                                   WASMTableType *const type);
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 0
core/iwasm/compilation/aot_emit_table.c

@@ -132,6 +132,7 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx,
     return offset;
 }
 
+/*TODO: move it to aot_llvm.c/h */
 uint32
 get_module_inst_extra_offset(AOTCompContext *comp_ctx)
 {

+ 240 - 29
core/iwasm/compilation/aot_emit_variable.c

@@ -6,6 +6,7 @@
 #include "aot_emit_variable.h"
 #include "aot_emit_exception.h"
 #include "../aot/aot_runtime.h"
+#include "aot_emit_table.h"
 
 #define CHECK_LOCAL(idx)                                      \
     do {                                                      \
@@ -149,43 +150,259 @@ aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     return aot_compile_op_set_or_tee_local(comp_ctx, func_ctx, local_idx, true);
 }
 
+/*TODO: should be optimized by moving globals to WASMModuleInstance */
+LLVMValueRef
+get_global_from_wasm_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 global_idx)
+{
+    /* WASMModuleInstance->e->globals */
+    uint32 e_offset_val = get_module_inst_extra_offset(comp_ctx);
+    uint32 globals_offset_val = e_offset_val;
+#if WASM_ENABLE_JIT != 0
+    if (comp_ctx->is_jit_mode)
+        globals_offset_val += offsetof(WASMModuleInstanceExtra, globals);
+    else
+#endif
+        globals_offset_val += offsetof(AOTModuleInstanceExtra, globals);
+
+    LLVMValueRef globals_offset = I32_CONST(globals_offset_val);
+    if (!globals_offset) {
+        aot_set_last_error("I32_CONST failed for globals_offset");
+        return NULL;
+    }
+
+    LLVMValueRef globals_ptr =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
+                              &globals_offset, 1, "globals_ptr");
+    if (!globals_ptr) {
+        aot_set_last_error("LLVMBuildInBoundsGEP2 failed for globals_ptr");
+        return NULL;
+    }
+
+    LLVMValueRef globals =
+        LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, globals_ptr, "globals");
+    if (!globals) {
+        aot_set_last_error("LLVMBuildLoad2 failed for globals");
+        return NULL;
+    }
+
+    /* WASMGlobalInstance[global_idx] */
+    uint32 global_offset_val = global_idx * sizeof(WASMGlobalInstance);
+    LLVMValueRef global_offset = I32_CONST(global_offset_val);
+    if (!global_offset) {
+        aot_set_last_error("I32_CONST failed for global_offset");
+        return NULL;
+    }
+
+    LLVMValueRef global_ptr = LLVMBuildInBoundsGEP2(
+        comp_ctx->builder, INT8_TYPE, globals, &global_offset, 1, "global_ptr");
+    if (!global_ptr) {
+        aot_set_last_error("LLVMBuildInBoundsGEP2 failed for global_ptr");
+        return NULL;
+    }
+
+    return global_ptr;
+}
+
+static LLVMValueRef
+get_global_value_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                      uint32 global_idx)
+{
+    /* WASMGlobalInstance[global_idx] */
+    LLVMValueRef global_ptr =
+        get_global_from_wasm_inst(comp_ctx, func_ctx, global_idx);
+    if (!global_ptr) {
+        aot_set_last_error("get_global_from_wasm_inst failed");
+        return NULL;
+    }
+
+    /* WASMGlobalInstance->import_module_inst */
+    uint32 import_inst_offset_val =
+        offsetof(WASMGlobalInstance, import_module_inst);
+    LLVMValueRef import_inst_offset = I32_CONST(import_inst_offset_val);
+    if (!import_inst_offset) {
+        aot_set_last_error("I32_CONST failed for import_inst_offset");
+        return NULL;
+    }
+
+    LLVMValueRef import_inst_ptr_u8 =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, global_ptr,
+                              &import_inst_offset, 1, "import_inst_u8_ptr");
+    if (!import_inst_ptr_u8) {
+        aot_set_last_error(
+            "LLVMBuildInBoundsGEP2 failed for import_inst_ptr_u8");
+        return NULL;
+    }
+
+    LLVMValueRef import_inst_ptr = LLVMBuildBitCast(
+        comp_ctx->builder, import_inst_ptr_u8, OPQ_PTR_TYPE, "import_inst_ptr");
+    if (!import_inst_ptr) {
+        aot_set_last_error("LLVMBuildBitCast failed for import_inst_ptr");
+        return NULL;
+    }
+
+    LLVMValueRef import_inst = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+                                              import_inst_ptr, "import_inst");
+    if (!import_inst) {
+        aot_set_last_error("LLVMBuildLoad2 failed for import_inst");
+        return NULL;
+    }
+
+    /* WASMGlobalInstance->data_offset */
+    uint32 data_offset_offset_val = offsetof(WASMGlobalInstance, data_offset);
+    LLVMValueRef data_offset_offset = I32_CONST(data_offset_offset_val);
+    if (!data_offset_offset) {
+        aot_set_last_error("I32_CONST failed for data_offset_offset");
+        return NULL;
+    }
+
+    LLVMValueRef data_offset_ptr =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, global_ptr,
+                              &data_offset_offset, 1, "data_offset_ptr");
+    if (!data_offset_ptr) {
+        aot_set_last_error("LLVMBuildInBoundsGEP2 failed for data_offset_ptr");
+        return NULL;
+    }
+
+    LLVMValueRef data_offset = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE,
+                                              data_offset_ptr, "data_offset");
+    if (!data_offset) {
+        aot_set_last_error("LLVMBuildLoad2 failed for data_offset");
+        return NULL;
+    }
+
+    /* WASMModuleInstance->global_data preparation */
+    uint32 global_data_offset_val =
+        offsetof(WASMModuleInstance, global_table_data.bytes)
+        + sizeof(AOTMemoryInstance)
+              * (comp_ctx->comp_data->memory_count
+                 + comp_ctx->comp_data->import_memory_count);
+    LLVMValueRef global_data_offset = I32_CONST(global_data_offset_val);
+    if (!global_data_offset) {
+        aot_set_last_error("I32_CONST failed for global_data_offset");
+        return NULL;
+    }
+
+    // Check if import_module_inst is NULL
+    LLVMBasicBlockRef then_block = LLVMAppendBasicBlockInContext(
+        comp_ctx->context, func_ctx->func, "then");
+    if (!then_block) {
+        aot_set_last_error(
+            "LLVMAppendBasicBlockInContext failed for then_block");
+        return NULL;
+    }
+
+    LLVMBasicBlockRef else_block = LLVMAppendBasicBlockInContext(
+        comp_ctx->context, func_ctx->func, "else");
+    if (!else_block) {
+        aot_set_last_error(
+            "LLVMAppendBasicBlockInContext failed for else_block");
+        return NULL;
+    }
+
+    LLVMBasicBlockRef merge_block = LLVMAppendBasicBlockInContext(
+        comp_ctx->context, func_ctx->func, "merge");
+    if (!merge_block) {
+        aot_set_last_error(
+            "LLVMAppendBasicBlockInContext failed for merge_block");
+        return NULL;
+    }
+
+    LLVMValueRef terminator = LLVMBuildCondBr(
+        comp_ctx->builder,
+        LLVMBuildIsNull(comp_ctx->builder, import_inst, "is_null"), then_block,
+        else_block);
+    if (!terminator) {
+        aot_set_last_error("LLVMBuildCondBr failed");
+        return NULL;
+    }
+
+    // If import_module_inst is NULL
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, then_block);
+    // load global_data from local module instance
+    LLVMValueRef local_global_data =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
+                              &global_data_offset, 1, "local_global_data");
+    if (!local_global_data) {
+        aot_set_last_error(
+            "LLVMBuildInBoundsGEP2 failed for local_global_data");
+        return NULL;
+    }
+
+    // global value pointer
+    LLVMValueRef local_global_value_ptr =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, local_global_data,
+                              &data_offset, 1, "local_global_value_ptr");
+    if (!local_global_value_ptr) {
+        aot_set_last_error(
+            "LLVMBuildInBoundsGEP2 failed for local_global_value_ptr");
+        return NULL;
+    }
+
+    terminator = LLVMBuildBr(comp_ctx->builder, merge_block);
+    if (!terminator) {
+        aot_set_last_error("LLVMBuildBr failed");
+        return NULL;
+    }
+
+    // If import_module_inst is not NULL
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, else_block);
+    // load global_data in import module instance
+    LLVMValueRef import_global_data =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, import_inst,
+                              &global_data_offset, 1, "import_global_data");
+    if (!import_global_data) {
+        aot_set_last_error(
+            "LLVMBuildInBoundsGEP2 failed for import_global_data");
+        return NULL;
+    }
+
+    LLVMValueRef import_global_value_ptr =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, import_global_data,
+                              &data_offset, 1, "import_global_value_ptr");
+    if (!import_global_value_ptr) {
+        aot_set_last_error(
+            "LLVMBuildInBoundsGEP2 failed for import_global_value_ptr");
+        return NULL;
+    }
+
+    terminator = LLVMBuildBr(comp_ctx->builder, merge_block);
+    if (!terminator) {
+        aot_set_last_error("LLVMBuildBr failed");
+        return NULL;
+    }
+
+    // Merge block
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, merge_block);
+    LLVMValueRef phi =
+        LLVMBuildPhi(comp_ctx->builder, OPQ_PTR_TYPE, "global_value_addr");
+    if (!phi) {
+        aot_set_last_error("LLVMBuildPhi failed for global_value_addr");
+        return NULL;
+    }
+
+    LLVMAddIncoming(phi, &local_global_value_ptr, &then_block, 1);
+    LLVMAddIncoming(phi, &import_global_value_ptr, &else_block, 1);
+
+    return phi;
+}
+
 static bool
 compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                uint32 global_idx, bool is_set, bool is_aux_stack)
 {
     const AOTCompData *comp_data = comp_ctx->comp_data;
     uint32 import_global_count = comp_data->import_global_count;
-    uint32 global_base_offset;
-    uint32 global_offset;
     uint8 global_type;
-    LLVMValueRef offset, global_ptr, global, res;
+    LLVMValueRef global_ptr, global, res;
     LLVMTypeRef ptr_type = NULL;
 
-    global_base_offset = offsetof(AOTModuleInstance, global_table_data.bytes)
-                         + sizeof(AOTMemoryInstance)
-                               * (comp_ctx->comp_data->memory_count
-                                  + comp_ctx->comp_data->import_memory_count);
-
     bh_assert(global_idx < import_global_count + comp_data->global_count);
 
     if (global_idx < import_global_count) {
-        global_offset =
-            global_base_offset
-            /* Get global data offset according to target info */
-            + (comp_ctx->pointer_size == sizeof(uint64)
-                   ? comp_data->import_globals[global_idx].data_offset_64bit
-                   : comp_data->import_globals[global_idx].data_offset_32bit);
         global_type = comp_data->import_globals[global_idx].type.val_type;
     }
     else {
-        global_offset =
-            global_base_offset
-            /* Get global data offset according to target info */
-            + (comp_ctx->pointer_size == sizeof(uint64)
-                   ? comp_data->globals[global_idx - import_global_count]
-                         .data_offset_64bit
-                   : comp_data->globals[global_idx - import_global_count]
-                         .data_offset_32bit);
         global_type =
             comp_data->globals[global_idx - import_global_count].type.val_type;
     }
@@ -193,13 +410,7 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     if (comp_ctx->enable_gc && aot_is_type_gc_reftype(global_type))
         global_type = VALUE_TYPE_GC_REF;
 
-    offset = I32_CONST(global_offset);
-    if (!(global_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
-                                             func_ctx->aot_inst, &offset, 1,
-                                             "global_ptr_tmp"))) {
-        aot_set_last_error("llvm build in bounds gep failed.");
-        return false;
-    }
+    global_ptr = get_global_value_addr(comp_ctx, func_ctx, global_idx);
 
     switch (global_type) {
         case VALUE_TYPE_I32:

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

@@ -7,6 +7,7 @@
 #include "aot_llvm_extra2.h"
 #include "aot_compiler.h"
 #include "aot_emit_exception.h"
+// TODO: remove me if get_module_inst_extra_offset() has been moved out
 #include "aot_emit_table.h"
 #include "../aot/aot_runtime.h"
 #include "../aot/aot_intrinsic.h"

+ 20 - 18
core/iwasm/include/wasm_export.h

@@ -142,6 +142,11 @@ typedef struct WASMMemoryInstance *wasm_memory_inst_t;
 struct WASMTableInstance;
 typedef struct WASMTableInstance *wasm_table_inst_t;
 
+/*TODO: remove me when rebasing*/
+/* Global instance*/
+struct WASMGlobalInstance;
+typedef struct WASMGlobalInstance *wasm_global_inst_t;
+
 /* WASM section */
 typedef struct wasm_section_t {
     struct wasm_section_t *next;
@@ -282,6 +287,7 @@ typedef struct LoadArgs {
 } LoadArgs;
 #endif /* LOAD_ARGS_OPTION_DEFINED */
 
+/*TODO: move it to wasm_runtime_common.h? */
 typedef struct WASMExternInstance {
     const char *module_name;
     const char *field_name;
@@ -289,7 +295,14 @@ typedef struct WASMExternInstance {
     union {
         wasm_memory_inst_t memory;
         wasm_table_inst_t table;
+        wasm_global_inst_t global;
     } u;
+
+    /*
+     * to handle imports properly,
+     * especially for wasm_global_inst_t and wasm_func_inst_t
+     */
+    wasm_module_inst_t dep_inst;
 } WASMExternInstance, *wasm_extern_inst_t;
 
 #ifndef INSTANTIATION_ARGS_OPTION_DEFINED
@@ -335,13 +348,6 @@ typedef struct wasm_val_t {
 } wasm_val_t;
 #endif
 
-/* Global instance*/
-typedef struct wasm_global_inst_t {
-    wasm_valkind_t kind;
-    bool is_mutable;
-    void *global_data;
-} wasm_global_inst_t;
-
 typedef enum {
     WASM_LOG_LEVEL_FATAL = 0,
     WASM_LOG_LEVEL_ERROR = 1,
@@ -1099,6 +1105,11 @@ wasm_memory_get_base_address(const wasm_memory_inst_t memory_inst);
 WASM_RUNTIME_API_EXTERN bool
 wasm_memory_enlarge(wasm_memory_inst_t memory_inst, uint64_t inc_page_count);
 
+WASM_RUNTIME_API_EXTERN wasm_global_inst_t
+wasm_runtime_create_immutable_global(const wasm_module_t module,
+                                     const wasm_global_type_t type,
+                                     const wasm_val_t *value);
+
 /**
  * Call the given WASM function of a WASM module instance with
  * arguments (bytecode and AoT).
@@ -1754,10 +1765,9 @@ wasm_runtime_unregister_natives(const char *module_name,
  * @return true if success, false otherwise
  *
  */
-WASM_RUNTIME_API_EXTERN bool
+WASM_RUNTIME_API_EXTERN wasm_global_inst_t
 wasm_runtime_get_export_global_inst(const wasm_module_inst_t module_inst,
-                                    const char *name,
-                                    wasm_global_inst_t *global_inst);
+                                    const char *name);
 
 /**
  * @brief Retrieves the table instance exported from a WebAssembly module
@@ -2384,14 +2394,6 @@ wasm_runtime_create_imports_with_builtin(wasm_module_t module,
                                          wasm_extern_inst_t out,
                                          uint32_t out_len);
 
-WASM_RUNTIME_API_EXTERN void
-wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports);
-
-WASM_RUNTIME_API_EXTERN bool
-wasm_runtime_create_imports(wasm_module_t module,
-                            bool (*module_name_filter)(const char *),
-                            wasm_extern_inst_t out, uint32_t out_len);
-
 #ifdef __cplusplus
 }
 #endif

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

@@ -608,18 +608,23 @@ typedef struct WASMGlobalImport {
     char *module_name;
     char *field_name;
     WASMGlobalType type;
+
+    /*TODO: not necessary if WASM_ENABLE_MULTI_MODULE == 0*/
     bool is_linked;
     /* global data after linked */
     WASMValue global_data_linked;
+
 #if WASM_ENABLE_GC != 0
     WASMRefType *ref_type;
 #endif
+
 #if WASM_ENABLE_MULTI_MODULE != 0
     /* imported function pointer after linked */
     /* TODO: remove if not needed */
     WASMModule *import_module;
     WASMGlobal *import_global_linked;
 #endif
+
 #if WASM_ENABLE_FAST_JIT != 0
     /* The data offset of current global in global data */
     uint32 data_offset;

+ 0 - 13
core/iwasm/interpreter/wasm_interp_classic.c

@@ -1549,19 +1549,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
 
 #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
 
-static inline uint8 *
-get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
-{
-#if WASM_ENABLE_MULTI_MODULE == 0
-    return global_data + global->data_offset;
-#else
-    return global->import_global_inst
-               ? global->import_module_inst->global_data
-                     + global->import_global_inst->data_offset
-               : global_data + global->data_offset;
-#endif
-}
-
 static void
 wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                WASMExecEnv *exec_env,

+ 0 - 13
core/iwasm/interpreter/wasm_interp_fast.c

@@ -1450,19 +1450,6 @@ wasm_interp_dump_op_count()
 static void **global_handle_table;
 #endif
 
-static inline uint8 *
-get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
-{
-#if WASM_ENABLE_MULTI_MODULE == 0
-    return global_data + global->data_offset;
-#else
-    return global->import_global_inst
-               ? global->import_module_inst->global_data
-                     + global->import_global_inst->data_offset
-               : global_data + global->data_offset;
-#endif
-}
-
 static void
 wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                WASMExecEnv *exec_env,

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

@@ -2991,7 +2991,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
         return false;
     }
 
+#if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_LIBC_BUILTIN != 0
+    /* link with libc-builtin provided */
     ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
                                                  global);
     if (ret) {
@@ -3004,7 +3006,8 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
         global->is_linked = true;
     }
 #endif
-#if WASM_ENABLE_MULTI_MODULE != 0
+
+    /* link with other modules' */
     if (!global->is_linked
         && !wasm_runtime_is_built_in_module(sub_module_name)) {
         sub_module = (WASMModule *)wasm_runtime_load_depended_module(
@@ -3022,7 +3025,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
             }
         }
     }
-#endif
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
 
     global->module_name = sub_module_name;
     global->field_name = global_name;

+ 134 - 74
core/iwasm/interpreter/wasm_runtime.c

@@ -296,8 +296,7 @@ memories_deinstantiate(WASMModuleInstance *module_inst)
 #else
         wasm_runtime_free(memory);
 #endif
-#endif
-        (void)memory;
+#endif /* WASM_ENABLE_MULTI_MODULE == 0 */
     }
 
     for (; mem_index < module->memory_count; mem_index++) {
@@ -772,8 +771,10 @@ tables_deinstantiate(WASMModuleInstance *module_inst)
     }
 #endif
 
-    wasm_runtime_free(module_inst->tables);
-    module_inst->tables = NULL;
+    if (module_inst->tables) {
+        wasm_runtime_free(module_inst->tables);
+        module_inst->tables = NULL;
+    }
 }
 
 /**
@@ -1265,7 +1266,7 @@ instantiate_struct_global_recursive(WASMModule *module,
                         (WASMStructNewInitValues *)wasm_value->data;
                     WASMStructObjectRef field =
                         instantiate_struct_global_recursive(
-                            module, module_inst, heap_type,
+                            module, module_inst, (uint32)heap_type,
                             init_values1 ? INIT_EXPR_TYPE_STRUCT_NEW
                                          : INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT,
                             init_values1, error_buf, error_buf_size);
@@ -1370,6 +1371,7 @@ instantiate_array_global_recursive(WASMModule *module,
  */
 static WASMGlobalInstance *
 globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
+                    const WASMExternInstance *imports, uint32 import_count,
                     char *error_buf, uint32 error_buf_size)
 {
     WASMImport *import;
@@ -1385,66 +1387,99 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
     /* instantiate globals from import section */
     global = globals;
     import = module->import_globals;
-    for (i = 0; i < module->import_global_count; i++, import++) {
-        WASMGlobalImport *global_import = &import->u.global;
-        global->type = global_import->type.val_type;
-        global->is_mutable = global_import->type.is_mutable;
+    for (i = 0; i < module->import_global_count; i++, import++, global++) {
+        WASMGlobalImport *import_global_type = &import->u.global;
+
+        global->type = import_global_type->type.val_type;
+        global->is_mutable = import_global_type->type.is_mutable;
 #if WASM_ENABLE_GC != 0
-        global->ref_type = global_import->ref_type;
+        global->ref_type = import_global_type->ref_type;
+#endif
+#if WASM_ENABLE_FAST_JIT != 0
+        bh_assert(global_data_offset == import_global_type->data_offset);
 #endif
+        global->data_offset = global_data_offset;
+        global_data_offset += wasm_value_type_size(global->type);
+
 #if WASM_ENABLE_MULTI_MODULE != 0
-        if (global_import->import_module) {
+        if (import_global_type->import_module) {
             if (!(global->import_module_inst = get_sub_module_inst(
-                      module_inst, global_import->import_module))) {
+                      module_inst, import_global_type->import_module))) {
                 set_error_buf(error_buf, error_buf_size, "unknown global");
                 goto fail;
             }
 
-            if (!(global->import_global_inst = wasm_lookup_global(
-                      global->import_module_inst, global_import->field_name))) {
+            if (!(global->import_global_inst =
+                      wasm_lookup_global(global->import_module_inst,
+                                         import_global_type->field_name))) {
                 set_error_buf(error_buf, error_buf_size, "unknown global");
                 goto fail;
             }
 
             /* The linked global instance has been initialized, we
                just need to copy the value. */
-            bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
-                        &(global_import->import_global_linked->init_expr.u),
-                        sizeof(WASMValue));
+            bh_memcpy_s(
+                &(global->initial_value), sizeof(WASMValue),
+                &(import_global_type->import_global_linked->init_expr.u),
+                sizeof(WASMValue));
         }
-        else
-#endif
-        {
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+        else {
             /* native globals share their initial_values in one module */
             bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
-                        &(global_import->global_data_linked),
+                        &(import_global_type->global_data_linked),
                         sizeof(WASMValue));
         }
-#if WASM_ENABLE_FAST_JIT != 0
-        bh_assert(global_data_offset == global_import->data_offset);
 #endif
-        global->data_offset = global_data_offset;
-        global_data_offset += wasm_value_type_size(global->type);
 
-        global++;
+#else
+
+        /* refer to the imported global */
+        const WASMExternInstance *extern_inst =
+            wasm_runtime_get_extern_instance(imports, import_count,
+                                             WASM_IMPORT_EXPORT_KIND_GLOBAL, i);
+        if (!extern_inst) {
+            LOG_ERROR("missing an import global(%s, %s)",
+                      import_global_type->module_name,
+                      import_global_type->field_name);
+            goto fail;
+        }
+
+        /* just in case */
+#ifndef NDEBUG
+        if (strcmp(import_global_type->field_name, extern_inst->field_name)) {
+            LOG_ERROR(
+                "mismatched import global name: expect \"%s\", got \"%s\"",
+                import_global_type->field_name, extern_inst->field_name);
+            goto fail;
+        }
+#endif
+
+        bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
+                    &(extern_inst->u.global->initial_value), sizeof(WASMValue));
+        global->import_module_inst =
+            (WASMModuleInstance *)extern_inst->dep_inst;
+        global->import_global_inst = extern_inst->u.global;
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
     }
 
     /* instantiate globals from global section */
-    for (i = 0; i < module->global_count; i++) {
-        InitializerExpression *init_expr = &(module->globals[i].init_expr);
-        uint8 flag = init_expr->init_expr_type;
-
+    for (i = 0; i < module->global_count; i++, global++) {
         global->type = module->globals[i].type.val_type;
         global->is_mutable = module->globals[i].type.is_mutable;
+
+#if WASM_ENABLE_GC != 0
+        global->ref_type = module->globals[i].ref_type;
+#endif
+
 #if WASM_ENABLE_FAST_JIT != 0
         bh_assert(global_data_offset == module->globals[i].data_offset);
 #endif
         global->data_offset = global_data_offset;
         global_data_offset += wasm_value_type_size(global->type);
-#if WASM_ENABLE_GC != 0
-        global->ref_type = module->globals[i].ref_type;
-#endif
 
+        InitializerExpression *init_expr = &(module->globals[i].init_expr);
+        uint8 flag = init_expr->init_expr_type;
         switch (flag) {
             case INIT_EXPR_TYPE_GET_GLOBAL:
             {
@@ -1453,10 +1488,9 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
                     goto fail;
                 }
 
-                bh_memcpy_s(
-                    &(global->initial_value), sizeof(WASMValue),
-                    &(globals[init_expr->u.global_index].initial_value),
-                    sizeof(globals[init_expr->u.global_index].initial_value));
+                bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
+                            &(globals[init_expr->u.global_index].initial_value),
+                            sizeof(WASMValue));
                 break;
             }
 #if WASM_ENABLE_GC != 0
@@ -1525,11 +1559,9 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
 #endif /* end of WASM_ENABLE_GC != 0 */
             default:
                 bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
-                            &(init_expr->u), sizeof(init_expr->u));
+                            &(init_expr->u), sizeof(WASMValue));
                 break;
         }
-
-        global++;
     }
 
     bh_assert((uint32)(global - globals) == global_count);
@@ -2105,6 +2137,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
         }
     }
 
+#if WASM_ENABLE_MULTI_MODULE != 0
     for (i = 0; i < module->import_global_count; i++) {
         WASMGlobalImport *global = &((module->import_globals + i)->u.global);
 
@@ -2126,10 +2159,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
         WASMTableImport *table = &((module->import_tables + i)->u.table);
 
         if (!wasm_runtime_is_built_in_module(table->module_name)
-#if WASM_ENABLE_MULTI_MODULE != 0
-            && !table->import_table_linked
-#endif
-        ) {
+            && !table->import_table_linked) {
             set_error_buf_v(error_buf, error_buf_size,
                             "failed to link import table (%s, %s)",
                             table->module_name, table->field_name);
@@ -2138,25 +2168,17 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
     }
 
     for (i = 0; i < module->import_memory_count; i++) {
-        WASMMemoryImport *type = &((module->import_memories + i)->u.memory);
-        WASMMemoryInstance *memory = module_inst->memories[i];
-        (void)memory;
-        if (
-#if WASM_ENABLE_MULTI_MODULE != 0
-            !wasm_runtime_is_built_in_module(type->module_name)
-            && !type->import_memory_linked
-#else
-            !memory
-#endif
-        ) {
+        WASMMemoryImport *memory = &((module->import_memories + i)->u.memory);
+
+        if (!wasm_runtime_is_built_in_module(memory->module_name)
+            && !memory->import_memory_linked) {
             set_error_buf_v(error_buf, error_buf_size,
                             "failed to link import memory (%s, %s)",
-                            type->module_name, type->field_name);
+                            memory->module_name, memory->field_name);
             return false;
         }
     }
 
-#if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_TAGS != 0
     for (i = 0; i < module->import_tag_count; i++) {
         WASMTagImport *tag = &((module->import_tags + i)->u.tag);
@@ -2169,7 +2191,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
         }
     }
 #endif /* WASM_ENABLE_TAGS != 0 */
-#endif
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
 
     return true;
 }
@@ -2726,8 +2748,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
      */
     global_count = module->import_global_count + module->global_count;
     if (global_count
-        && !(globals = globals_instantiate(module, module_inst, error_buf,
-                                           error_buf_size))) {
+        && !(globals =
+                 globals_instantiate(module, module_inst, imports, import_count,
+                                     error_buf, error_buf_size))) {
         goto fail;
     }
     module_inst->e->global_count = global_count;
@@ -2820,6 +2843,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         goto fail;
     }
 
+    /*TODO: init_global_data() ?*/
+    /* WASMGlobalInstance->initial_value => WASMModuleInstance->global_data*/
     if (global_count > 0) {
         /* Initialize the global data */
         global_data = module_inst->global_data;
@@ -2892,7 +2917,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                         /* UINT32_MAX indicates that it is a null reference */
                         if ((uint32)global->initial_value.i32 != UINT32_MAX) {
                             if (!(func_obj = wasm_create_func_obj(
-                                      module_inst, global->initial_value.i32,
+                                      module_inst, global->initial_value.u32,
                                       false, error_buf, error_buf_size)))
                                 goto fail;
                         }
@@ -3175,19 +3200,21 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 #endif
 
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
-        bh_assert(table_seg->base_offset.init_expr_type
-                      == INIT_EXPR_TYPE_I32_CONST
-                  || table_seg->base_offset.init_expr_type
-                         == INIT_EXPR_TYPE_GET_GLOBAL
-                  || table_seg->base_offset.init_expr_type
-                         == INIT_EXPR_TYPE_FUNCREF_CONST
-                  || table_seg->base_offset.init_expr_type
-                         == INIT_EXPR_TYPE_REFNULL_CONST);
+        bh_assert(
+            table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
+            || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_CONST
+            || table_seg->base_offset.init_expr_type
+                   == INIT_EXPR_TYPE_GET_GLOBAL
+            || table_seg->base_offset.init_expr_type
+                   == INIT_EXPR_TYPE_FUNCREF_CONST
+            || table_seg->base_offset.init_expr_type
+                   == INIT_EXPR_TYPE_REFNULL_CONST);
 #else
-        bh_assert(table_seg->base_offset.init_expr_type
-                      == INIT_EXPR_TYPE_I32_CONST
-                  || table_seg->base_offset.init_expr_type
-                         == INIT_EXPR_TYPE_GET_GLOBAL);
+        bh_assert(
+            table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
+            || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_CONST
+            || table_seg->base_offset.init_expr_type
+                   == INIT_EXPR_TYPE_GET_GLOBAL);
 #endif
 
         /* init vec(funcidx) or vec(expr) */
@@ -3410,7 +3437,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                 }
                 case INIT_EXPR_TYPE_I31_NEW:
                 {
-                    ref = (wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
+                    ref = (wasm_obj_t)wasm_i31_obj_new(init_expr->u.u32);
                     break;
                 }
 #endif /* end of WASM_ENABLE_GC != 0 */
@@ -5395,4 +5422,37 @@ wasm_destroy_table(WASMTableInstance *table)
         return;
 
     wasm_runtime_free(table);
+}
+
+WASMGlobalInstance *
+wasm_create_global(const WASMModule *module, WASMModuleInstance *dep_inst,
+                   WASMGlobalType *type)
+{
+    WASMGlobalInstance *global =
+        runtime_malloc(sizeof(WASMGlobalInstance), NULL, 0);
+    if (!global) {
+        return NULL;
+    }
+
+    global->type = type->val_type;
+    global->is_mutable = type->is_mutable;
+    global->import_module_inst = dep_inst;
+    /* empty global. set value later by wasm_set_global_value */
+    return global;
+}
+
+void
+wasm_set_global_value(WASMGlobalInstance *global, const WASMValue *value)
+{
+    bh_memcpy_s(&global->initial_value, sizeof(WASMValue), value,
+                sizeof(WASMValue));
+}
+
+void
+wasm_destroy_global(WASMGlobalInstance *global)
+{
+    if (!global)
+        return;
+
+    wasm_runtime_free(global);
 }

+ 40 - 8
core/iwasm/interpreter/wasm_runtime.h

@@ -192,19 +192,23 @@ struct WASMGlobalInstance {
     uint8 type;
     /* mutable or constant */
     bool is_mutable;
+
     /* data offset to the address of initial_value, started from the end of
      * WASMMemoryInstance(start of WASMGlobalInstance)*/
     uint32 data_offset;
-    /* initial value */
+
+    /*
+     * initial value (before instantiation stage)
+     *   - host creation. store initial value directly. no init expr
+     *   - as a temp value before storing in global_data
+     */
     WASMValue initial_value;
-#if WASM_ENABLE_GC != 0
-    WASMRefType *ref_type;
-#endif
-#if WASM_ENABLE_MULTI_MODULE != 0
+
     /* just for import, keep the reference here */
-    WASMModuleInstance *import_module_inst;
-    WASMGlobalInstance *import_global_inst;
-#endif
+    DefPointer(WASMModuleInstance *, import_module_inst);
+    DefPointer(WASMGlobalInstance *, import_global_inst);
+    /* WASMRefType *ref_type */
+    DefPointer(void *, ref_type);
 };
 
 struct WASMFunctionInstance {
@@ -563,6 +567,24 @@ wasm_get_tbl_data_slots(const WASMTableType *table_type,
 #endif
 }
 
+static inline uint8 *
+get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
+{
+    /*
+     * global->import_global_inst != NULL means the global is imported
+     * from another module.
+     * global->import_module_isnt != NULL means the data is stored in
+     * local module instance.
+     *
+     * A host created global doesn't have its own global_data need to
+     * be maintained.
+     */
+    return global->import_module_inst
+               ? global->import_module_inst->global_data
+                     + global->import_global_inst->data_offset
+               : global_data + global->data_offset;
+}
+
 WASMModule *
 wasm_load(uint8 *buf, uint32 size,
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -956,6 +978,16 @@ wasm_set_table_elem(const WASMModule *module, WASMTableInstance *table,
 void
 wasm_destroy_table(WASMTableInstance *table);
 
+WASMGlobalInstance *
+wasm_create_global(const WASMModule *module, WASMModuleInstance *dep_inst,
+                   WASMGlobalType *type);
+
+void
+wasm_set_global_value(WASMGlobalInstance *global, const WASMValue *value);
+
+void
+wasm_destroy_global(WASMGlobalInstance *global);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 0
core/iwasm/libraries/libc-builtin/SConscript

@@ -10,6 +10,8 @@ cwd     = GetCurrentDir()
 
 #src = Split('''
 #libc_builtin_wrapper.c
+#spec_test_builtin_wrapper.c
+#wasi_test_builtin_wrapper.c
 #''')
 
 src = Glob('*.c')

+ 47 - 0
core/iwasm/libraries/libc-builtin/builtin_wrapper.h

@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#ifndef _BUILTIN_WRAPPER_H_
+#define _BUILTIN_WRAPPER_H_
+
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+#include "../common/wasm_runtime_common.h"
+
+/*************************************
+ * Functions
+ *************************************/
+
+/*************************************
+ * Globals
+ *************************************/
+typedef struct WASMNativeGlobalDef {
+    const char *module_name;
+    const char *name;
+    uint8 type;
+    bool is_mutable;
+    WASMValue value;
+} WASMNativeGlobalDef;
+
+/*************************************
+ * Tables
+ *************************************/
+
+typedef struct WASMNativeTableDef {
+    const char *module_name;
+    const char *name;
+    uint8 elem_type;
+
+} WASMNativeTableDef;
+
+/*************************************
+ * Memories
+ *************************************/
+
+typedef struct WASMNativeMemoryDef {
+    const char *module_name;
+    const char *name;
+} WASMNativeMemoryDef;
+
+#endif

+ 10 - 3
core/iwasm/libraries/libc-builtin/libc_builtin.cmake

@@ -5,9 +5,16 @@ set (LIBC_BUILTIN_DIR ${CMAKE_CURRENT_LIST_DIR})
 
 add_definitions (-DWASM_ENABLE_LIBC_BUILTIN=1)
 
-include_directories(${LIBC_BUILTIN_DIR})
+include_directories (${LIBC_BUILTIN_DIR})
 
-file (GLOB source_all ${LIBC_BUILTIN_DIR}/*.c)
+list (APPEND source_all ${LIBC_BUILTIN_DIR}/libc_builtin_wrapper.c)
 
-set (LIBC_BUILTIN_SOURCE ${source_all})
+if (WAMR_BUILD_SPEC_TEST EQUAL 1)
+  list (APPEND source_all ${LIBC_BUILTIN_DIR}/spec_test_builtin_wrapper.c)
+endif ()
+
+if (WAMR_BUILD_WASI_TEST EQUAL 1)
+  list (APPEND source_all ${LIBC_BUILTIN_DIR}/wasi_test_builtin_wrapper.c)
+endif ()
 
+set (LIBC_BUILTIN_SOURCE ${source_all})

+ 24 - 14
core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c

@@ -5,8 +5,7 @@
 
 #include "bh_common.h"
 #include "bh_log.h"
-#include "wasm_export.h"
-#include "../interpreter/wasm.h"
+#include "builtin_wrapper.h"
 
 #if defined(_WIN32) || defined(_WIN32_)
 #define strncasecmp _strnicmp
@@ -1129,15 +1128,8 @@ get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
  * Global Variables                  *
  *************************************/
 
-typedef struct WASMNativeGlobalDef {
-    const char *module_name;
-    const char *global_name;
-    uint8 type;
-    bool is_mutable;
-    WASMValue value;
-} WASMNativeGlobalDef;
-
 static WASMNativeGlobalDef native_global_defs[] = {
+#if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_SPEC_TEST != 0
     { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 },
     { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 },
@@ -1148,13 +1140,19 @@ static WASMNativeGlobalDef native_global_defs[] = {
     { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
     { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
     { "test", "g", VALUE_TYPE_I32, true, .value.i32 = 0 },
+
 #if WASM_ENABLE_GC != 0
     { "G", "g", VALUE_TYPE_I32, false, .value.i32 = 4 },
     { "M", "g", REF_TYPE_HT_NON_NULLABLE, false, .value.gc_obj = 0 },
 #endif
-#endif
-    { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL },
-    { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL }
+
+#endif /* WASM_ENABLE_SPEC_TEST != 0 */
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
+
+    { "global", "NaN", VALUE_TYPE_F64, false,
+      .value.u64 = 0x7FF8000000000000LL },
+    { "global", "Infinity", VALUE_TYPE_F64, false,
+      .value.u64 = 0x7FF0000000000000LL }
 };
 
 bool
@@ -1172,7 +1170,7 @@ wasm_native_lookup_libc_builtin_global(const char *module_name,
     /* Lookup constant globals which can be defined by table */
     while (global_def < global_def_end) {
         if (!strcmp(global_def->module_name, module_name)
-            && !strcmp(global_def->global_name, global_name)) {
+            && !strcmp(global_def->name, global_name)) {
             global->type.val_type = global_def->type;
             global->type.is_mutable = global_def->is_mutable;
             global->global_data_linked = global_def->value;
@@ -1183,3 +1181,15 @@ wasm_native_lookup_libc_builtin_global(const char *module_name,
 
     return false;
 }
+
+/*
+ * it is a workaround to fix undefined reference to
+ * `wasm_runtime_create_extern_inst_for_spec_test'
+ */
+#if defined(__NuttX__)
+
+#if WASM_ENABLE_SPEC_TEST != 0
+#include "./spec_test_builtin_wrapper.c"
+#endif
+
+#endif

+ 182 - 0
core/iwasm/libraries/libc-builtin/spec_test_builtin_wrapper.c

@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "builtin_wrapper.h"
+
+/*************************************
+ * Functions
+ *************************************/
+
+/*************************************
+ * Globals
+ *************************************/
+
+static WASMNativeGlobalDef spec_test_global_defs[] = {
+    /* for standard spec test */
+    { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 },
+    { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 },
+    { "spectest", "global_f32", VALUE_TYPE_F32, false, .value.f32 = 666.6f },
+    { "spectest", "global_f64", VALUE_TYPE_F64, false, .value.f64 = 666.6 },
+    { "test", "global-i32", VALUE_TYPE_I32, false, .value.i32 = 0 },
+    { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 },
+    { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
+    { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
+    { "test", "g", VALUE_TYPE_I32, true, .value.i32 = 0 },
+/* for gc spec test */
+#if WASM_ENABLE_GC != 0
+    { "G", "g", VALUE_TYPE_I32, false, .value.i32 = 4 },
+    { "M", "g", REF_TYPE_HT_NON_NULLABLE, false, .value.gc_obj = 0 },
+#endif
+};
+
+static wasm_global_inst_t
+create_spec_test_global(wasm_module_t module, const char *module_name,
+                        const char *name, wasm_global_type_t type)
+{
+    if (!module || !module_name || !name || !type) {
+        return NULL;
+    }
+
+    WASMNativeGlobalDef *global_def = spec_test_global_defs;
+    uint32 size = sizeof(spec_test_global_defs) / sizeof(WASMNativeGlobalDef);
+    WASMNativeGlobalDef *global_def_end = global_def + size;
+    for (; global_def < global_def_end; global_def++) {
+        if (strcmp(global_def->module_name, module_name) != 0) {
+            continue;
+        }
+
+        if (strcmp(global_def->name, name) != 0) {
+            continue;
+        }
+
+        wasm_global_inst_t global =
+            wasm_runtime_create_global_internal(module, NULL, type);
+        if (!global) {
+            return NULL;
+        }
+
+        wasm_runtime_set_global_value(module, global, &global_def->value);
+        return global;
+    }
+
+    return NULL;
+}
+
+/*************************************
+ * Tables
+ *************************************/
+static WASMNativeTableDef builtin_table_defs[] = {
+    { "spectest", "table", VALUE_TYPE_FUNCREF },
+    { "spectest", "table64", VALUE_TYPE_FUNCREF },
+};
+
+static wasm_table_inst_t
+create_spec_test_table(wasm_module_t module, const char *module_name,
+                       const char *name, wasm_table_type_t type)
+{
+    if (!module || !module_name || !name || !type) {
+        return NULL;
+    }
+
+    WASMNativeTableDef *table_def = builtin_table_defs;
+    size_t count = sizeof(builtin_table_defs) / sizeof(WASMNativeTableDef);
+    WASMNativeTableDef *table_def_end = builtin_table_defs + count;
+
+    for (; table_def < table_def_end; table_def++) {
+        if (strcmp(table_def->module_name, module_name) != 0) {
+            continue;
+        }
+
+        if (strcmp(table_def->name, name) != 0) {
+            continue;
+        }
+
+        return wasm_runtime_create_table(module, type);
+    }
+
+    return NULL;
+}
+
+/*************************************
+ * Memories
+ *************************************/
+
+/*
+ * no predefined memory for spec test
+ */
+static wasm_memory_inst_t
+create_spec_test_memory(wasm_module_t module, const char *module_name,
+                        const char *name, wasm_memory_type_t type)
+{
+    if (!module || !module_name || !name || !type) {
+        return NULL;
+    }
+
+    if (strcmp(module_name, "spectest") != 0) {
+        return NULL;
+    }
+
+    if (strcmp(name, "memory") != 0) {
+        return NULL;
+    }
+
+    return wasm_runtime_create_memory(module, type);
+}
+
+/*************************************
+ * Extern
+ *************************************/
+
+bool
+wasm_runtime_create_extern_inst_for_spec_test(wasm_module_t module,
+                                              wasm_import_t *import_type,
+                                              WASMExternInstance *out)
+{
+    if (!module || !import_type || !out)
+        return false;
+
+    LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name,
+              import_type->name, import_type->kind);
+
+    out->module_name = import_type->module_name;
+    out->field_name = import_type->name;
+    out->kind = import_type->kind;
+
+    if (import_type->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
+        out->u.memory = create_spec_test_memory(
+            module, import_type->module_name, import_type->name,
+            import_type->u.memory_type);
+        if (!out->u.memory) {
+            LOG_ERROR("create memory failed\n");
+            return false;
+        }
+    }
+    else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_TABLE) {
+        out->u.table = create_spec_test_table(module, import_type->module_name,
+                                              import_type->name,
+                                              import_type->u.table_type);
+        if (!out->u.table) {
+            LOG_ERROR("create table failed\n");
+            return false;
+        }
+    }
+    else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_GLOBAL) {
+        out->u.global = create_spec_test_global(
+            module, import_type->module_name, import_type->name,
+            import_type->u.global_type);
+        if (!out->u.global) {
+            LOG_ERROR("create global failed\n");
+            return false;
+        }
+    }
+    else {
+        LOG_DEBUG("unimplemented import(%s,%s) kind %d for spec test",
+                  import_type->module_name, import_type->name,
+                  import_type->kind);
+    }
+
+    return true;
+}

+ 92 - 0
core/iwasm/libraries/libc-builtin/wasi_test_builtin_wrapper.c

@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "builtin_wrapper.h"
+
+/*************************************
+ * Functions
+ *************************************/
+
+/*************************************
+ * Globals
+ *************************************/
+
+/*************************************
+ * Tables
+ *************************************/
+
+/*************************************
+ * Memories
+ *************************************/
+
+static WASMNativeMemoryDef builtin_memory_defs[] = {
+    { "foo", "bar" },
+    { "env", "memory" },
+};
+
+static wasm_memory_inst_t
+create_wasi_test_memory(wasm_module_t module, const char *module_name,
+                        const char *name, wasm_memory_type_t type)
+{
+    if (!module || !module_name || !name || !type) {
+        return NULL;
+    }
+
+    WASMNativeMemoryDef *memory_def = builtin_memory_defs;
+    size_t count = sizeof(builtin_memory_defs) / sizeof(WASMNativeMemoryDef);
+    WASMNativeMemoryDef *memory_def_end = builtin_memory_defs + count;
+
+    for (; memory_def < memory_def_end; memory_def++) {
+        if (strcmp(memory_def->module_name, module_name) != 0) {
+            continue;
+        }
+
+        if (strcmp(memory_def->name, name) != 0) {
+            continue;
+        }
+
+        return wasm_runtime_create_memory(module, type);
+    }
+
+    return NULL;
+}
+
+/*************************************
+ * Extern
+ *************************************/
+
+bool
+wasm_runtime_create_extern_inst_for_wasi_test(wasm_module_t module,
+                                              wasm_import_t *import_type,
+                                              WASMExternInstance *out)
+{
+    if (!module || !import_type || !out)
+        return false;
+
+    LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name,
+              import_type->name, import_type->kind);
+
+    out->module_name = import_type->module_name;
+    out->field_name = import_type->name;
+    out->kind = import_type->kind;
+
+    if (import_type->kind != WASM_IMPORT_EXPORT_KIND_MEMORY) {
+        LOG_DEBUG("unimplemented import(%s,%s) kind %d for wasi test",
+                  import_type->module_name, import_type->name,
+                  import_type->kind);
+        return true;
+    }
+
+    out->u.memory =
+        create_wasi_test_memory(module, import_type->module_name,
+                                import_type->name, import_type->u.memory_type);
+    if (!out->u.memory) {
+        LOG_ERROR("create memory failed\n");
+        return false;
+    }
+
+    return true;
+}

+ 1 - 1
tests/wamr-test-suites/test_wamr.sh

@@ -1048,7 +1048,7 @@ function trigger()
     if [[ $TEST_CASE_ARR ]]; then
         for test in "${TEST_CASE_ARR[@]}"; do
             if [[ "$test" == "wasi_certification" ]]; then
-                EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_WASI_TEST=1"
+                EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_WASI_TEST=1 -DWAMR_BUILD_SPEC_TEST=0"
             fi
             if [[ "$test" == "wasi_certification"
                   || "$test" == "standalone" ]]; then