Ver Fonte

[instantiation linking] create and import WASMMemoryInstance for aot (#3887)

liang.he há 1 ano atrás
pai
commit
9b5058c7fe

+ 2 - 1
.gitignore

@@ -40,4 +40,5 @@ tests/benchmarks/coremark/coremark*
 samples/workload/include/**
 !samples/workload/include/.gitkeep
 
-# core/iwasm/libraries/wasi-threads
+core/iwasm/libraries/lib-wasi-threads/**/*.aot
+core/iwasm/libraries/lib-wasi-threads/**/*.wasm

+ 69 - 14
core/iwasm/aot/aot_loader.c

@@ -963,6 +963,11 @@ fail:
 static void
 destroy_import_memories(AOTImportMemory *import_memories)
 {
+    if (!import_memories)
+        return;
+
+    import_memories->module_name = NULL;
+    import_memories->memory_name = NULL;
     wasm_runtime_free(import_memories);
 }
 
@@ -991,6 +996,13 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
     uint64 size;
     uint32 i;
 
+    read_uint32(buf, buf_end, module->mem_init_data_count);
+
+    if (module->mem_init_data_count == 0) {
+        *p_buf = buf;
+        return true;
+    }
+
     /* Allocate memory */
     size = sizeof(AOTMemInitData *) * (uint64)module->mem_init_data_count;
     if (!(module->mem_init_data_list = data_list =
@@ -1035,6 +1047,51 @@ fail:
     return false;
 }
 
+static bool
+load_import_memory_info(const uint8 **p_buf, const uint8 *buf_end,
+                        AOTModule *module, bool is_load_from_file_buf,
+                        char *error_buf, uint32 error_buf_size)
+{
+    const uint8 *buf = *p_buf;
+
+    read_uint32(buf, buf_end, module->import_memory_count);
+
+    if (module->import_memory_count == 0) {
+        *p_buf = buf;
+        return true;
+    }
+
+    uint64 size = sizeof(AOTImportMemory) * (uint64)module->import_memory_count;
+    AOTImportMemory *import_memories =
+        loader_malloc(size, error_buf, error_buf_size);
+    if (!import_memories) {
+        return false;
+    }
+
+    module->import_memories = import_memories;
+    for (uint32 i = 0; i < module->import_memory_count; i++) {
+        AOTImportMemory *import_memory = import_memories + i;
+
+        read_uint32(buf, buf_end, import_memory->mem_type.flags);
+        if (!wasm_memory_check_flags(import_memory->mem_type.flags, error_buf,
+                                     error_buf_size, true)) {
+            set_error_buf(error_buf, error_buf_size, "invalid memory flags");
+            return false;
+        }
+
+        read_uint32(buf, buf_end, import_memory->mem_type.num_bytes_per_page);
+        read_uint32(buf, buf_end, import_memory->mem_type.init_page_count);
+        read_uint32(buf, buf_end, import_memory->mem_type.max_page_count);
+        read_string(buf, buf_end, import_memory->module_name);
+        read_string(buf, buf_end, import_memory->memory_name);
+    }
+
+    *p_buf = buf;
+    return true;
+fail:
+    return false;
+}
+
 static bool
 load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                  char *error_buf, uint32 error_buf_size)
@@ -1043,12 +1100,13 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
     uint64 total_size;
     const uint8 *buf = *p_buf;
 
-    read_uint32(buf, buf_end, module->import_memory_count);
-    /* We don't support import_memory_count > 0 currently */
-    if (module->import_memory_count > 0)
-        return false;
-
     read_uint32(buf, buf_end, module->memory_count);
+
+    if (module->memory_count == 0) {
+        *p_buf = buf;
+        return true;
+    }
+
     total_size = sizeof(AOTMemory) * (uint64)module->memory_count;
     if (!(module->memories =
               loader_malloc(total_size, error_buf, error_buf_size))) {
@@ -1068,14 +1126,6 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         read_uint32(buf, buf_end, module->memories[i].max_page_count);
     }
 
-    read_uint32(buf, buf_end, module->mem_init_data_count);
-
-    /* load memory init data list */
-    if (module->mem_init_data_count > 0
-        && !load_mem_init_data_list(&buf, buf_end, module, error_buf,
-                                    error_buf_size))
-        return false;
-
     *p_buf = buf;
     return true;
 fail:
@@ -2414,7 +2464,11 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end,
 {
     const uint8 *p = buf, *p_end = buf_end;
 
-    if (!load_memory_info(&p, p_end, module, error_buf, error_buf_size)
+    if (!load_import_memory_info(&p, p_end, module, is_load_from_file_buf,
+                                 error_buf, error_buf_size)
+        || !load_memory_info(&p, p_end, module, error_buf, error_buf_size)
+        || !load_mem_init_data_list(&p, p_end, module, error_buf,
+                                    error_buf_size)
         || !load_table_info(&p, p_end, module, error_buf, error_buf_size)
         || !load_type_info(&p, p_end, module, error_buf, error_buf_size)
         || !load_import_global_info(&p, p_end, module, is_load_from_file_buf,
@@ -3799,6 +3853,7 @@ has_module_memory64(AOTModule *module)
 {
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
+    /*FIXME: support import memory */
     if (module->import_memory_count > 0)
         return !!(module->import_memories[0].mem_type.flags & MEMORY64_FLAG);
     else if (module->memory_count > 0)

+ 404 - 135
core/iwasm/aot/aot_runtime.c

@@ -824,81 +824,93 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 }
 
 static void
-memories_deinstantiate(AOTModuleInstance *module_inst)
+memory_deinstantiate(AOTMemoryInstance *memory)
 {
-    uint32 i;
-    AOTMemoryInstance *memory_inst;
+    if (!memory) {
+        return;
+    }
 
-    for (i = 0; i < module_inst->memory_count; i++) {
-        memory_inst = module_inst->memories[i];
-        if (memory_inst) {
 #if WASM_ENABLE_SHARED_MEMORY != 0
-            if (shared_memory_is_shared(memory_inst)) {
-                uint32 ref_count = shared_memory_dec_reference(memory_inst);
-                /* if the reference count is not zero,
-                    don't free the memory */
-                if (ref_count > 0)
-                    continue;
-            }
+    if (shared_memory_is_shared(memory)) {
+        uint32 ref_count = shared_memory_dec_reference(memory);
+        /* if the reference count is not zero,
+            don't free the memory */
+        if (ref_count > 0) {
+            return;
+        }
+    }
 #endif
-            if (memory_inst->heap_handle) {
-                mem_allocator_destroy(memory_inst->heap_handle);
-                wasm_runtime_free(memory_inst->heap_handle);
-            }
 
-            if (memory_inst->memory_data) {
-                wasm_deallocate_linear_memory(memory_inst);
-            }
-        }
+    if (memory->heap_handle) {
+        mem_allocator_destroy(memory->heap_handle);
+        wasm_runtime_free(memory->heap_handle);
+        memory->heap_handle = NULL;
+    }
+
+    if (memory->memory_data) {
+        wasm_deallocate_linear_memory(memory);
+        memory->memory_data = NULL;
+    }
+}
+
+static void
+memories_deinstantiate(AOTModuleInstance *module_inst)
+{
+    /* import memories created by host or linker. released by them too */
+    for (uint32 i = ((AOTModule *)module_inst->module)->import_memory_count;
+         i < module_inst->memory_count; i++) {
+        memory_deinstantiate(module_inst->memories[i]);
     }
     wasm_runtime_free(module_inst->memories);
 }
 
+/*
+ * TODO: can be optimized by merging with another memory_instantiate() in
+ * wasm_runtime.c
+ */
 static AOTMemoryInstance *
-memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
-                   AOTModule *module, AOTMemoryInstance *memory_inst,
-                   AOTMemory *memory, uint32 memory_idx, uint32 heap_size,
-                   uint32 max_memory_pages, char *error_buf,
+memory_instantiate(const AOTModule *module, AOTModuleInstance *parent,
+                   AOTMemoryInstance *memory, AOTMemoryInstance *parent_memory,
+                   uint32 num_bytes_per_page, uint32 init_page_count,
+                   uint32 max_page_count, uint32 heap_size, uint32 flags,
+                   uint8 *aux_heap_base_global_data, char *error_buf,
                    uint32 error_buf_size)
 {
-    void *heap_handle;
-    uint32 num_bytes_per_page = memory->num_bytes_per_page;
-    uint32 init_page_count = memory->init_page_count;
-    uint32 max_page_count = wasm_runtime_get_max_mem(
-        max_memory_pages, memory->init_page_count, memory->max_page_count);
     uint32 default_max_pages;
-    uint32 inc_page_count, global_idx;
     uint32 bytes_of_last_page, bytes_to_page_end;
-    uint64 aux_heap_base,
-        heap_offset = (uint64)num_bytes_per_page * init_page_count;
-    uint64 memory_data_size, max_memory_data_size;
-    uint8 *p = NULL, *global_addr;
-    bool is_memory64 = memory->flags & MEMORY64_FLAG;
+    uint64 aux_heap_base;
+
+    bh_assert(memory != NULL);
 
     bool is_shared_memory = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
-    is_shared_memory = memory->flags & SHARED_MEMORY_FLAG ? true : false;
+    is_shared_memory = flags & SHARED_MEMORY_FLAG ? true : false;
+
     /* Shared memory */
     if (is_shared_memory && parent != NULL) {
-        AOTMemoryInstance *shared_memory_instance;
-        bh_assert(memory_idx == 0);
-        bh_assert(parent->memory_count > memory_idx);
-        shared_memory_instance = parent->memories[memory_idx];
-        shared_memory_inc_reference(shared_memory_instance);
-        return shared_memory_instance;
+        bh_assert(parent_memory != NULL);
+        memory = parent_memory;
+        shared_memory_inc_reference(memory);
+        return memory;
     }
-#endif
+#else
+    (void)parent;
+    (void)parent_memory;
+    (void)flags;
+#endif /* #if WASM_ENABLE_SHARED_MEMORY != 0 */
 
 #if WASM_ENABLE_MEMORY64 != 0
-    if (is_memory64) {
-        default_max_pages = DEFAULT_MEM64_MAX_PAGES;
+    if (flags & MEMORY64_FLAG) {
+        memory->is_memory64 = 1;
     }
-    else
 #endif
-    {
-        default_max_pages = DEFAULT_MAX_PAGES;
-    }
 
+    default_max_pages =
+        memory->is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
+
+    /* TODO: use small functions to reduce the complexity */
+    /* adjust heap_size, heap_offset and num_bytes_per_page */
+    uint64 heap_offset = (uint64)num_bytes_per_page * init_page_count;
     if (heap_size > 0 && module->malloc_func_index != (uint32)-1
         && module->free_func_index != (uint32)-1) {
         /* Disable app heap, use malloc/free function exported
@@ -906,9 +918,10 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
         heap_size = 0;
     }
 
-    /* If initial memory is the largest size allowed, disallowing insert host
-     * managed heap */
-    if (heap_size > 0 && heap_offset == MAX_LINEAR_MEMORY_SIZE) {
+    /* If initial memory is the largest size allowed, disallowing insert
+     * host managed heap */
+    if (heap_size > 0
+        && heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) {
         set_error_buf(error_buf, error_buf_size,
                       "failed to insert app heap into linear memory, "
                       "try using `--heap-size=0` option");
@@ -929,6 +942,8 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
         }
     }
     else if (heap_size > 0) {
+        uint32 inc_page_count = 0;
+
         if (init_page_count == max_page_count && init_page_count == 0) {
             /* If the memory data size is always 0, we resize it to
                one page for app heap */
@@ -961,11 +976,24 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
             }
 
             /* Adjust __heap_base global value */
-            global_idx = module->aux_heap_base_global_index
-                         - module->import_global_count;
-            global_addr = module_inst->global_data
-                          + module->globals[global_idx].data_offset;
-            *(uint32 *)global_addr = (uint32)aux_heap_base;
+            if (aux_heap_base_global_data == NULL) {
+                set_error_buf(
+                    error_buf, error_buf_size,
+                    "auxiliary heap base global data should not be NULL");
+                return NULL;
+            }
+
+#if WASM_ENABLE_MEMORY64 != 0
+            if (memory->is_memory64) {
+                /* For memory64, the global value should be i64 */
+                *(uint64 *)aux_heap_base_global_data = aux_heap_base;
+            }
+            else
+#endif
+            {
+                /* For memory32, the global value should be i32 */
+                *(uint32 *)aux_heap_base_global_data = (uint32)aux_heap_base;
+            }
             LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base);
         }
         else {
@@ -994,53 +1022,48 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
                 num_bytes_per_page, init_page_count, max_page_count);
     LOG_VERBOSE("  data offset: %" PRIu64 ", stack size: %d",
                 module->aux_data_end, module->aux_stack_size);
-    LOG_VERBOSE("  heap offset: %" PRIu64 ", heap size: %d\n", heap_offset,
-                heap_size);
 
-    max_memory_data_size = (uint64)num_bytes_per_page * max_page_count;
-    bh_assert(max_memory_data_size <= GET_MAX_LINEAR_MEMORY_SIZE(is_memory64));
+    uint64 max_memory_data_size = (uint64)num_bytes_per_page * max_page_count;
+    bh_assert(max_memory_data_size
+              <= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
     (void)max_memory_data_size;
 
-    /* TODO: memory64 uses is_memory64 flag */
-    if (wasm_allocate_linear_memory(&p, is_shared_memory, is_memory64,
-                                    num_bytes_per_page, init_page_count,
-                                    max_page_count, &memory_data_size)
+    uint64 memory_data_size = 0;
+    if (wasm_allocate_linear_memory(&memory->memory_data, is_shared_memory,
+                                    memory->is_memory64, num_bytes_per_page,
+                                    init_page_count, max_page_count,
+                                    &memory_data_size)
         != BHT_OK) {
         set_error_buf(error_buf, error_buf_size,
                       "allocate linear memory failed");
         return NULL;
     }
 
-    memory_inst->module_type = Wasm_Module_AoT;
-    memory_inst->num_bytes_per_page = num_bytes_per_page;
-    memory_inst->cur_page_count = init_page_count;
-    memory_inst->max_page_count = max_page_count;
-    memory_inst->memory_data_size = memory_data_size;
-#if WASM_ENABLE_MEMORY64 != 0
-    if (is_memory64) {
-        memory_inst->is_memory64 = 1;
-    }
-#endif
-
     /* Init memory info */
-    memory_inst->memory_data = p;
-    memory_inst->memory_data_end = p + memory_data_size;
+    memory->module_type = Wasm_Module_AoT;
+    memory->num_bytes_per_page = num_bytes_per_page;
+    memory->cur_page_count = init_page_count;
+    memory->max_page_count = max_page_count;
+    memory->memory_data_size = memory_data_size;
+    memory->heap_data = memory->memory_data + heap_offset;
+    memory->heap_data_end = memory->heap_data + heap_size;
+    memory->memory_data_end = memory->memory_data + memory->memory_data_size;
 
     /* Initialize heap info */
-    memory_inst->heap_data = p + heap_offset;
-    memory_inst->heap_data_end = p + heap_offset + heap_size;
     if (heap_size > 0) {
+        LOG_VERBOSE("  heap offset: %" PRIu64 ", heap size: %d\n", heap_offset,
+                    heap_size);
+
         uint32 heap_struct_size = mem_allocator_get_heap_struct_size();
 
-        if (!(heap_handle = runtime_malloc((uint64)heap_struct_size, error_buf,
-                                           error_buf_size))) {
+        memory->heap_handle =
+            runtime_malloc((uint64)heap_struct_size, error_buf, error_buf_size);
+        if (!memory->heap_handle) {
             goto fail1;
         }
 
-        memory_inst->heap_handle = heap_handle;
-
         if (!mem_allocator_create_with_struct_and_pool(
-                heap_handle, heap_struct_size, memory_inst->heap_data,
+                memory->heap_handle, heap_struct_size, memory->heap_data,
                 heap_size)) {
             set_error_buf(error_buf, error_buf_size, "init app heap failed");
             goto fail2;
@@ -1048,23 +1071,27 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
     }
 
     if (memory_data_size > 0) {
-        wasm_runtime_set_mem_bound_check_bytes(memory_inst, memory_data_size);
+        wasm_runtime_set_mem_bound_check_bytes(memory, memory_data_size);
     }
 
 #if WASM_ENABLE_SHARED_MEMORY != 0
     if (is_shared_memory) {
-        memory_inst->is_shared_memory = 1;
-        memory_inst->ref_count = 1;
+        memory->is_shared_memory = 1;
+        memory->ref_count = 1;
     }
 #endif
 
-    return memory_inst;
+    LOG_VERBOSE("Memory instantiate success.");
+    return memory;
 
 fail2:
-    if (heap_size > 0)
-        wasm_runtime_free(memory_inst->heap_handle);
+    if (heap_size > 0) {
+        wasm_runtime_free(memory->heap_handle);
+        memory->heap_handle = NULL;
+    }
 fail1:
-    wasm_deallocate_linear_memory(memory_inst);
+    if (memory->memory_data)
+        wasm_deallocate_linear_memory(memory);
 
     return NULL;
 }
@@ -1072,27 +1099,33 @@ fail1:
 AOTMemoryInstance *
 aot_lookup_memory(AOTModuleInstance *module_inst, char const *name)
 {
-#if WASM_ENABLE_MULTI_MEMORY != 0
-    uint32 i;
-    for (i = 0; i < module_inst->export_memory_count; i++)
+    for (uint32 i = 0; i < module_inst->export_memory_count; i++)
         if (!strcmp(module_inst->export_memories[i].name, name))
             return module_inst->export_memories[i].memory;
     return NULL;
-#else
-    (void)module_inst->export_memories;
-    if (!module_inst->memories)
-        return NULL;
-    return module_inst->memories[0];
-#endif
 }
 
+/*
+ * [0] could be internal or external
+ *
+ * it won't be NULL because of the reserved
+ * memory(aot_create_comp_data() in
+ * core/iwasm/compilation/aot.c),
+ */
 AOTMemoryInstance *
 aot_get_default_memory(AOTModuleInstance *module_inst)
 {
-    if (module_inst->memories)
-        return module_inst->memories[0];
-    else
+    if (!module_inst->memories) {
+        LOG_WARNING("memories[] is not instantiated");
         return NULL;
+    }
+
+    AOTMemoryInstance *default_memory = module_inst->memories[0];
+    bh_assert(default_memory && "default memory(AOT) can't be NULL");
+    if (!default_memory) {
+        LOG_ERROR("default memory(AOT) is NULL");
+    }
+    return default_memory;
 }
 
 AOTMemoryInstance *
@@ -1104,46 +1137,111 @@ aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index)
 }
 
 static bool
-memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
-                     AOTModule *module, uint32 heap_size,
-                     uint32 max_memory_pages, char *error_buf,
-                     uint32 error_buf_size)
+memories_instantiate(const AOTModule *module, AOTModuleInstance *module_inst,
+                     AOTModuleInstance *parent, uint32 heap_size,
+                     uint32 max_memory_pages, uint8 *aux_heap_base_global_data,
+                     const WASMExternInstance *imports, uint32 import_count,
+                     char *error_buf, uint32 error_buf_size)
 {
-    uint32 global_index, global_data_offset, length;
-    uint32 i, memory_count = module->memory_count;
-    AOTMemoryInstance *memories, *memory_inst;
-    AOTMemInitData *data_seg;
+    uint32 memory_count = module->import_memory_count + module->memory_count;
     uint64 total_size;
-    mem_offset_t base_offset;
+    uint32 mem_index = 0;
 
     module_inst->memory_count = memory_count;
     total_size = sizeof(AOTMemoryInstance *) * (uint64)memory_count;
+
     if (!(module_inst->memories =
               runtime_malloc(total_size, error_buf, error_buf_size))) {
         return false;
     }
 
-    memories = module_inst->global_table_data.memory_instances;
-    for (i = 0; i < memory_count; i++, memories++) {
-        memory_inst = memory_instantiate(
-            module_inst, parent, module, memories, &module->memories[i], i,
-            heap_size, max_memory_pages, error_buf, error_buf_size);
-        if (!memory_inst) {
+    AOTMemoryInstance *memory = module_inst->global_table_data.memory_instances;
+
+    /* process imported memories */
+    for (mem_index = 0; mem_index < module->import_memory_count;
+         mem_index++, memory++) {
+        AOTImportMemory *memory_type = module->import_memories + mem_index;
+
+#if WASM_ENABLE_MULTI_MODULE == 0
+        const WASMExternInstance *extern_inst =
+            wasm_runtime_get_extern_instance(imports, import_count,
+                                             WASM_IMPORT_EXPORT_KIND_MEMORY,
+                                             mem_index);
+        if (!extern_inst) {
+            LOG_ERROR("missing a import memory(%s, %s)",
+                      memory_type->module_name, memory_type->memory_name);
             return false;
         }
 
-        module_inst->memories[i] = memory_inst;
+        /* just in case */
+#ifndef NDEBUG
+        if (strcmp(memory_type->memory_name, extern_inst->field_name)) {
+            LOG_ERROR(
+                "mismatched import memory name: expect \"%s\", got \"%s\"",
+                memory_type->memory_name, extern_inst->field_name);
+            return false;
+        }
+#endif
+        /*
+         *TODO:
+         * - either memories[x] points to an external AOTMemoryInstance.
+         * - or memories[x] points to an internal AOTMemoryInstance in
+         *   global_table_data
+         *
+         * the first case is simple for maintaining resource management
+         */
+        module_inst->memories[mem_index] = extern_inst->u.memory;
+        bh_memcpy_s(memory, sizeof(AOTMemoryInstance), extern_inst->u.memory,
+                    sizeof(AOTMemoryInstance));
+#else
+        uint32 max_page_count = wasm_runtime_get_max_mem(
+            max_memory_pages, memory_type->mem_type.init_page_count,
+            memory_type->mem_type.max_page_count);
+
+        module_inst->memories[mem_index] = memory_instantiate(
+            module, parent, memory, parent ? parent->memories[mem_index] : NULL,
+            memory_type->mem_type.num_bytes_per_page,
+            memory_type->mem_type.init_page_count, max_page_count,
+            /* only inst->memories[0] will have a app heap */
+            mem_index == 0 ? heap_size : 0, memory_type->mem_type.flags,
+            aux_heap_base_global_data, error_buf, error_buf_size);
+        if (!module_inst->memories[mem_index]) {
+            return false;
+        }
+#endif
+    }
+
+    /* process internal memories */
+    for (; mem_index < memory_count; mem_index++, memory++) {
+        AOTMemory *memory_type =
+            module->memories + mem_index - module->import_memory_count;
+
+        uint32 max_page_count = wasm_runtime_get_max_mem(
+            max_memory_pages, memory_type->init_page_count,
+            memory_type->max_page_count);
+
+        module_inst->memories[mem_index] = memory_instantiate(
+            module, parent, memory, parent ? parent->memories[mem_index] : NULL,
+            memory_type->num_bytes_per_page, memory_type->init_page_count,
+            max_page_count,
+            /* only inst->memories[0] will have a app heap */
+            mem_index == 0 ? heap_size : 0, memory_type->flags,
+            aux_heap_base_global_data, error_buf, error_buf_size);
+        if (!module_inst->memories[mem_index]) {
+            return false;
+        }
     }
 
     /* Get default memory instance */
-    memory_inst = aot_get_default_memory(module_inst);
+    AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
     if (!memory_inst) {
-        /* Ignore setting memory init data if no memory inst is created */
-        return true;
+        set_error_buf(error_buf, error_buf_size, "get default memory failed");
+        return false;
     }
 
-    for (i = 0; i < module->mem_init_data_count; i++) {
-        data_seg = module->mem_init_data_list[i];
+    for (uint32 i = 0; i < module->mem_init_data_count; i++) {
+        AOTMemInitData *data_seg = module->mem_init_data_list[i];
+        mem_offset_t base_offset;
 #if WASM_ENABLE_BULK_MEMORY != 0
         if (data_seg->is_passive)
             continue;
@@ -1161,7 +1259,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
 
         /* Resolve memory data base offset */
         if (data_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
-            global_index = data_seg->offset.u.global_index;
+            uint32 global_index = data_seg->offset.u.global_index;
+            uint32 global_data_offset = 0;
 
             if (!check_global_init_expr(module, global_index, error_buf,
                                         error_buf_size)) {
@@ -1221,7 +1320,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
         }
 
         /* check offset + length(could be zero) */
-        length = data_seg->byte_count;
+        uint32 length = data_seg->byte_count;
         if (base_offset + length > memory_inst->memory_data_size) {
             LOG_DEBUG("base_offset(%" PR_MEM_OFFSET
                       ") + length(%d) > memory_data_size(%" PRIu64 ")",
@@ -1246,6 +1345,53 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
     return true;
 }
 
+AOTMemoryInstance *
+aot_create_memory(const AOTModule *module, const AOTMemoryType *type)
+{
+    if (!module || !type)
+        return NULL;
+
+    AOTMemoryInstance *memory = NULL;
+    char error_buf[64] = { 0 };
+
+    memory =
+        runtime_malloc(sizeof(AOTMemoryInstance), error_buf, sizeof(error_buf));
+    if (!memory) {
+        LOG_ERROR("Failed to allocate AOTMemoryInstance. %s", error_buf);
+        return NULL;
+    }
+
+    /*
+     * use provided max_page_count of type instead of adjusting with
+     * wasm_runtime_get_max_mem()
+     */
+    if (!memory_instantiate(module,
+                            NULL, // parent
+                            memory,
+                            NULL, // parent_memory
+                            type->num_bytes_per_page, type->init_page_count,
+                            type->max_page_count,
+                            0, // no app heap for host
+                            type->flags,
+                            NULL, // aux_heap_base_global_data
+                            error_buf, sizeof(error_buf))) {
+        wasm_runtime_free(memory);
+        return NULL;
+    }
+
+    return memory;
+}
+
+void
+aot_destroy_memory(AOTMemoryInstance *memory)
+{
+    if (!memory)
+        return;
+
+    memory_deinstantiate(memory);
+    wasm_runtime_free(memory);
+}
+
 static bool
 init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
                char *error_buf, uint32 error_buf_size)
@@ -1709,7 +1855,8 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size)
 AOTModuleInstance *
 aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
                 WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
-                uint32 max_memory_pages, char *error_buf, uint32 error_buf_size)
+                uint32 max_memory_pages, const WASMExternInstance *imports,
+                uint32 import_count, char *error_buf, uint32 error_buf_size)
 {
     AOTModuleInstance *module_inst;
 #if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
@@ -1719,7 +1866,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     const uint32 module_inst_struct_size =
         offsetof(AOTModuleInstance, global_table_data.bytes);
     const uint64 module_inst_mem_inst_size =
-        (uint64)module->memory_count * sizeof(AOTMemoryInstance);
+        (uint64)(module->memory_count + module->import_memory_count)
+        * sizeof(AOTMemoryInstance);
     uint64 total_size, table_size = 0;
     uint8 *p;
     uint32 i, extra_info_offset;
@@ -1728,6 +1876,21 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     bool ret = false;
 #endif
 
+#if WASM_ENABLE_MULTI_MODULE == 0
+    uint32 total_import_count =
+        module->import_func_count + module->import_global_count
+        + module->import_memory_count + module->import_table_count;
+    if (total_import_count > 0 && !imports) {
+        /*
+         * TODO: might be too strict
+         * might wasm_runtime_create_imports_with_builtin() here by default
+         */
+        set_error_buf(error_buf, error_buf_size,
+                      "imports is NULL while module has imports");
+        // return NULL;
+    }
+#endif
+
     /* Check heap size */
     heap_size = align_uint(heap_size, 8);
     if (heap_size > APP_HEAP_SIZE_MAX)
@@ -1862,6 +2025,16 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     if (!global_instantiate(module_inst, module, error_buf, error_buf_size))
         goto fail;
 
+    /* __heap_base */
+    uint8 *aux_heap_base_global_data = NULL;
+    if (module_inst->e->globals
+        && module->aux_heap_base_global_index < module->global_count) {
+        aux_heap_base_global_data =
+            module_inst->global_data
+            + module_inst->e->globals[module->aux_heap_base_global_index]
+                  .data_offset;
+    }
+
     /* Initialize table info */
     p += module->global_data_size;
     module_inst->table_count = module->table_count + module->import_table_count;
@@ -1870,8 +2043,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         goto fail;
 
     /* Initialize memory space */
-    if (!memories_instantiate(module_inst, parent, module, heap_size,
-                              max_memory_pages, error_buf, error_buf_size))
+    if (!memories_instantiate(module, module_inst, parent, heap_size,
+                              max_memory_pages, aux_heap_base_global_data,
+                              imports, import_count, error_buf, error_buf_size))
         goto fail;
 
     /* Initialize function pointers */
@@ -2168,10 +2342,14 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
     if (module_inst->export_functions)
         wasm_runtime_free(module_inst->export_functions);
 
-#if WASM_ENABLE_MULTI_MEMORY != 0
+    if (module_inst->export_globals)
+        wasm_runtime_free(module_inst->export_globals);
+
     if (module_inst->export_memories)
         wasm_runtime_free(module_inst->export_memories);
-#endif
+
+    if (module_inst->export_tables)
+        wasm_runtime_free(module_inst->export_tables);
 
     if (extra->functions) {
         uint32 func_idx;
@@ -3431,6 +3609,9 @@ static void
 const_string_node_size_cb(void *key, void *value, void *p_const_string_size)
 {
     uint32 const_string_size = 0;
+
+    (void)key;
+
     const_string_size += bh_hash_map_get_elem_struct_size();
     const_string_size += strlen((const char *)value) + 1;
     *(uint32 *)p_const_string_size += const_string_size;
@@ -3466,7 +3647,9 @@ aot_get_module_mem_consumption(const AOTModule *module,
 
     mem_conspn->tables_size = sizeof(AOTTable) * module->table_count;
 
-    mem_conspn->memories_size = sizeof(AOTMemory) * module->memory_count;
+    mem_conspn->memories_size =
+        sizeof(AOTMemory)
+        * (module->memory_count + module->import_memory_count);
     mem_conspn->globals_size = sizeof(AOTGlobal) * module->global_count;
     mem_conspn->exports_size = sizeof(AOTExport) * module->export_count;
 
@@ -5248,10 +5431,12 @@ aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func)
     char error_buf[128];
     AOTModule *sub_module = NULL;
 #endif
+
     import_func->func_ptr_linked = wasm_native_resolve_symbol(
         import_func->module_name, import_func->func_name,
         import_func->func_type, &import_func->signature,
         &import_func->attachment, &import_func->call_conv_raw);
+
 #if WASM_ENABLE_MULTI_MODULE != 0
     if (!import_func->func_ptr_linked) {
         if (!wasm_runtime_is_built_in_module(import_func->module_name)) {
@@ -5274,6 +5459,90 @@ aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func)
             }
         }
     }
+#else
+    (void)module;
 #endif
+
     return import_func->func_ptr_linked != NULL;
 }
+
+#if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
+/*
+ * The function is used to create a new WASMExternInstance list
+ * for a spawned thread.
+ */
+int32
+aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
+                    WASMExternInstance *out, int32 out_len)
+{
+    if (!module || !inst || !out)
+        return -1;
+
+    int32 spawned_import_count =
+        wasm_runtime_get_import_count((WASMModuleCommon *)module);
+    if (spawned_import_count > out_len) {
+        LOG_WARNING("The number of imported functions is more than the "
+                    "length of provided buffer ");
+        return -1;
+    }
+
+    for (int32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) {
+        wasm_import_t import_type = { 0 };
+
+        wasm_runtime_get_import_type((WASMModuleCommon *)module, i,
+                                     &import_type);
+
+        out[i].module_name = import_type.module_name;
+        out[i].field_name = import_type.name;
+        out[i].kind = import_type.kind;
+
+        if (import_type.kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
+            out[i].u.memory = inst->memories[import_memory_index];
+#if WASM_ENABLE_SHARED_MEMORY != 0
+            shared_memory_inc_reference(inst->memories[import_memory_index]);
+#endif
+            import_memory_index++;
+        }
+        else {
+            LOG_WARNING("for spawned, inherit() skips import(%s,%s) kind %d",
+                        import_type.module_name, import_type.name,
+                        import_type.kind);
+        }
+    }
+
+    return 0;
+}
+
+void
+aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
+                       int32 import_count)
+{
+    if (!module || !imports)
+        return;
+
+    int32 spawned_import_count =
+        wasm_runtime_get_import_count((WASMModuleCommon *)module);
+    if (spawned_import_count > import_count) {
+        LOG_WARNING("The number of imported functions is more than the "
+                    "length of provided buffer ");
+        return;
+    }
+
+    for (int32 i = 0; i < import_count; i++) {
+        WASMExternInstance *import = imports + i;
+
+        if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
+            if (!import->u.memory)
+                continue;
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+            shared_memory_dec_reference(import->u.memory);
+#endif
+        }
+        else {
+            LOG_WARNING("for spawned, disinherit() skips import(%s,%s) kind %d",
+                        import->module_name, import->field_name, import->kind);
+        }
+    }
+}
+#endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */

+ 17 - 2
core/iwasm/aot/aot_runtime.h

@@ -533,8 +533,8 @@ aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func);
 AOTModuleInstance *
 aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
                 WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
-                uint32 max_memory_pages, char *error_buf,
-                uint32 error_buf_size);
+                uint32 max_memory_pages, const WASMExternInstance *imports,
+                uint32 import_count, char *error_buf, uint32 error_buf_size);
 
 /**
  * Deinstantiate a AOT module instance, destroy the resources.
@@ -545,6 +545,11 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
 void
 aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst);
 
+AOTMemoryInstance *
+aot_create_memory(const AOTModule *module, const AOTMemoryType *type);
+
+void
+aot_destroy_memory(AOTMemoryInstance *memory);
 /**
  * Lookup an exported function in the AOT module instance.
  *
@@ -855,6 +860,16 @@ aot_set_module_name(AOTModule *module, const char *name, char *error_buf,
 const char *
 aot_get_module_name(AOTModule *module);
 
+#if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
+int32
+aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
+                    WASMExternInstance *out, int32 out_len);
+
+void
+aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
+                       int32 import_count);
+#endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 7 - 4
core/iwasm/common/wasm_memory.c

@@ -1547,8 +1547,9 @@ wasm_runtime_create_memory(WASMModuleCommon *module, WASMMemoryType *type)
 #endif
 
 #if WASM_ENABLE_AOT != 0
-    if (module->module_type == Wasm_Module_AoT)
-        bh_assert(false && "Unsupported operation");
+    if (module->module_type == Wasm_Module_AoT) {
+        return aot_create_memory((AOTModule *)module, type);
+    }
 #endif
 
     LOG_ERROR("create memory failed, invalid module type");
@@ -1570,8 +1571,10 @@ wasm_runtime_destroy_memory(WASMModuleCommon *const module,
 #endif
 
 #if WASM_ENABLE_AOT != 0
-    if (module->module_type == Wasm_Module_AoT)
-        bh_assert(false && "Unsupported operation");
+    if (module->module_type == Wasm_Module_AoT) {
+        aot_destroy_memory(memory);
+        return;
+    }
 #endif
 
     LOG_ERROR("destroy memory failed, invalid module type");

+ 27 - 3
core/iwasm/common/wasm_runtime_common.c

@@ -1638,7 +1638,8 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module,
     if (module->module_type == Wasm_Module_AoT)
         return (WASMModuleInstanceCommon *)aot_instantiate(
             (AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main,
-            stack_size, heap_size, max_memory_pages, error_buf, error_buf_size);
+            stack_size, heap_size, max_memory_pages, imports, import_count,
+            error_buf, error_buf_size);
 #endif
     set_error_buf(error_buf, error_buf_size,
                   "Instantiate module failed, invalid module type");
@@ -7918,7 +7919,8 @@ wasm_runtime_inherit_imports(WASMModuleCommon *module,
 #endif
 #if WASM_ENABLE_AOT != 0
     if (module->module_type == Wasm_Module_AoT) {
-        bh_assert(false && "Unsupported operation");
+        return aot_inherit_imports((AOTModule *)module,
+                                   (AOTModuleInstance *)inst, out, out_len);
     }
 #endif
     LOG_ERROR("inherit imports failed, invalid module type");
@@ -7937,9 +7939,31 @@ wasm_runtime_disinherit_imports(WASMModuleCommon *module,
 #endif
 #if WASM_ENABLE_AOT != 0
     if (module->module_type == Wasm_Module_AoT) {
-        bh_assert(false && "Unsupported operation");
+        return aot_disinherit_imports((AOTModule *)module, imports,
+                                      import_count);
     }
 #endif
     LOG_ERROR("disinherit imports failed, invalid module type");
 }
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
+
+const WASMExternInstance *
+wasm_runtime_get_extern_instance(const WASMExternInstance *imports,
+                                 uint32 import_count,
+                                 wasm_import_export_kind_t kind, uint32 index)
+{
+    for (uint32 i = 0, target_kind_index = 0; i < import_count; i++) {
+        if (imports[i].kind != kind) {
+            continue;
+        }
+
+        if (target_kind_index != index) {
+            target_kind_index++;
+            continue;
+        }
+
+        return imports + i;
+    }
+
+    return NULL;
+}

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

@@ -1231,7 +1231,12 @@ void
 wasm_runtime_disinherit_imports(WASMModuleCommon *module,
                                 WASMExternInstance *imports,
                                 int32 import_count);
-#endif
+#endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
+
+const WASMExternInstance *
+wasm_runtime_get_extern_instance(const WASMExternInstance *imports,
+                                 uint32 import_count,
+                                 wasm_import_export_kind_t kind, uint32 index);
 
 #ifdef __cplusplus
 }

+ 96 - 36
core/iwasm/compilation/aot.c

@@ -31,6 +31,82 @@ aot_set_last_error(const char *error)
         aot_error[0] = '\0';
 }
 
+static AOTImportMemory *
+aot_create_import_memories(const WASMModule *module, uint32 import_memory_count)
+{
+    uint64 size;
+    AOTImportMemory *import_memories;
+    unsigned i;
+
+    bh_assert(import_memory_count == module->import_memory_count);
+
+    size = sizeof(AOTImportMemory) * (uint64)import_memory_count;
+    if (size >= UINT32_MAX) {
+        aot_set_last_error("too big allocate size");
+        return NULL;
+    }
+
+    import_memories = wasm_runtime_malloc((uint32)size);
+    if (!import_memories) {
+        aot_set_last_error("allocate memory failed.");
+        return NULL;
+    }
+
+    memset(import_memories, 0, (uint32)size);
+
+    for (i = 0; i < module->import_memory_count; i++) {
+        AOTImportMemory *memory_aot = import_memories + i;
+        WASMImport *memory_wasm = module->import_memories + i;
+
+        memory_aot->module_name = memory_wasm->u.memory.module_name;
+        memory_aot->memory_name = memory_wasm->u.memory.field_name;
+        memory_aot->mem_type.flags = memory_wasm->u.memory.mem_type.flags;
+        memory_aot->mem_type.init_page_count =
+            memory_wasm->u.memory.mem_type.init_page_count;
+        memory_aot->mem_type.max_page_count =
+            memory_wasm->u.memory.mem_type.max_page_count;
+        memory_aot->mem_type.num_bytes_per_page =
+            memory_wasm->u.memory.mem_type.num_bytes_per_page;
+    }
+
+    return import_memories;
+}
+
+static AOTMemory *
+aot_create_memories(const WASMModule *module, uint32 memory_count)
+{
+    uint64 size;
+    AOTMemory *memories;
+    unsigned i;
+
+    size = (uint64)memory_count * sizeof(AOTMemory);
+    if (size >= UINT32_MAX) {
+        aot_set_last_error("too big allocate size");
+        return NULL;
+    }
+
+    memories = wasm_runtime_malloc((uint32)size);
+    if (!memories) {
+        aot_set_last_error("create memories array failed.\n");
+        return NULL;
+    }
+
+    memset(memories, 0, size);
+
+    /* in reserved case, assign nothing */
+    for (i = 0; i < module->memory_count; i++) {
+        AOTMemory *memory_aot = memories + i;
+        WASMMemory *memory_wasm = module->memories + i;
+
+        memory_aot->flags = memory_wasm->flags;
+        memory_aot->init_page_count = memory_wasm->init_page_count;
+        memory_aot->max_page_count = memory_wasm->max_page_count;
+        memory_aot->num_bytes_per_page = memory_wasm->num_bytes_per_page;
+    }
+
+    return memories;
+}
+
 static void
 aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
 {
@@ -534,52 +610,36 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
 
     memset(comp_data, 0, sizeof(AOTCompData));
 
-    comp_data->memory_count =
-        module->import_memory_count + module->memory_count;
+    /* Create import memories */
+    comp_data->import_memory_count = module->import_memory_count;
+    if (comp_data->import_memory_count) {
+        comp_data->import_memories =
+            aot_create_import_memories(module, comp_data->import_memory_count);
+        if (!comp_data->import_memories) {
+            goto fail;
+        }
+    }
 
-    /* TODO: create import memories */
+    /* Create memories */
+    comp_data->memory_count = module->memory_count;
 
     /* Allocate memory for memory array, reserve one AOTMemory space at least */
-    /* TODO: multi-memory */
-    if (!comp_data->memory_count)
+    if (module->import_memory_count + module->memory_count == 0)
         comp_data->memory_count = 1;
 
-    size = (uint64)comp_data->memory_count * sizeof(AOTMemory);
-    if (size >= UINT32_MAX
-        || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
-        aot_set_last_error("create memories array failed.\n");
-        goto fail;
+    if (comp_data->memory_count) {
+        comp_data->memories =
+            aot_create_memories(module, comp_data->memory_count);
+        if (!comp_data->memories) {
+            goto fail;
+        }
     }
-    memset(comp_data->memories, 0, size);
 
-    if (!(module->import_memory_count + module->memory_count)) {
+    /* inherit reserved memory. keep it in memories[] */
+    if (module->import_memory_count + module->memory_count == 0) {
         comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
     }
 
-    /* Set memory page count */
-    for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
-        if (i < module->import_memory_count) {
-            comp_data->memories[i].flags =
-                module->import_memories[i].u.memory.mem_type.flags;
-            comp_data->memories[i].num_bytes_per_page =
-                module->import_memories[i].u.memory.mem_type.num_bytes_per_page;
-            comp_data->memories[i].init_page_count =
-                module->import_memories[i].u.memory.mem_type.init_page_count;
-            comp_data->memories[i].max_page_count =
-                module->import_memories[i].u.memory.mem_type.max_page_count;
-        }
-        else {
-            j = i - module->import_memory_count;
-            comp_data->memories[i].flags = module->memories[j].flags;
-            comp_data->memories[i].num_bytes_per_page =
-                module->memories[j].num_bytes_per_page;
-            comp_data->memories[i].init_page_count =
-                module->memories[j].init_page_count;
-            comp_data->memories[i].max_page_count =
-                module->memories[j].max_page_count;
-        }
-    }
-
     /* Create memory data segments */
     comp_data->mem_init_data_count = module->data_seg_count;
     if (comp_data->mem_init_data_count > 0

+ 21 - 1
core/iwasm/compilation/aot_compiler.h

@@ -528,8 +528,28 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
         wasm_runtime_free(aot_value);                                        \
     } while (0)
 
+/* requires comp_ctx */
+#define DEFAULT_MEMORY_TYPE                                 \
+    (comp_ctx->comp_data->import_memory_count               \
+         ? comp_ctx->comp_data->import_memories[0].mem_type \
+         : comp_ctx->comp_data->memories[0])
+
+#define DEFAULT_MEMORY_TYPE_FLAG (DEFAULT_MEMORY_TYPE.flags)
+
+#define DEFAULT_MEMORY_TYPE_NUM_BYTES_PER_PAGE \
+    (DEFAULT_MEMORY_TYPE.num_bytes_per_page)
+
+#define DEFAULT_MEMORY_TYPE_INIT_PAGE_COUNT \
+    (DEFAULT_MEMORY_TYPE.init_page_count)
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#define IS_SHARED_MEMORY (DEFAULT_MEMORY_TYPE_FLAG & SHARED_MEMORY_FLAG)
+#else
+#define IS_SHARED_MEMORY 0
+#endif
+
 #if WASM_ENABLE_MEMORY64 != 0
-#define IS_MEMORY64 (comp_ctx->comp_data->memories[0].flags & MEMORY64_FLAG)
+#define IS_MEMORY64 (DEFAULT_MEMORY_TYPE_FLAG & MEMORY64_FLAG)
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
 #define IS_TABLE64(i) \

+ 144 - 38
core/iwasm/compilation/aot_emit_aot_file.c

@@ -165,14 +165,15 @@ get_mem_init_data_size(AOTCompContext *comp_ctx, AOTMemInitData *mem_init_data)
 }
 
 static uint32
-get_mem_init_data_list_size(AOTCompContext *comp_ctx,
-                            AOTMemInitData **mem_init_data_list,
-                            uint32 mem_init_data_count)
+get_mem_init_data_list_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
-    AOTMemInitData **mem_init_data = mem_init_data_list;
+    AOTMemInitData **mem_init_data = comp_data->mem_init_data_list;
     uint32 size = 0, i;
 
-    for (i = 0; i < mem_init_data_count; i++, mem_init_data++) {
+    /* mem_init_data_count */
+    size = (uint32)sizeof(uint32);
+
+    for (i = 0; i < comp_data->mem_init_data_count; i++, mem_init_data++) {
         size = align_uint(size, 4);
         size += get_mem_init_data_size(comp_ctx, *mem_init_data);
     }
@@ -180,14 +181,34 @@ get_mem_init_data_list_size(AOTCompContext *comp_ctx,
 }
 
 static uint32
-get_import_memory_size(AOTCompData *comp_data)
+get_import_memory_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
-    /* currently we only emit import_memory_count = 0 */
-    return sizeof(uint32);
+    AOTImportMemory *import_memory = NULL;
+    uint32 i = 0;
+    uint32 size = 0;
+
+    /* import_memory_count */
+    size = (uint32)sizeof(uint32);
+
+    /* AOTImportMemory[] */
+    for (i = 0, import_memory = comp_data->import_memories;
+         i < comp_data->import_memory_count; i++, import_memory++) {
+        size = align_uint(size, 4);
+
+        /* u32 * 4 */
+        size += (uint32)sizeof(uint32) * 4;
+        /* module_name */
+        size += get_string_size(comp_ctx, import_memory->module_name);
+        size = align_uint(size, 2);
+        /* field_name */
+        size += get_string_size(comp_ctx, import_memory->memory_name);
+    }
+
+    return size;
 }
 
 static uint32
-get_memory_size(AOTCompData *comp_data)
+get_memory_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
     /* memory_count + count * (flags + num_bytes_per_page +
                                init_page_count + max_page_count) */
@@ -195,18 +216,6 @@ get_memory_size(AOTCompData *comp_data)
                     + comp_data->memory_count * sizeof(uint32) * 4);
 }
 
-static uint32
-get_mem_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
-{
-    /* import_memory_size + memory_size
-       + init_data_count + init_data_list */
-    return get_import_memory_size(comp_data) + get_memory_size(comp_data)
-           + (uint32)sizeof(uint32)
-           + get_mem_init_data_list_size(comp_ctx,
-                                         comp_data->mem_init_data_list,
-                                         comp_data->mem_init_data_count);
-}
-
 static uint32
 get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
                    InitializerExpression *expr)
@@ -767,7 +776,45 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
 {
     uint32 size = 0;
 
-    size += get_mem_info_size(comp_ctx, comp_data);
+    /*
+     * -------------------------------------------------------
+     * | u32 import_memory_count
+     * -------------------------------------------------------
+     * |                                      | u32 flags
+     * | AOTImportMemory[import_memory_count] | u32 num_bytes_per_page
+     * |                                      | u32 init_page_count
+     * |                                      | u32 max_page_count
+     * |                                      | str module_name
+     * |                                      | str field_name
+     * -------------------------------------------------------
+     * | padding
+     * -------------------------------------------------------
+     * | u32 memory_count
+     * -------------------------------------------------------
+     * |                             | u32 flags
+     * | AOTMemoryType[memory_count] | u32 num_bytes_per_page
+     * |                             | u32 init_page_count
+     * |                             | u32 max_page_count
+     * -------------------------------------------------------
+     * | padding (TBC: previous aot doesn't have this padding by design)
+     * -------------------------------------------------------
+     * | u32 mem_init_data_count
+     * -------------------------------------------------------
+     * |                                     | u32 is_passive/placeholder
+     * |                                     | u32 memory_index/placeholder
+     * |                                     | u32 init expr type
+     * | AOTMemInitData[mem_init_data_count] | u32 init expr value
+     * |                                     | u32 byte count
+     * |                                     | u8* bytes
+     * -------------------------------------------------------
+     */
+    size += get_import_memory_size(comp_ctx, comp_data);
+
+    size = align_uint(size, 4);
+    size += get_memory_size(comp_ctx, comp_data);
+
+    size = align_uint(size, 4);
+    size += get_mem_init_data_list_size(comp_ctx, comp_data);
 
     size = align_uint(size, 4);
     size += get_table_info_size(comp_ctx, comp_data);
@@ -1745,30 +1792,83 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                    AOTCompContext *comp_ctx, InitializerExpression *expr);
 
 static bool
-aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
-                  AOTCompContext *comp_ctx, AOTCompData *comp_data,
-                  AOTObjectData *obj_data)
+aot_emit_import_memory_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                            AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                            AOTObjectData *obj_data)
 {
     uint32 offset = *p_offset, i;
-    AOTMemInitData **init_datas = comp_data->mem_init_data_list;
+    AOTImportMemory *import_memory = NULL;
 
     *p_offset = offset = align_uint(offset, 4);
 
-    /* Emit import memory count, only emit 0 currently.
-       TODO: emit the actual import memory count and
-             the full import memory info. */
-    EMIT_U32(0);
+    /* Emit import memory count */
+    EMIT_U32(comp_data->import_memory_count);
+
+    for (i = 0, import_memory = comp_data->import_memories;
+         i < comp_data->import_memory_count; i++, import_memory++) {
+        offset = align_uint(offset, 4);
+
+        EMIT_U32(import_memory->mem_type.flags);
+        EMIT_U32(import_memory->mem_type.num_bytes_per_page);
+        EMIT_U32(import_memory->mem_type.init_page_count);
+        EMIT_U32(import_memory->mem_type.max_page_count);
+
+        EMIT_STR(import_memory->module_name);
+        offset = align_uint(offset, 2);
+
+        EMIT_STR(import_memory->memory_name);
+    }
+
+    if (offset - *p_offset != get_import_memory_size(comp_ctx, comp_data)) {
+        aot_set_last_error("emit import memory info failed.");
+        return false;
+    }
+
+    *p_offset = offset;
+    return true;
+}
+
+static bool
+aot_emit_memory_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                     AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                     AOTObjectData *obj_data)
+{
+    uint32 offset = *p_offset, i;
+    AOTMemory *memory = NULL;
+
+    *p_offset = offset = align_uint(offset, 4);
 
     /* Emit memory count */
     EMIT_U32(comp_data->memory_count);
+
     /* Emit memory items */
-    for (i = 0; i < comp_data->memory_count; i++) {
-        EMIT_U32(comp_data->memories[i].flags);
-        EMIT_U32(comp_data->memories[i].num_bytes_per_page);
-        EMIT_U32(comp_data->memories[i].init_page_count);
-        EMIT_U32(comp_data->memories[i].max_page_count);
+    for (i = 0, memory = comp_data->memories; i < comp_data->memory_count;
+         i++, memory++) {
+        EMIT_U32(memory->flags);
+        EMIT_U32(memory->num_bytes_per_page);
+        EMIT_U32(memory->init_page_count);
+        EMIT_U32(memory->max_page_count);
     }
 
+    if (offset - *p_offset != get_memory_size(comp_ctx, comp_data)) {
+        aot_set_last_error("emit memory info failed.");
+        return false;
+    }
+
+    *p_offset = offset;
+    return true;
+}
+
+static bool
+aot_emit_memory_init_data_list(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                               AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                               AOTObjectData *obj_data)
+{
+    uint32 offset = *p_offset, i;
+    AOTMemInitData **init_datas = comp_data->mem_init_data_list;
+
+    *p_offset = offset = align_uint(offset, 4);
+
     /* Emit mem init data count */
     EMIT_U32(comp_data->mem_init_data_count);
     /* Emit mem init data items */
@@ -1793,8 +1893,9 @@ aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
         EMIT_BUF(init_datas[i]->bytes, init_datas[i]->byte_count);
     }
 
-    if (offset - *p_offset != get_mem_info_size(comp_ctx, comp_data)) {
-        aot_set_last_error("emit memory info failed.");
+    if (offset - *p_offset
+        != get_mem_init_data_list_size(comp_ctx, comp_data)) {
+        aot_set_last_error("emit memory init data list failed.");
         return false;
     }
 
@@ -2383,7 +2484,12 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     EMIT_U32(AOT_SECTION_TYPE_INIT_DATA);
     EMIT_U32(section_size);
 
-    if (!aot_emit_mem_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data)
+    if (!aot_emit_import_memory_info(buf, buf_end, &offset, comp_ctx, comp_data,
+                                     obj_data)
+        || !aot_emit_memory_info(buf, buf_end, &offset, comp_ctx, comp_data,
+                                 obj_data)
+        || !aot_emit_memory_init_data_list(buf, buf_end, &offset, comp_ctx,
+                                           comp_data, obj_data)
         || !aot_emit_table_info(buf, buf_end, &offset, comp_ctx, comp_data,
                                 obj_data)
         || !aot_emit_type_info(buf, buf_end, &offset, comp_ctx, comp_data,

+ 1 - 2
core/iwasm/compilation/aot_emit_control.c

@@ -881,8 +881,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
     LLVMBasicBlockRef terminate_block, non_terminate_block;
     AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
-    bool is_shared_memory =
-        comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false;
+    bool is_shared_memory = IS_SHARED_MEMORY;
 
     /* Only need to check the suspend flags when memory is shared since
        shared memory must be enabled for multi-threading */

+ 8 - 14
core/iwasm/compilation/aot_emit_memory.c

@@ -124,12 +124,11 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMBasicBlockRef check_succ, block_maddr_phi = NULL;
     AOTValue *aot_value_top;
     uint32 local_idx_of_aot_value = 0;
-    uint64 const_value;
+    uint64 const_value = 0;
     bool is_target_64bit, is_local_of_aot_value = false;
     bool is_const = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
-    bool is_shared_memory =
-        comp_ctx->comp_data->memories[0].flags & SHARED_MEMORY_FLAG;
+    bool is_shared_memory = IS_SHARED_MEMORY;
 #endif
 #if WASM_ENABLE_MEMORY64 == 0
     bool is_memory64 = false;
@@ -207,10 +206,8 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             value = const_value;
         }
         uint64 mem_offset = value + (uint64)offset;
-        uint32 num_bytes_per_page =
-            comp_ctx->comp_data->memories[0].num_bytes_per_page;
-        uint32 init_page_count =
-            comp_ctx->comp_data->memories[0].init_page_count;
+        uint32 num_bytes_per_page = DEFAULT_MEMORY_TYPE_NUM_BYTES_PER_PAGE;
+        uint32 init_page_count = DEFAULT_MEMORY_TYPE_INIT_PAGE_COUNT;
         uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
 
         if (alignp != NULL) {
@@ -408,8 +405,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         && !(is_local_of_aot_value
              && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value,
                                            offset, bytes))) {
-        uint32 init_page_count =
-            comp_ctx->comp_data->memories[0].init_page_count;
+        uint32 init_page_count = DEFAULT_MEMORY_TYPE_INIT_PAGE_COUNT;
         if (init_page_count == 0) {
             LLVMValueRef mem_size;
 
@@ -1149,7 +1145,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     /* Get memory base address and memory data size */
 #if WASM_ENABLE_SHARED_MEMORY != 0
-    bool is_shared_memory = comp_ctx->comp_data->memories[0].flags & 0x02;
+    bool is_shared_memory = IS_SHARED_MEMORY;
 
     if (func_ctx->mem_space_unchanged || is_shared_memory) {
 #else
@@ -1174,10 +1170,8 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     if (LLVMIsEfficientConstInt(offset) && LLVMIsEfficientConstInt(bytes)) {
         uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset);
         uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes);
-        uint32 num_bytes_per_page =
-            comp_ctx->comp_data->memories[0].num_bytes_per_page;
-        uint32 init_page_count =
-            comp_ctx->comp_data->memories[0].init_page_count;
+        uint32 num_bytes_per_page = DEFAULT_MEMORY_TYPE_NUM_BYTES_PER_PAGE;
+        uint32 init_page_count = DEFAULT_MEMORY_TYPE_INIT_PAGE_COUNT;
         uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
         if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) {
             /* inside memory space */

+ 8 - 7
core/iwasm/compilation/aot_emit_table.c

@@ -90,13 +90,14 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx,
     AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
     AOTTable *tbls = comp_ctx->comp_data->tables;
 
-    offset =
-        offsetof(AOTModuleInstance, global_table_data.bytes)
-        + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
-        /* Get global data size according to target info */
-        + (comp_ctx->pointer_size == sizeof(uint64)
-               ? comp_ctx->comp_data->global_data_size_64bit
-               : comp_ctx->comp_data->global_data_size_32bit);
+    offset = offsetof(AOTModuleInstance, global_table_data.bytes)
+             + (uint64)(comp_ctx->comp_data->memory_count
+                        + comp_ctx->comp_data->import_memory_count)
+                   * sizeof(AOTMemoryInstance)
+             /* Get global data size according to target info */
+             + (comp_ctx->pointer_size == sizeof(uint64)
+                    ? comp_ctx->comp_data->global_data_size_64bit
+                    : comp_ctx->comp_data->global_data_size_32bit);
 
     while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
         offset += offsetof(AOTTableInstance, elems);

+ 4 - 3
core/iwasm/compilation/aot_emit_variable.c

@@ -161,9 +161,10 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef offset, 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;
+    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);
 

+ 5 - 7
core/iwasm/compilation/aot_llvm.c

@@ -1204,11 +1204,10 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     func_ctx->mem_space_unchanged = mem_space_unchanged;
 
-    memory_count = module->memory_count + module->import_memory_count;
-    /* If the module doesn't have memory, reserve
-        one mem_info space with empty content */
-    if (memory_count == 0)
-        memory_count = 1;
+    /* comp_data contains processed reservation */
+    memory_count = comp_ctx->comp_data->import_memory_count
+                   + comp_ctx->comp_data->memory_count;
+    bh_assert(memory_count > 0);
 
     if (!(func_ctx->mem_info =
               wasm_runtime_malloc(sizeof(AOTMemInfo) * memory_count))) {
@@ -1219,8 +1218,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Currently we only create memory info for memory 0 */
     /* Load memory base address */
 #if WASM_ENABLE_SHARED_MEMORY != 0
-    is_shared_memory =
-        comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false;
+    is_shared_memory = IS_SHARED_MEMORY;
     if (is_shared_memory) {
         LLVMValueRef shared_mem_addr;
         offset = I32_CONST(offsetof(AOTModuleInstance, memories));

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

@@ -280,6 +280,17 @@ typedef struct InstantiationArgs {
     uint32_t default_stack_size;
     uint32_t host_managed_heap_size;
     uint32_t max_memory_pages;
+    /*
+     * Callers need to create a list of wasm_extern_inst_t that follows the
+     * sequence specified by the import section.
+     *
+     * The usual way to determine the sequence is by calling
+     * wasm_runtime_get_import_type().
+     *
+     * The runtime will complete the import list with known elements,
+     * such as functions from wasi_snapshot_preview1 and registered native
+     * functions. The caller must handle the parts that are not known.
+     */
     const wasm_extern_inst_t imports;
     uint32_t import_count;
 } InstantiationArgs;

+ 65 - 53
core/iwasm/interpreter/wasm_runtime.c

@@ -300,15 +300,15 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent,
                    uint8 *aux_heap_base_global_data, char *error_buf,
                    uint32 error_buf_size)
 {
+    bh_assert(memory != NULL);
+
     bool is_shared_memory = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
     is_shared_memory = flags & SHARED_MEMORY_FLAG ? true : false;
 
-    bh_assert(memory != NULL);
-
     /* shared memory */
     if (is_shared_memory && parent != NULL) {
-        bh_assert(parent->memory_count > 0);
+        bh_assert(parent_memory != NULL);
         memory = parent_memory;
         shared_memory_inc_reference(memory);
         return memory;
@@ -360,6 +360,7 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent,
         }
         else if (heap_size > 0) {
             uint32 inc_page_count = 0;
+
             if (init_page_count == max_page_count && init_page_count == 0) {
                 /* If the memory data size is always 0, we resize it to
                    one page for app heap */
@@ -445,6 +446,8 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent,
     LOG_VERBOSE("Memory instantiate:");
     LOG_VERBOSE("  page bytes: %u, init pages: %u, max pages: %u",
                 num_bytes_per_page, init_page_count, max_page_count);
+    LOG_VERBOSE("  data offset: %" PRIu64 ", stack size: %d",
+                module->aux_data_end, module->aux_stack_size);
 
 #ifndef NDEBUG
     {
@@ -532,12 +535,13 @@ static WASMMemoryInstance **
 memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
                      WASMModuleInstance *parent, uint32 heap_size,
                      uint32 max_memory_pages, uint8 *aux_heap_base_global_data,
+                     const WASMExternInstance *imports, uint32 import_count,
                      char *error_buf, uint32 error_buf_size)
 {
     uint32 mem_index = 0, i,
            memory_count = module->import_memory_count + module->memory_count;
     uint64 total_size;
-    WASMMemoryInstance **memories, *memory;
+    WASMMemoryInstance **memories;
 
     total_size = sizeof(WASMMemoryInstance *) * (uint64)memory_count;
 
@@ -545,25 +549,29 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
         return NULL;
     }
 
-    memory = module_inst->global_table_data.memory_instances;
+    WASMMemoryInstance *memory =
+        module_inst->global_table_data.memory_instances;
 
     /* instantiate memories from import section */
+    for (mem_index = 0; mem_index < module->import_memory_count;
+         mem_index++, memory++) {
+        WASMMemoryImport *memory_type =
+            &((module->import_memories + mem_index)->u.memory);
+
 #if WASM_ENABLE_MULTI_MODULE != 0
-    WASMImport *import = module->import_memories;
-    for (i = 0; i < module->import_memory_count; i++, import++, memory++) {
         // TODO: ? make sure import->u.memory.import_module is set properly
-        if (import->u.memory.import_module != NULL) {
+        if (memory_type->import_module != NULL) {
             WASMModuleInstance *module_inst_linked;
 
             if (!(module_inst_linked = get_sub_module_inst(
-                      module_inst, import->u.memory.import_module))) {
+                      module_inst, memory_type->import_module))) {
                 set_error_buf(error_buf, error_buf_size, "unknown memory");
                 memories_deinstantiate(module_inst, memories, memory_count);
                 return NULL;
             }
 
-            if (!(memories[mem_index++] = wasm_lookup_memory(
-                      module_inst_linked, import->u.memory.field_name))) {
+            if (!(memories[mem_index] = wasm_lookup_memory(
+                      module_inst_linked, memory_type->field_name))) {
                 set_error_buf(error_buf, error_buf_size, "unknown memory");
                 memories_deinstantiate(module_inst, memories, memory_count);
                 return NULL;
@@ -573,12 +581,12 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
             // TODO: Although it is for inherited memory, it misses a situation
             // where the memory is imported from host or other modules
             uint32 num_bytes_per_page =
-                import->u.memory.mem_type.num_bytes_per_page;
-            uint32 init_page_count = import->u.memory.mem_type.init_page_count;
+                memory_type->mem_type.num_bytes_per_page;
+            uint32 init_page_count = memory_type->mem_type.init_page_count;
             uint32 max_page_count = wasm_runtime_get_max_mem(
-                max_memory_pages, import->u.memory.mem_type.init_page_count,
-                import->u.memory.mem_type.max_page_count);
-            uint32 flags = import->u.memory.mem_type.flags;
+                max_memory_pages, memory_type->mem_type.init_page_count,
+                memory_type->mem_type.max_page_count);
+            uint32 flags = memory_type->mem_type.flags;
 
             if (!(memories[mem_index] = memory_instantiate(
                       module, parent, memory,
@@ -590,25 +598,53 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
                 memories_deinstantiate(module_inst, memories, memory_count);
                 return NULL;
             }
-            mem_index++;
         }
+#else
+
+        const WASMExternInstance *extern_inst =
+            wasm_runtime_get_extern_instance(imports, import_count,
+                                             WASM_IMPORT_EXPORT_KIND_MEMORY,
+                                             mem_index);
+        if (!extern_inst) {
+            LOG_ERROR("missing a import memory(%s, %s)",
+                      memory_type->module_name, memory_type->field_name);
+            return NULL;
+        }
+
+        /* just in case */
+#ifndef NDEBUG
+        if (strcmp(memory_type->field_name, extern_inst->field_name)) {
+            LOG_ERROR(
+                "mismatched import memory name: expect \"%s\", got \"%s\"",
+                memory_type->field_name, extern_inst->field_name);
+            return NULL;
+        }
+#endif
+        /*
+         *TODO:
+         * - either memories[x] points to an external AOTMemoryInstance.
+         * - or memories[x] points to an internal AOTMemoryInstance in
+         *   global_table_data
+         *
+         * the first case is simple for maintaining resource management
+         */
+        memories[mem_index] = extern_inst->u.memory;
+        bh_memcpy_s(memory, sizeof(WASMMemoryInstance), extern_inst->u.memory,
+                    sizeof(WASMMemoryInstance));
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
     }
 
     bh_assert(mem_index == module->import_memory_count);
     bh_assert(memory
               == module_inst->global_table_data.memory_instances
                      + module->import_memory_count);
-#else
-    mem_index = module->import_memory_count;
-    memory = module_inst->global_table_data.memory_instances
-             + module->import_memory_count;
-#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
 
     /* instantiate memories from memory section */
     for (i = 0; i < module->memory_count; i++, memory++) {
         uint32 max_page_count = wasm_runtime_get_max_mem(
             max_memory_pages, module->memories[i].init_page_count,
             module->memories[i].max_page_count);
+
         if (!(memories[mem_index] = memory_instantiate(
                   module, parent, memory,
                   parent ? parent->memories[mem_index] : NULL,
@@ -631,6 +667,9 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
 WASMMemoryInstance *
 wasm_create_memory(const WASMModule *module, const WASMMemoryType *type)
 {
+    if (!module || !type)
+        return NULL;
+
     WASMMemoryInstance *memory = NULL;
     char error_buf[64] = { 0 };
 
@@ -651,7 +690,7 @@ wasm_create_memory(const WASMModule *module, const WASMMemoryType *type)
                             NULL, // parent_memory
                             type->num_bytes_per_page, type->init_page_count,
                             type->max_page_count,
-                            0, // no heap_size from host side
+                            0, // no app heap for host
                             type->flags,
                             NULL, // aux_heap_base_global_data
                             error_buf, sizeof(error_buf))) {
@@ -2028,6 +2067,7 @@ 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)
@@ -2666,7 +2706,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
     if ((module_inst->memory_count > 0
          && !(module_inst->memories = memories_instantiate(
                   module, module_inst, parent, heap_size, max_memory_pages,
-                  aux_heap_base_global_data, error_buf, error_buf_size)))
+                  aux_heap_base_global_data, imports, import_count, error_buf,
+                  error_buf_size)))
         || (module_inst->table_count > 0
             && !(module_inst->tables =
                      tables_instantiate(module, module_inst, first_table,
@@ -2711,35 +2752,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         goto fail;
     }
 
-#if WASM_ENABLE_MULTI_MODULE == 0
-    /* imports */
-    /*
-     * const WASMExternInstance *imports should have the same order
-     * with import section content in .wasm.
-     */
-    {
-        uint32 import_memory_index = 0;
-        uint32 import_index = 0;
-        for (; import_index < import_count; import_index++) {
-            /* TODO: remove me if the entire instantiation linking feature is
-             * complete */
-            if (imports == NULL)
-                break;
-
-            const WASMExternInstance *import = imports + import_index;
-            if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
-                if (import_memory_index >= module->import_memory_count) {
-                    LOG_ERROR("provided import memory not match requirement");
-                    goto fail;
-                }
-
-                module_inst->memories[import_memory_index] = import->u.memory;
-                import_memory_index++;
-            }
-        }
-    }
-#endif
-
     if (global_count > 0) {
         /* Initialize the global data */
         global_data = module_inst->global_data;

+ 2 - 1
core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c

@@ -561,7 +561,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
     uint32 aux_stack_size;
     uint64 aux_stack_start = 0;
     int32 ret = -1;
-    int32 spawned_import_count = ((WASMModule *)module)->import_count;
+    int32 spawned_import_count = 0;
     WASMExternInstance *spawned_imports = NULL;
 
     bh_assert(module);
@@ -584,6 +584,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
     /*
      * build a imports list(WASMExternInstance[]) from parent's imports
      */
+    spawned_import_count = wasm_runtime_get_import_count(module);
     spawned_imports =
         wasm_runtime_malloc(sizeof(WASMExternInstance) * spawned_import_count);
     if (spawned_imports == NULL) {

+ 2 - 1
core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c

@@ -80,7 +80,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
     int32 thread_id = -1;
     uint32 stack_size = 8192;
     int32 ret = -1;
-    int32 spawned_import_count = ((WASMModule *)module)->import_count;
+    int32 spawned_import_count = 0;
     WASMExternInstance *spawned_imports = NULL;
 
     bh_assert(module);
@@ -91,6 +91,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
     /*
      * build a imports list(WASMExternInstance[]) from parent's imports
      */
+    spawned_import_count = wasm_runtime_get_import_count(module);
     spawned_imports =
         wasm_runtime_malloc(sizeof(WASMExternInstance) * spawned_import_count);
     if (spawned_imports == NULL) {

+ 5 - 0
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -82,6 +82,7 @@ wasi_ctx_get_curfds(wasi_ctx_t wasi_ctx)
 static inline struct argv_environ_values *
 wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
 {
+    (void)module_inst;
     if (!wasi_ctx)
         return NULL;
     return wasi_ctx->argv_environ;
@@ -2171,6 +2172,8 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
     wasi_errno_t err;
     size_t send_bytes = 0;
 
+    (void)si_flags;
+
     if (!wasi_ctx) {
         return __WASI_EINVAL;
     }
@@ -2241,6 +2244,8 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
     struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx);
 
+    (void)how;
+
     if (!wasi_ctx)
         return __WASI_EINVAL;
 

+ 5 - 2
samples/linking/CMakeLists.txt

@@ -14,7 +14,9 @@ string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
 include(CheckPIESupported)
 
 # AOT and JIT byd default
-set(WAMR_BUILD_AOT 0)
+if(NOT WAMR_BUILD_AOT)
+  set(WAMR_BUILD_AOT 0)
+endif()
 set(WAMR_BUILD_INTERP 1)
 set(WAMR_BUILD_JIT 0)
 # wasm32-wasi
@@ -33,7 +35,7 @@ set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
 include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
 add_library(vmlib SHARED ${WAMR_RUNTIME_LIB_SOURCE})
 target_include_directories(vmlib INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include)
-target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl)
+target_link_libraries(vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl)
 
 ################  samples  ################
 add_subdirectory(raw)
@@ -45,6 +47,7 @@ ExternalProject_Add(wasm
   CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm -B build
                       -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
                       -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN}
+                      -DWAMR_BUILD_AOT=${WAMR_BUILD_AOT}
   BUILD_COMMAND     ${CMAKE_COMMAND} --build build
   INSTALL_COMMAND   ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR}
   EXCLUDE_FROM_ALL  NO

+ 27 - 0
samples/linking/cmake/FindWAMRC.cmake

@@ -0,0 +1,27 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+include(FindPackageHandleStandardArgs)
+
+find_path(WAMRC_HOME
+  wamr-compiler
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/../../..
+  NO_DEFAULT_PATH
+  NO_CMAKE_PATH
+  NO_CMAKE_SYSTEM_PATH
+  NO_CMAKE_FIND_ROOT_PATH
+  REQUIRED
+)
+
+find_file(WAMRC_BIN
+  wamrc
+  HINTS ${WAMRC_HOME}/wamr-compiler/build
+  NO_DEFAULT_PATH
+  NO_CMAKE_PATH
+  NO_CMAKE_SYSTEM_PATH
+  NO_CMAKE_FIND_ROOT_PATH
+  REQUIRED
+)
+
+find_package_handle_standard_args(WAMRC REQUIRED_VARS WAMRC_BIN)
+mark_as_advanced(WAMRC_BIN)

+ 1 - 0
samples/linking/cmake/FindWASISDK.cmake

@@ -11,6 +11,7 @@ find_path(WASISDK_HOME
   REQUIRED
 )
 
+
 string(REGEX MATCH [0-9]+\.[0-9]+\.*[0-9]* WASISDK_VERSION ${WASISDK_HOME})
 
 find_package_handle_standard_args(WASISDK REQUIRED_VARS WASISDK_HOME VERSION_VAR WASISDK_VERSION)

+ 6 - 0
samples/linking/raw/main.c

@@ -21,7 +21,13 @@ main(int argc, char *argv_main[])
     /* wasm module file */
     char *buffer;
     uint32 buf_size;
+#if WASM_ENABLE_AOT != 0
+    printf("Loading AOT file...\n");
+    buffer = bh_read_file_to_buffer("import_memory.aot", &buf_size);
+#else
+    printf("Loading WASM file...\n");
     buffer = bh_read_file_to_buffer("import_memory.wasm", &buf_size);
+#endif
     if (!buffer) {
         printf("Open wasm file failed.\n");
         goto destroy_runtime;

+ 18 - 1
samples/linking/wasm/CMakeLists.txt

@@ -1,10 +1,15 @@
 # Copyright (C) 2019 Intel Corporation. All rights reserved.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-cmake_minimum_required (VERSION 3.14)
+cmake_minimum_required(VERSION 3.14)
 
 project(linking_samples_wasm)
 
+if(WAMR_BUILD_AOT EQUAL 1)
+  list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../cmake)
+  find_package(WAMRC REQUIRED)
+endif()
+
 add_executable(import_memory import_memory.c)
 target_link_options(import_memory
   PRIVATE
@@ -16,3 +21,15 @@ target_link_options(import_memory
 )
 set_target_properties(import_memory PROPERTIES SUFFIX .wasm)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.wasm DESTINATION .)
+
+if(WAMR_BUILD_AOT EQUAL 1)
+  add_custom_target (
+    import_memory_aot
+    ALL
+    DEPENDS ${WAMRC_BIN} import_memory
+    COMMAND ${WAMRC_BIN} -o import_memory.aot import_memory.wasm
+    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+  )
+  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.aot DESTINATION .)
+endif()
+