mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-30 21:02:27 +00:00 
			
		
		
		
	Support muti-module for AOT mode (#2482)
Support muti-module for AOT mode, currently only implement the multi-module's function import feature for AOT, the memory/table/ global import are not implemented yet. And update wamr-test-suites scripts, multi-module sample and some CIs accordingly.
This commit is contained in:
		
							parent
							
								
									fff0e2ad1c
								
							
						
					
					
						commit
						79b27c1934
					
				|  | @ -328,7 +328,12 @@ jobs: | ||||||
|         working-directory: samples/wasm-c-api |         working-directory: samples/wasm-c-api | ||||||
| 
 | 
 | ||||||
|   build_samples_others: |   build_samples_others: | ||||||
|     needs: [build_iwasm] |     needs: | ||||||
|  |       [ | ||||||
|  |         build_iwasm, | ||||||
|  |         build_llvm_libraries_on_ubuntu_2204, | ||||||
|  |         build_wamrc, | ||||||
|  |       ]     | ||||||
|     runs-on: ${{ matrix.os }} |     runs-on: ${{ matrix.os }} | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|  | @ -341,6 +346,9 @@ jobs: | ||||||
|           [ |           [ | ||||||
|             "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", |             "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", | ||||||
|           ] |           ] | ||||||
|  |         include: | ||||||
|  |           - os: ubuntu-22.04 | ||||||
|  |             llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} | ||||||
|     steps: |     steps: | ||||||
|       - name: checkout |       - name: checkout | ||||||
|         uses: actions/checkout@v3 |         uses: actions/checkout@v3 | ||||||
|  | @ -358,7 +366,23 @@ jobs: | ||||||
|           sudo wget ${{ matrix.wabt_release }} |           sudo wget ${{ matrix.wabt_release }} | ||||||
|           sudo tar -xzf wabt-1.0.31-*.tar.gz |           sudo tar -xzf wabt-1.0.31-*.tar.gz | ||||||
|           sudo mv wabt-1.0.31 wabt |           sudo mv wabt-1.0.31 wabt | ||||||
| 
 |       - name: Get LLVM libraries | ||||||
|  |         id: retrieve_llvm_libs | ||||||
|  |         uses: actions/cache@v3 | ||||||
|  |         with: | ||||||
|  |           path: | | ||||||
|  |             ./core/deps/llvm/build/bin | ||||||
|  |             ./core/deps/llvm/build/include | ||||||
|  |             ./core/deps/llvm/build/lib | ||||||
|  |             ./core/deps/llvm/build/libexec | ||||||
|  |             ./core/deps/llvm/build/share | ||||||
|  |           key: ${{ matrix.llvm_cache_key }} | ||||||
|  |       - name: Build wamrc | ||||||
|  |         run: | | ||||||
|  |           mkdir build && cd build | ||||||
|  |           cmake .. | ||||||
|  |           cmake --build . --config Release --parallel 4 | ||||||
|  |         working-directory: wamr-compiler | ||||||
|       - name: Build Sample [basic] |       - name: Build Sample [basic] | ||||||
|         run: | |         run: | | ||||||
|           cd samples/basic |           cd samples/basic | ||||||
|  | @ -385,9 +409,10 @@ jobs: | ||||||
|         run: | |         run: | | ||||||
|           cd samples/multi-module |           cd samples/multi-module | ||||||
|           mkdir build && cd build |           mkdir build && cd build | ||||||
|           cmake .. |           cmake .. -DWAMR_BUILD_AOT=1 | ||||||
|           cmake --build . --config Release --parallel 4 |           cmake --build . --config Release --parallel 4 | ||||||
|           ./multi_module |           ./multi_module mC.wasm | ||||||
|  |           ./multi_module mC.aot | ||||||
| 
 | 
 | ||||||
|       - name: Build Sample [spawn-thread] |       - name: Build Sample [spawn-thread] | ||||||
|         run: | |         run: | | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								.github/workflows/compilation_on_macos.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/compilation_on_macos.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -245,7 +245,7 @@ jobs: | ||||||
|         working-directory: samples/wasm-c-api |         working-directory: samples/wasm-c-api | ||||||
| 
 | 
 | ||||||
|   build_samples_others: |   build_samples_others: | ||||||
|     needs: [build_iwasm] |     needs: [build_iwasm, build_wamrc] | ||||||
|     runs-on: ${{ matrix.os }} |     runs-on: ${{ matrix.os }} | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|  | @ -304,7 +304,7 @@ jobs: | ||||||
|           mkdir build && cd build |           mkdir build && cd build | ||||||
|           cmake .. |           cmake .. | ||||||
|           cmake --build . --config Release --parallel 4 |           cmake --build . --config Release --parallel 4 | ||||||
|           ./multi_module |           ./multi_module mC.wasm | ||||||
| 
 | 
 | ||||||
|       - name: Build Sample [spawn-thread] |       - name: Build Sample [spawn-thread] | ||||||
|         run: | |         run: | | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								.github/workflows/nightly_run.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/nightly_run.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -380,7 +380,12 @@ jobs: | ||||||
|         working-directory: samples/wasm-c-api |         working-directory: samples/wasm-c-api | ||||||
| 
 | 
 | ||||||
|   build_samples_others: |   build_samples_others: | ||||||
|     needs: [build_iwasm] |     needs: | ||||||
|  |       [ | ||||||
|  |         build_iwasm, | ||||||
|  |         build_llvm_libraries_on_ubuntu_2004, | ||||||
|  |         build_wamrc, | ||||||
|  |       ] | ||||||
|     runs-on: ${{ matrix.os }} |     runs-on: ${{ matrix.os }} | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|  | @ -393,6 +398,9 @@ jobs: | ||||||
|           [ |           [ | ||||||
|             "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", |             "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", | ||||||
|           ] |           ] | ||||||
|  |         include: | ||||||
|  |           - os: ubuntu-20.04 | ||||||
|  |             llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} | ||||||
|     steps: |     steps: | ||||||
|       - name: checkout |       - name: checkout | ||||||
|         uses: actions/checkout@v3 |         uses: actions/checkout@v3 | ||||||
|  | @ -409,6 +417,26 @@ jobs: | ||||||
|           sudo wget ${{ matrix.wabt_release }} |           sudo wget ${{ matrix.wabt_release }} | ||||||
|           sudo tar -xzf wabt-1.0.31-*.tar.gz |           sudo tar -xzf wabt-1.0.31-*.tar.gz | ||||||
|           sudo mv wabt-1.0.31 wabt |           sudo mv wabt-1.0.31 wabt | ||||||
|  | 
 | ||||||
|  |       - name: Get LLVM libraries | ||||||
|  |         id: retrieve_llvm_libs | ||||||
|  |         uses: actions/cache@v3 | ||||||
|  |         with: | ||||||
|  |           path: | | ||||||
|  |             ./core/deps/llvm/build/bin | ||||||
|  |             ./core/deps/llvm/build/include | ||||||
|  |             ./core/deps/llvm/build/lib | ||||||
|  |             ./core/deps/llvm/build/libexec | ||||||
|  |             ./core/deps/llvm/build/share | ||||||
|  |           key: ${{ matrix.llvm_cache_key }} | ||||||
|  | 
 | ||||||
|  |       - name: Build wamrc | ||||||
|  |         run: | | ||||||
|  |           mkdir build && cd build | ||||||
|  |           cmake -D WAMR_BUILD_SANITIZER="${{matrix.sanitizer}}" .. | ||||||
|  |           cmake --build . --config Release --parallel 4 | ||||||
|  |         working-directory: wamr-compiler | ||||||
|  | 
 | ||||||
|       - name: Build Sample [basic] |       - name: Build Sample [basic] | ||||||
|         run: | |         run: | | ||||||
|           cd samples/basic |           cd samples/basic | ||||||
|  | @ -432,9 +460,10 @@ jobs: | ||||||
|         run: | |         run: | | ||||||
|           cd samples/multi-module |           cd samples/multi-module | ||||||
|           mkdir build && cd build |           mkdir build && cd build | ||||||
|           cmake .. |           cmake .. -DWAMR_BUILD_AOT=1 | ||||||
|           cmake --build . --config Release --parallel 4 |           cmake --build . --config Release --parallel 4 | ||||||
|           ./multi_module |           ./multi_module mC.wasm | ||||||
|  |           ./multi_module mC.aot | ||||||
|       - name: Build Sample [spawn-thread] |       - name: Build Sample [spawn-thread] | ||||||
|         run: | |         run: | | ||||||
|           cd samples/spawn-thread |           cd samples/spawn-thread | ||||||
|  |  | ||||||
|  | @ -558,6 +558,56 @@ str2uint32(const char *buf, uint32 *p_res); | ||||||
| static bool | static bool | ||||||
| str2uint64(const char *buf, uint64 *p_res); | str2uint64(const char *buf, uint64 *p_res); | ||||||
| 
 | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  | static void * | ||||||
|  | aot_loader_resolve_function(const char *module_name, const char *function_name, | ||||||
|  |                             const AOTFuncType *expected_function_type, | ||||||
|  |                             char *error_buf, uint32 error_buf_size) | ||||||
|  | { | ||||||
|  |     WASMModuleCommon *module_reg; | ||||||
|  |     void *function = NULL; | ||||||
|  |     AOTExport *export = NULL; | ||||||
|  |     AOTModule *module = NULL; | ||||||
|  |     AOTFuncType *target_function_type = NULL; | ||||||
|  | 
 | ||||||
|  |     module_reg = wasm_runtime_find_module_registered(module_name); | ||||||
|  |     if (!module_reg || module_reg->module_type != Wasm_Module_AoT) { | ||||||
|  |         LOG_DEBUG("can not find a module named %s for function %s", module_name, | ||||||
|  |                   function_name); | ||||||
|  |         set_error_buf(error_buf, error_buf_size, "unknown import"); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     module = (AOTModule *)module_reg; | ||||||
|  |     export = loader_find_export(module_reg, module_name, function_name, | ||||||
|  |                                 EXPORT_KIND_FUNC, error_buf, error_buf_size); | ||||||
|  |     if (!export) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* resolve function type and function */ | ||||||
|  |     if (export->index < module->import_func_count) { | ||||||
|  |         target_function_type = module->import_funcs[export->index].func_type; | ||||||
|  |         function = module->import_funcs[export->index].func_ptr_linked; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         target_function_type = | ||||||
|  |             module->func_types[module->func_type_indexes | ||||||
|  |                                    [export->index - module->import_func_count]]; | ||||||
|  |         function = | ||||||
|  |             (module->func_ptrs[export->index - module->import_func_count]); | ||||||
|  |     } | ||||||
|  |     /* check function type */ | ||||||
|  |     if (!wasm_type_equal(expected_function_type, target_function_type)) { | ||||||
|  |         LOG_DEBUG("%s.%s failed the type check", module_name, function_name); | ||||||
|  |         set_error_buf(error_buf, error_buf_size, "incompatible import type"); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     return function; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* end of WASM_ENABLE_MULTI_MODULE */ | ||||||
|  | 
 | ||||||
| static bool | static bool | ||||||
| load_native_symbol_section(const uint8 *buf, const uint8 *buf_end, | load_native_symbol_section(const uint8 *buf, const uint8 *buf_end, | ||||||
|                            AOTModule *module, bool is_load_from_file_buf, |                            AOTModule *module, bool is_load_from_file_buf, | ||||||
|  | @ -1357,11 +1407,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, | ||||||
|                   bool is_load_from_file_buf, char *error_buf, |                   bool is_load_from_file_buf, char *error_buf, | ||||||
|                   uint32 error_buf_size) |                   uint32 error_buf_size) | ||||||
| { | { | ||||||
|     const char *module_name, *field_name; |     char *module_name, *field_name; | ||||||
|     const uint8 *buf = *p_buf; |     const uint8 *buf = *p_buf; | ||||||
|     AOTImportFunc *import_funcs; |     AOTImportFunc *import_funcs; | ||||||
|     uint64 size; |     uint64 size; | ||||||
|     uint32 i; |     uint32 i; | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     AOTModule *sub_module = NULL; | ||||||
|  |     AOTFunc *linked_func = NULL; | ||||||
|  |     WASMType *declare_func_type = NULL; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     /* Allocate memory */ |     /* Allocate memory */ | ||||||
|     size = sizeof(AOTImportFunc) * (uint64)module->import_func_count; |     size = sizeof(AOTImportFunc) * (uint64)module->import_func_count; | ||||||
|  | @ -1377,17 +1432,46 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, | ||||||
|             set_error_buf(error_buf, error_buf_size, "unknown type"); |             set_error_buf(error_buf, error_buf_size, "unknown type"); | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |         declare_func_type = module->func_types[import_funcs[i].func_type_index]; | ||||||
|  |         read_string(buf, buf_end, module_name); | ||||||
|  |         read_string(buf, buf_end, field_name); | ||||||
|  | 
 | ||||||
|  |         import_funcs[i].module_name = module_name; | ||||||
|  |         import_funcs[i].func_name = field_name; | ||||||
|  |         linked_func = wasm_native_resolve_symbol( | ||||||
|  |             module_name, field_name, declare_func_type, | ||||||
|  |             &import_funcs[i].signature, &import_funcs[i].attachment, | ||||||
|  |             &import_funcs[i].call_conv_raw); | ||||||
|  |         if (!linked_func) { | ||||||
|  |             if (!wasm_runtime_is_built_in_module(module_name)) { | ||||||
|  |                 sub_module = (AOTModule *)wasm_runtime_load_depended_module( | ||||||
|  |                     (WASMModuleCommon *)module, module_name, error_buf, | ||||||
|  |                     error_buf_size); | ||||||
|  |                 if (!sub_module) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             linked_func = aot_loader_resolve_function( | ||||||
|  |                 module_name, field_name, declare_func_type, error_buf, | ||||||
|  |                 error_buf_size); | ||||||
|  |         } | ||||||
|  |         import_funcs[i].func_ptr_linked = linked_func; | ||||||
|  |         import_funcs[i].func_type = declare_func_type; | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|         import_funcs[i].func_type = |         import_funcs[i].func_type = | ||||||
|             module->func_types[import_funcs[i].func_type_index]; |             module->func_types[import_funcs[i].func_type_index]; | ||||||
|         read_string(buf, buf_end, import_funcs[i].module_name); |         read_string(buf, buf_end, import_funcs[i].module_name); | ||||||
|         read_string(buf, buf_end, import_funcs[i].func_name); |         read_string(buf, buf_end, import_funcs[i].func_name); | ||||||
| 
 |  | ||||||
|         module_name = import_funcs[i].module_name; |         module_name = import_funcs[i].module_name; | ||||||
|         field_name = import_funcs[i].func_name; |         field_name = import_funcs[i].func_name; | ||||||
|         import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol( |         import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol( | ||||||
|             module_name, field_name, import_funcs[i].func_type, |             module_name, field_name, import_funcs[i].func_type, | ||||||
|             &import_funcs[i].signature, &import_funcs[i].attachment, |             &import_funcs[i].signature, &import_funcs[i].attachment, | ||||||
|             &import_funcs[i].call_conv_raw); |             &import_funcs[i].call_conv_raw); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #if WASM_ENABLE_LIBC_WASI != 0 | #if WASM_ENABLE_LIBC_WASI != 0 | ||||||
|         if (!strcmp(import_funcs[i].module_name, "wasi_unstable") |         if (!strcmp(import_funcs[i].module_name, "wasi_unstable") | ||||||
|  | @ -2872,12 +2956,17 @@ create_module(char *error_buf, uint32 error_buf_size) | ||||||
|     AOTModule *module = |     AOTModule *module = | ||||||
|         loader_malloc(sizeof(AOTModule), error_buf, error_buf_size); |         loader_malloc(sizeof(AOTModule), error_buf, error_buf_size); | ||||||
| 
 | 
 | ||||||
|  |     bh_list_status ret; | ||||||
|     if (!module) { |     if (!module) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     module->module_type = Wasm_Module_AoT; |     module->module_type = Wasm_Module_AoT; | ||||||
| 
 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     module->import_module_list = &module->import_module_list_head; | ||||||
|  |     ret = bh_list_init(module->import_module_list); | ||||||
|  |     bh_assert(ret == BH_LIST_SUCCESS); | ||||||
|  | #endif | ||||||
|  |     (void)ret; | ||||||
|     return module; |     return module; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -3201,6 +3290,19 @@ aot_unload(AOTModule *module) | ||||||
| 
 | 
 | ||||||
|     if (module->const_str_set) |     if (module->const_str_set) | ||||||
|         bh_hash_map_destroy(module->const_str_set); |         bh_hash_map_destroy(module->const_str_set); | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     /* just release the sub module list */ | ||||||
|  |     if (module->import_module_list) { | ||||||
|  |         WASMRegisteredModule *node = | ||||||
|  |             bh_list_first_elem(module->import_module_list); | ||||||
|  |         while (node) { | ||||||
|  |             WASMRegisteredModule *next = bh_list_elem_next(node); | ||||||
|  |             bh_list_remove(module->import_module_list, node); | ||||||
|  |             wasm_runtime_free(node); | ||||||
|  |             node = next; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     if (module->code && !module->is_indirect_mode) { |     if (module->code && !module->is_indirect_mode) { | ||||||
|         /* The layout is: literal size + literal + code (with plt table) */ |         /* The layout is: literal size + literal + code (with plt table) */ | ||||||
|  |  | ||||||
|  | @ -1091,6 +1091,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, | ||||||
|     uint8 *p; |     uint8 *p; | ||||||
|     uint32 i, extra_info_offset; |     uint32 i, extra_info_offset; | ||||||
|     const bool is_sub_inst = parent != NULL; |     const bool is_sub_inst = parent != NULL; | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     bool ret = false; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     /* Check heap size */ |     /* Check heap size */ | ||||||
|     heap_size = align_uint(heap_size, 8); |     heap_size = align_uint(heap_size, 8); | ||||||
|  | @ -1134,6 +1137,18 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, | ||||||
|     module_inst->e = |     module_inst->e = | ||||||
|         (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); |         (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); | ||||||
| 
 | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list = | ||||||
|  |         &((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list_head; | ||||||
|  |     ret = wasm_runtime_sub_module_instantiate( | ||||||
|  |         (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, | ||||||
|  |         stack_size, heap_size, error_buf, error_buf_size); | ||||||
|  |     if (!ret) { | ||||||
|  |         LOG_DEBUG("build a sub module list failed"); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     /* Initialize global info */ |     /* Initialize global info */ | ||||||
|     p = (uint8 *)module_inst + module_inst_struct_size |     p = (uint8 *)module_inst + module_inst_struct_size | ||||||
|         + module_inst_mem_inst_size; |         + module_inst_mem_inst_size; | ||||||
|  | @ -1256,6 +1271,11 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     wasm_runtime_sub_module_deinstantiate( | ||||||
|  |         (WASMModuleInstanceCommon *)module_inst); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     if (module_inst->tables) |     if (module_inst->tables) | ||||||
|         wasm_runtime_free(module_inst->tables); |         wasm_runtime_free(module_inst->tables); | ||||||
| 
 | 
 | ||||||
|  | @ -1411,10 +1431,43 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, | ||||||
|                   unsigned argc, uint32 argv[]) |                   unsigned argc, uint32 argv[]) | ||||||
| { | { | ||||||
|     AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; |     AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; | ||||||
|     AOTFuncType *func_type = function->u.func.func_type; |     AOTFuncType *func_type = function->is_import_func | ||||||
|  |                                  ? function->u.func_import->func_type | ||||||
|  |                                  : function->u.func.func_type; | ||||||
|     uint32 result_count = func_type->result_count; |     uint32 result_count = func_type->result_count; | ||||||
|     uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; |     uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; | ||||||
|     bool ret; |     bool ret; | ||||||
|  |     void *func_ptr = function->is_import_func | ||||||
|  |                          ? function->u.func_import->func_ptr_linked | ||||||
|  |                          : function->u.func.func_ptr; | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     bh_list *sub_module_list_node = NULL; | ||||||
|  |     const char *sub_inst_name = NULL; | ||||||
|  |     const char *func_name = function->u.func_import->module_name; | ||||||
|  |     if (function->is_import_func) { | ||||||
|  |         sub_module_list_node = | ||||||
|  |             ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list; | ||||||
|  |         sub_module_list_node = bh_list_first_elem(sub_module_list_node); | ||||||
|  |         while (sub_module_list_node) { | ||||||
|  |             sub_inst_name = | ||||||
|  |                 ((AOTSubModInstNode *)sub_module_list_node)->module_name; | ||||||
|  |             if (strcmp(sub_inst_name, func_name) == 0) { | ||||||
|  |                 exec_env = wasm_runtime_get_exec_env_singleton( | ||||||
|  |                     (WASMModuleInstanceCommon *)((AOTSubModInstNode *) | ||||||
|  |                                                      sub_module_list_node) | ||||||
|  |                         ->module_inst); | ||||||
|  |                 module_inst = (AOTModuleInstance *)exec_env->module_inst; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             sub_module_list_node = bh_list_elem_next(sub_module_list_node); | ||||||
|  |         } | ||||||
|  |         if (exec_env == NULL) { | ||||||
|  |             wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst, | ||||||
|  |                                        "create singleton exec_env failed"); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     if (argc < func_type->param_cell_num) { |     if (argc < func_type->param_cell_num) { | ||||||
|         char buf[108]; |         char buf[108]; | ||||||
|  | @ -1436,8 +1489,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     /* func pointer was looked up previously */ |     /* func pointer was looked up previously */ | ||||||
|     bh_assert(function->u.func.func_ptr != NULL); |     bh_assert(func_ptr != NULL); | ||||||
| 
 |  | ||||||
|     /* set thread handle and stack boundary */ |     /* set thread handle and stack boundary */ | ||||||
|     wasm_exec_env_set_thread_info(exec_env); |     wasm_exec_env_set_thread_info(exec_env); | ||||||
| 
 | 
 | ||||||
|  | @ -1546,8 +1598,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|         ret = invoke_native_internal(exec_env, function->u.func.func_ptr, |         ret = invoke_native_internal(exec_env, func_ptr, func_type, NULL, NULL, | ||||||
|                                      func_type, NULL, NULL, argv, argc, argv); |                                      argv, argc, argv); | ||||||
| 
 | 
 | ||||||
| #if WASM_ENABLE_DUMP_CALL_STACK != 0 | #if WASM_ENABLE_DUMP_CALL_STACK != 0 | ||||||
|         if (aot_copy_exception(module_inst, NULL)) { |         if (aot_copy_exception(module_inst, NULL)) { | ||||||
|  | @ -1939,7 +1991,10 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, | ||||||
|     void *attachment; |     void *attachment; | ||||||
|     char buf[96]; |     char buf[96]; | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
| 
 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     bh_list *sub_module_list_node = NULL; | ||||||
|  |     const char *sub_inst_name = NULL; | ||||||
|  | #endif | ||||||
|     bh_assert(func_idx < aot_module->import_func_count); |     bh_assert(func_idx < aot_module->import_func_count); | ||||||
| 
 | 
 | ||||||
|     import_func = aot_module->import_funcs + func_idx; |     import_func = aot_module->import_funcs + func_idx; | ||||||
|  | @ -1963,6 +2018,28 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, | ||||||
|     } |     } | ||||||
|     else if (!import_func->call_conv_raw) { |     else if (!import_func->call_conv_raw) { | ||||||
|         signature = import_func->signature; |         signature = import_func->signature; | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |         sub_module_list_node = | ||||||
|  |             ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list; | ||||||
|  |         sub_module_list_node = bh_list_first_elem(sub_module_list_node); | ||||||
|  |         while (sub_module_list_node) { | ||||||
|  |             sub_inst_name = | ||||||
|  |                 ((AOTSubModInstNode *)sub_module_list_node)->module_name; | ||||||
|  |             if (strcmp(sub_inst_name, import_func->module_name) == 0) { | ||||||
|  |                 exec_env = wasm_runtime_get_exec_env_singleton( | ||||||
|  |                     (WASMModuleInstanceCommon *)((AOTSubModInstNode *) | ||||||
|  |                                                      sub_module_list_node) | ||||||
|  |                         ->module_inst); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             sub_module_list_node = bh_list_elem_next(sub_module_list_node); | ||||||
|  |         } | ||||||
|  |         if (exec_env == NULL) { | ||||||
|  |             wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst, | ||||||
|  |                                        "create singleton exec_env failed"); | ||||||
|  |             goto fail; | ||||||
|  |         } | ||||||
|  | #endif | ||||||
|         ret = |         ret = | ||||||
|             wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, |             wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, | ||||||
|                                        attachment, argv, argc, argv); |                                        attachment, argv, argc, argv); | ||||||
|  |  | ||||||
|  | @ -90,6 +90,10 @@ typedef struct AOTFunctionInstance { | ||||||
| typedef struct AOTModuleInstanceExtra { | typedef struct AOTModuleInstanceExtra { | ||||||
|     DefPointer(const uint32 *, stack_sizes); |     DefPointer(const uint32 *, stack_sizes); | ||||||
|     WASMModuleInstanceExtraCommon common; |     WASMModuleInstanceExtraCommon common; | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     bh_list sub_module_inst_list_head; | ||||||
|  |     bh_list *sub_module_inst_list; | ||||||
|  | #endif | ||||||
| } AOTModuleInstanceExtra; | } AOTModuleInstanceExtra; | ||||||
| 
 | 
 | ||||||
| #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) | #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) | ||||||
|  | @ -229,6 +233,12 @@ typedef struct AOTModule { | ||||||
|     WASIArguments wasi_args; |     WASIArguments wasi_args; | ||||||
|     bool import_wasi_api; |     bool import_wasi_api; | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |     /* TODO: add mutex for mutli-thread? */ | ||||||
|  |     bh_list import_module_list_head; | ||||||
|  |     bh_list *import_module_list; | ||||||
|  | #endif | ||||||
| #if WASM_ENABLE_DEBUG_AOT != 0 | #if WASM_ENABLE_DEBUG_AOT != 0 | ||||||
|     void *elf_hdr; |     void *elf_hdr; | ||||||
|     uint32 elf_size; |     uint32 elf_size; | ||||||
|  | @ -247,6 +257,10 @@ typedef struct AOTModule { | ||||||
| #define AOTTableInstance WASMTableInstance | #define AOTTableInstance WASMTableInstance | ||||||
| #define AOTModuleInstance WASMModuleInstance | #define AOTModuleInstance WASMModuleInstance | ||||||
| 
 | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  | #define AOTSubModInstNode WASMSubModInstNode | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /* Target info, read from ELF header of object file */ | /* Target info, read from ELF header of object file */ | ||||||
| typedef struct AOTTargetInfo { | typedef struct AOTTargetInfo { | ||||||
|     /* Binary type, elf32l/elf32b/elf64l/elf64b */ |     /* Binary type, elf32l/elf32b/elf64l/elf64b */ | ||||||
|  |  | ||||||
|  | @ -125,6 +125,36 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, | ||||||
|     return mem; |     return mem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  | /*
 | ||||||
|  |     TODO: | ||||||
|  |     Let loader_malloc be a general API both for AOT and WASM. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define loader_malloc(size, error_buf, error_buf_size) \ | ||||||
|  |     runtime_malloc(size, NULL, error_buf, error_buf_size) | ||||||
|  | static void | ||||||
|  | set_error_buf_v(const WASMModuleCommon *module, char *error_buf, | ||||||
|  |                 uint32 error_buf_size, const char *format, ...) | ||||||
|  | { | ||||||
|  |     va_list args; | ||||||
|  |     char buf[128]; | ||||||
|  |     if (error_buf != NULL) { | ||||||
|  |         va_start(args, format); | ||||||
|  |         vsnprintf(buf, sizeof(buf), format, args); | ||||||
|  |         va_end(args); | ||||||
|  |         if (module->module_type == Wasm_Module_AoT) { | ||||||
|  |             snprintf(error_buf, error_buf_size, "AOT module load failed: %s", | ||||||
|  |                      buf); | ||||||
|  |         } | ||||||
|  |         else if (module->module_type == Wasm_Module_Bytecode) { | ||||||
|  |             snprintf(error_buf, error_buf_size, "WASM module load failed: %s", | ||||||
|  |                      buf); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #if WASM_ENABLE_FAST_JIT != 0 | #if WASM_ENABLE_FAST_JIT != 0 | ||||||
| static JitCompOptions jit_options = { 0 }; | static JitCompOptions jit_options = { 0 }; | ||||||
| #endif | #endif | ||||||
|  | @ -1198,20 +1228,20 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, | ||||||
|     if (get_package_type(buf, size) == Wasm_Module_Bytecode) { |     if (get_package_type(buf, size) == Wasm_Module_Bytecode) { | ||||||
| #if WASM_ENABLE_INTERP != 0 | #if WASM_ENABLE_INTERP != 0 | ||||||
|         module_common = |         module_common = | ||||||
|             (WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size); |             (WASMModuleCommon *)wasm_load(buf, size, | ||||||
|         return register_module_with_null_name(module_common, error_buf, | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|                                               error_buf_size); |                                           true, | ||||||
|  | #endif | ||||||
|  |                                           error_buf, error_buf_size); | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|     else if (get_package_type(buf, size) == Wasm_Module_AoT) { |     else if (get_package_type(buf, size) == Wasm_Module_AoT) { | ||||||
| #if WASM_ENABLE_AOT != 0 | #if WASM_ENABLE_AOT != 0 | ||||||
|         module_common = (WASMModuleCommon *)aot_load_from_aot_file( |         module_common = (WASMModuleCommon *)aot_load_from_aot_file( | ||||||
|             buf, size, error_buf, error_buf_size); |             buf, size, error_buf, error_buf_size); | ||||||
|         return register_module_with_null_name(module_common, error_buf, |  | ||||||
|                                               error_buf_size); |  | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
| 
 |     else { | ||||||
|         if (size < 4) |         if (size < 4) | ||||||
|             set_error_buf(error_buf, error_buf_size, |             set_error_buf(error_buf, error_buf_size, | ||||||
|                           "WASM module load failed: unexpected end"); |                           "WASM module load failed: unexpected end"); | ||||||
|  | @ -1220,6 +1250,13 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, | ||||||
|                           "WASM module load failed: magic header not detected"); |                           "WASM module load failed: magic header not detected"); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  |     if (!module_common) { | ||||||
|  |         LOG_DEBUG("WASM module load failed"); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     return register_module_with_null_name(module_common, error_buf, | ||||||
|  |                                           error_buf_size); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| WASMModuleCommon * | WASMModuleCommon * | ||||||
| wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, | wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, | ||||||
|  | @ -1231,6 +1268,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, | ||||||
| #if WASM_ENABLE_INTERP != 0 | #if WASM_ENABLE_INTERP != 0 | ||||||
|         module_common = (WASMModuleCommon *)wasm_load_from_sections( |         module_common = (WASMModuleCommon *)wasm_load_from_sections( | ||||||
|             section_list, error_buf, error_buf_size); |             section_list, error_buf, error_buf_size); | ||||||
|  |         if (!module_common) { | ||||||
|  |             LOG_DEBUG("WASM module load failed from sections"); | ||||||
|  |             return NULL; | ||||||
|  |         } | ||||||
|         return register_module_with_null_name(module_common, error_buf, |         return register_module_with_null_name(module_common, error_buf, | ||||||
|                                               error_buf_size); |                                               error_buf_size); | ||||||
| #endif | #endif | ||||||
|  | @ -1239,6 +1280,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, | ||||||
| #if WASM_ENABLE_AOT != 0 | #if WASM_ENABLE_AOT != 0 | ||||||
|         module_common = (WASMModuleCommon *)aot_load_from_sections( |         module_common = (WASMModuleCommon *)aot_load_from_sections( | ||||||
|             section_list, error_buf, error_buf_size); |             section_list, error_buf, error_buf_size); | ||||||
|  |         if (!module_common) { | ||||||
|  |             LOG_DEBUG("WASM module load failed from sections"); | ||||||
|  |             return NULL; | ||||||
|  |         } | ||||||
|         return register_module_with_null_name(module_common, error_buf, |         return register_module_with_null_name(module_common, error_buf, | ||||||
|                                               error_buf_size); |                                               error_buf_size); | ||||||
| #endif | #endif | ||||||
|  | @ -5663,6 +5708,314 @@ wasm_runtime_is_import_global_linked(const char *module_name, | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  | WASMExport * | ||||||
|  | loader_find_export(const WASMModuleCommon *module, const char *module_name, | ||||||
|  |                    const char *field_name, uint8 export_kind, char *error_buf, | ||||||
|  |                    uint32 error_buf_size) | ||||||
|  | { | ||||||
|  |     WASMExport *exports = NULL, *result = NULL, *export; | ||||||
|  |     uint32 export_count = 0, i; | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (module->module_type == Wasm_Module_AoT) { | ||||||
|  |         AOTModule *aot_module = (AOTModule *)module; | ||||||
|  |         exports = (WASMExport *)aot_module->exports; | ||||||
|  |         export_count = aot_module->export_count; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (module->module_type == Wasm_Module_Bytecode) { | ||||||
|  |         WASMModule *wasm_module = (WASMModule *)module; | ||||||
|  |         exports = wasm_module->exports; | ||||||
|  |         export_count = wasm_module->export_count; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     for (i = 0, export = exports; i < export_count; ++i, ++export) { | ||||||
|  |         if (export->kind == export_kind && !strcmp(field_name, export->name)) { | ||||||
|  |             result = export; | ||||||
|  |             goto exit; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (i == export_count) { | ||||||
|  |         LOG_DEBUG("can not find an export %d named %s in the module %s", | ||||||
|  |                   export_kind, field_name, module_name); | ||||||
|  |         set_error_buf(error_buf, error_buf_size, | ||||||
|  |                       "unknown import or incompatible import type"); | ||||||
|  |     } | ||||||
|  | exit: | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  | WASMModuleCommon * | ||||||
|  | wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module, | ||||||
|  |                                const char *sub_module_name) | ||||||
|  | { | ||||||
|  |     WASMRegisteredModule *node = NULL; | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (parent_module->module_type == Wasm_Module_AoT) { | ||||||
|  |         node = bh_list_first_elem( | ||||||
|  |             ((AOTModule *)parent_module)->import_module_list); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (parent_module->module_type == Wasm_Module_Bytecode) { | ||||||
|  |         node = bh_list_first_elem( | ||||||
|  |             ((WASMModule *)parent_module)->import_module_list); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     while (node && strcmp(sub_module_name, node->module_name)) { | ||||||
|  |         node = bh_list_elem_next(node); | ||||||
|  |     } | ||||||
|  |     return node ? node->module : NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module, | ||||||
|  |                                  const char *sub_module_name, | ||||||
|  |                                  WASMModuleCommon *sub_module) | ||||||
|  | { | ||||||
|  |     /* register sub_module into its parent sub module list */ | ||||||
|  |     WASMRegisteredModule *node = NULL; | ||||||
|  |     bh_list_status ret; | ||||||
|  | 
 | ||||||
|  |     if (wasm_runtime_search_sub_module(parent_module, sub_module_name)) { | ||||||
|  |         LOG_DEBUG("%s has been registered in its parent", sub_module_name); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0); | ||||||
|  |     if (!node) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     node->module_name = sub_module_name; | ||||||
|  |     node->module = sub_module; | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (parent_module->module_type == Wasm_Module_AoT) { | ||||||
|  |         ret = bh_list_insert(((AOTModule *)parent_module)->import_module_list, | ||||||
|  |                              node); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (parent_module->module_type == Wasm_Module_Bytecode) { | ||||||
|  |         ret = bh_list_insert(((WASMModule *)parent_module)->import_module_list, | ||||||
|  |                              node); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     bh_assert(BH_LIST_SUCCESS == ret); | ||||||
|  |     (void)ret; | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | WASMModuleCommon * | ||||||
|  | wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module, | ||||||
|  |                                   const char *sub_module_name, char *error_buf, | ||||||
|  |                                   uint32 error_buf_size) | ||||||
|  | { | ||||||
|  |     WASMModuleCommon *sub_module = NULL; | ||||||
|  |     bool ret = false; | ||||||
|  |     uint8 *buffer = NULL; | ||||||
|  |     uint32 buffer_size = 0; | ||||||
|  | 
 | ||||||
|  |     /* check the registered module list of the parent */ | ||||||
|  |     sub_module = wasm_runtime_search_sub_module(parent_module, sub_module_name); | ||||||
|  |     if (sub_module) { | ||||||
|  |         LOG_DEBUG("%s has been loaded before", sub_module_name); | ||||||
|  |         return sub_module; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* check the global registered module list */ | ||||||
|  |     sub_module = wasm_runtime_find_module_registered(sub_module_name); | ||||||
|  |     if (sub_module) { | ||||||
|  |         LOG_DEBUG("%s has been loaded", sub_module_name); | ||||||
|  |         goto wasm_runtime_register_sub_module; | ||||||
|  |     } | ||||||
|  |     LOG_VERBOSE("loading %s", sub_module_name); | ||||||
|  |     if (!reader) { | ||||||
|  |         set_error_buf_v(parent_module, error_buf, error_buf_size, | ||||||
|  |                         "no sub module reader to load %s", sub_module_name); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     /* start to maintain a loading module list */ | ||||||
|  |     ret = wasm_runtime_is_loading_module(sub_module_name); | ||||||
|  |     if (ret) { | ||||||
|  |         set_error_buf_v(parent_module, error_buf, error_buf_size, | ||||||
|  |                         "found circular dependency on %s", sub_module_name); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     ret = wasm_runtime_add_loading_module(sub_module_name, error_buf, | ||||||
|  |                                           error_buf_size); | ||||||
|  |     if (!ret) { | ||||||
|  |         LOG_DEBUG("can not add %s into loading module list\n", sub_module_name); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ret = reader(parent_module->module_type, sub_module_name, &buffer, | ||||||
|  |                  &buffer_size); | ||||||
|  |     if (!ret) { | ||||||
|  |         LOG_DEBUG("read the file of %s failed", sub_module_name); | ||||||
|  |         set_error_buf_v(parent_module, error_buf, error_buf_size, | ||||||
|  |                         "unknown import", sub_module_name); | ||||||
|  |         goto delete_loading_module; | ||||||
|  |     } | ||||||
|  |     if (get_package_type(buffer, buffer_size) != parent_module->module_type) { | ||||||
|  |         LOG_DEBUG("moudle %s type error", sub_module_name); | ||||||
|  |         goto delete_loading_module; | ||||||
|  |     } | ||||||
|  |     if (get_package_type(buffer, buffer_size) == Wasm_Module_Bytecode) { | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |         sub_module = (WASMModuleCommon *)wasm_load(buffer, buffer_size, false, | ||||||
|  |                                                    error_buf, error_buf_size); | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  |     else if (get_package_type(buffer, buffer_size) == Wasm_Module_AoT) { | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |         sub_module = (WASMModuleCommon *)aot_load_from_aot_file( | ||||||
|  |             buffer, buffer_size, error_buf, error_buf_size); | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  |     if (!sub_module) { | ||||||
|  |         LOG_DEBUG("error: can not load the sub_module %s", sub_module_name); | ||||||
|  |         /* others will be destroyed in runtime_destroy() */ | ||||||
|  |         goto destroy_file_buffer; | ||||||
|  |     } | ||||||
|  |     wasm_runtime_delete_loading_module(sub_module_name); | ||||||
|  |     /* register on a global list */ | ||||||
|  |     ret = wasm_runtime_register_module_internal( | ||||||
|  |         sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size, | ||||||
|  |         error_buf, error_buf_size); | ||||||
|  |     if (!ret) { | ||||||
|  |         LOG_DEBUG("error: can not register module %s globally\n", | ||||||
|  |                   sub_module_name); | ||||||
|  |         /* others will be unloaded in runtime_destroy() */ | ||||||
|  |         goto unload_module; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* register into its parent list */ | ||||||
|  | wasm_runtime_register_sub_module: | ||||||
|  |     ret = wasm_runtime_register_sub_module(parent_module, sub_module_name, | ||||||
|  |                                            sub_module); | ||||||
|  |     if (!ret) { | ||||||
|  |         set_error_buf_v(parent_module, error_buf, error_buf_size, | ||||||
|  |                         "failed to register sub module %s", sub_module_name); | ||||||
|  |         /* since it is in the global module list, no need to
 | ||||||
|  |          * unload the module. the runtime_destroy() will do it | ||||||
|  |          */ | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return sub_module; | ||||||
|  | 
 | ||||||
|  | unload_module: | ||||||
|  |     wasm_runtime_unload(sub_module); | ||||||
|  | 
 | ||||||
|  | destroy_file_buffer: | ||||||
|  |     if (destroyer) { | ||||||
|  |         destroyer(buffer, buffer_size); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         LOG_WARNING("need to release the reading buffer of %s manually", | ||||||
|  |                     sub_module_name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | delete_loading_module: | ||||||
|  |     wasm_runtime_delete_loading_module(sub_module_name); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, | ||||||
|  |                                     WASMModuleInstanceCommon *module_inst, | ||||||
|  |                                     uint32 stack_size, uint32 heap_size, | ||||||
|  |                                     char *error_buf, uint32 error_buf_size) | ||||||
|  | { | ||||||
|  |     bh_list *sub_module_inst_list = NULL; | ||||||
|  |     WASMRegisteredModule *sub_module_list_node = NULL; | ||||||
|  | 
 | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (module->module_type == Wasm_Module_AoT) { | ||||||
|  |         sub_module_inst_list = | ||||||
|  |             ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) | ||||||
|  |                 ->sub_module_inst_list; | ||||||
|  |         sub_module_list_node = | ||||||
|  |             bh_list_first_elem(((AOTModule *)module)->import_module_list); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (module->module_type == Wasm_Module_Bytecode) { | ||||||
|  |         sub_module_inst_list = | ||||||
|  |             ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) | ||||||
|  |                 ->sub_module_inst_list; | ||||||
|  |         sub_module_list_node = | ||||||
|  |             bh_list_first_elem(((WASMModule *)module)->import_module_list); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     while (sub_module_list_node) { | ||||||
|  |         WASMSubModInstNode *sub_module_inst_list_node = NULL; | ||||||
|  |         WASMModuleCommon *sub_module = sub_module_list_node->module; | ||||||
|  |         WASMModuleInstanceCommon *sub_module_inst = NULL; | ||||||
|  |         sub_module_inst = wasm_runtime_instantiate_internal( | ||||||
|  |             sub_module, NULL, NULL, stack_size, heap_size, error_buf, | ||||||
|  |             error_buf_size); | ||||||
|  |         if (!sub_module_inst) { | ||||||
|  |             LOG_DEBUG("instantiate %s failed", | ||||||
|  |                       sub_module_list_node->module_name); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode), | ||||||
|  |                                                   error_buf, error_buf_size); | ||||||
|  |         if (!sub_module_inst_list_node) { | ||||||
|  |             LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d", | ||||||
|  |                       sizeof(WASMSubModInstNode)); | ||||||
|  |             if (sub_module_inst) | ||||||
|  |                 wasm_runtime_deinstantiate_internal(sub_module_inst, false); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         sub_module_inst_list_node->module_inst = | ||||||
|  |             (WASMModuleInstance *)sub_module_inst; | ||||||
|  |         sub_module_inst_list_node->module_name = | ||||||
|  |             sub_module_list_node->module_name; | ||||||
|  |         bh_list_status ret = | ||||||
|  |             bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); | ||||||
|  |         bh_assert(BH_LIST_SUCCESS == ret); | ||||||
|  |         (void)ret; | ||||||
|  |         sub_module_list_node = bh_list_elem_next(sub_module_list_node); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst) | ||||||
|  | { | ||||||
|  |     bh_list *list = NULL; | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (module_inst->module_type == Wasm_Module_AoT) { | ||||||
|  |         list = ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) | ||||||
|  |                    ->sub_module_inst_list; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (module_inst->module_type == Wasm_Module_Bytecode) { | ||||||
|  |         list = | ||||||
|  |             ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) | ||||||
|  |                 ->sub_module_inst_list; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     WASMSubModInstNode *node = bh_list_first_elem(list); | ||||||
|  |     while (node) { | ||||||
|  |         WASMSubModInstNode *next_node = bh_list_elem_next(node); | ||||||
|  |         bh_list_remove(list, node); | ||||||
|  |         wasm_runtime_deinstantiate_internal( | ||||||
|  |             (WASMModuleInstanceCommon *)node->module_inst, false); | ||||||
|  |         wasm_runtime_free(node); | ||||||
|  |         node = next_node; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | #endif /* end of WASM_ENABLE_MULTI_MODULE */ | ||||||
| #if WASM_ENABLE_MODULE_INST_CONTEXT != 0 | #if WASM_ENABLE_MODULE_INST_CONTEXT != 0 | ||||||
| void * | void * | ||||||
| wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, | wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, | ||||||
|  |  | ||||||
|  | @ -788,6 +788,9 @@ wasm_runtime_register_module_internal(const char *module_name, | ||||||
| void | void | ||||||
| wasm_runtime_unregister_module(const WASMModuleCommon *module); | wasm_runtime_unregister_module(const WASMModuleCommon *module); | ||||||
| 
 | 
 | ||||||
|  | WASMModuleCommon * | ||||||
|  | wasm_runtime_find_module_registered(const char *module_name); | ||||||
|  | 
 | ||||||
| bool | bool | ||||||
| wasm_runtime_add_loading_module(const char *module_name, char *error_buf, | wasm_runtime_add_loading_module(const char *module_name, char *error_buf, | ||||||
|                                 uint32 error_buf_size); |                                 uint32 error_buf_size); | ||||||
|  | @ -800,6 +803,35 @@ wasm_runtime_is_loading_module(const char *module_name); | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| wasm_runtime_destroy_loading_module_list(); | wasm_runtime_destroy_loading_module_list(); | ||||||
|  | 
 | ||||||
|  | WASMModuleCommon * | ||||||
|  | wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module, | ||||||
|  |                                const char *sub_module_name); | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module, | ||||||
|  |                                  const char *sub_module_name, | ||||||
|  |                                  WASMModuleCommon *sub_module); | ||||||
|  | 
 | ||||||
|  | WASMModuleCommon * | ||||||
|  | wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module, | ||||||
|  |                                   const char *sub_module_name, char *error_buf, | ||||||
|  |                                   uint32 error_buf_size); | ||||||
|  | 
 | ||||||
|  | bool | ||||||
|  | wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, | ||||||
|  |                                     WASMModuleInstanceCommon *module_inst, | ||||||
|  |                                     uint32 stack_size, uint32 heap_size, | ||||||
|  |                                     char *error_buf, uint32 error_buf_size); | ||||||
|  | void | ||||||
|  | wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  | WASMExport * | ||||||
|  | loader_find_export(const WASMModuleCommon *module, const char *module_name, | ||||||
|  |                    const char *field_name, uint8 export_kind, char *error_buf, | ||||||
|  |                    uint32 error_buf_size); | ||||||
| #endif /* WASM_ENALBE_MULTI_MODULE */ | #endif /* WASM_ENALBE_MULTI_MODULE */ | ||||||
| 
 | 
 | ||||||
| bool | bool | ||||||
|  |  | ||||||
|  | @ -311,7 +311,7 @@ wasm_runtime_is_xip_file(const uint8_t *buf, uint32_t size); | ||||||
| /**
 | /**
 | ||||||
|  * Callback to load a module file into a buffer in multi-module feature |  * Callback to load a module file into a buffer in multi-module feature | ||||||
|  */ |  */ | ||||||
| typedef bool (*module_reader)(const char *module_name, | typedef bool (*module_reader)(package_type_t module_type,const char *module_name, | ||||||
|                               uint8_t **p_buffer, uint32_t *p_size); |                               uint8_t **p_buffer, uint32_t *p_size); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -694,34 +694,10 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name, | ||||||
|                         const char *field_name, uint8 export_kind, |                         const char *field_name, uint8 export_kind, | ||||||
|                         char *error_buf, uint32 error_buf_size) |                         char *error_buf, uint32 error_buf_size) | ||||||
| { | { | ||||||
|     WASMExport *export; |     WASMExport *export = | ||||||
|     uint32 i; |         loader_find_export((WASMModuleCommon *)module, module_name, field_name, | ||||||
| 
 |                            export_kind, error_buf, error_buf_size); | ||||||
|     for (i = 0, export = module->exports; i < module->export_count; |     ; | ||||||
|          ++i, ++export) { |  | ||||||
|         /**
 |  | ||||||
|          * need to consider a scenario that different kinds of exports |  | ||||||
|          * may have the same name, like |  | ||||||
|          * (table (export "m1" "exported") 10 funcref) |  | ||||||
|          * (memory (export "m1" "exported") 10) |  | ||||||
|          **/ |  | ||||||
|         if (export->kind == export_kind && !strcmp(field_name, export->name)) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (i == module->export_count) { |  | ||||||
|         LOG_DEBUG("can not find an export %d named %s in the module %s", |  | ||||||
|                   export_kind, field_name, module_name); |  | ||||||
|         set_error_buf(error_buf, error_buf_size, |  | ||||||
|                       "unknown import or incompatible import type"); |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     (void)module_name; |  | ||||||
| 
 |  | ||||||
|     /* since there is a validation in load_export_section(), it is for sure
 |  | ||||||
|      * export->index is valid*/ |  | ||||||
|     return export; |     return export; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | @ -912,152 +888,6 @@ wasm_loader_resolve_global(const char *module_name, const char *global_name, | ||||||
|     return global; |     return global; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static WASMModule * |  | ||||||
| search_sub_module(const WASMModule *parent_module, const char *sub_module_name) |  | ||||||
| { |  | ||||||
|     WASMRegisteredModule *node = |  | ||||||
|         bh_list_first_elem(parent_module->import_module_list); |  | ||||||
|     while (node && strcmp(sub_module_name, node->module_name)) { |  | ||||||
|         node = bh_list_elem_next(node); |  | ||||||
|     } |  | ||||||
|     return node ? (WASMModule *)node->module : NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool |  | ||||||
| register_sub_module(const WASMModule *parent_module, |  | ||||||
|                     const char *sub_module_name, WASMModule *sub_module) |  | ||||||
| { |  | ||||||
|     /* register sub_module into its parent sub module list */ |  | ||||||
|     WASMRegisteredModule *node = NULL; |  | ||||||
|     bh_list_status ret; |  | ||||||
| 
 |  | ||||||
|     if (search_sub_module(parent_module, sub_module_name)) { |  | ||||||
|         LOG_DEBUG("%s has been registered in its parent", sub_module_name); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0); |  | ||||||
|     if (!node) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     node->module_name = sub_module_name; |  | ||||||
|     node->module = (WASMModuleCommon *)sub_module; |  | ||||||
|     ret = bh_list_insert(parent_module->import_module_list, node); |  | ||||||
|     bh_assert(BH_LIST_SUCCESS == ret); |  | ||||||
|     (void)ret; |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static WASMModule * |  | ||||||
| load_depended_module(const WASMModule *parent_module, |  | ||||||
|                      const char *sub_module_name, char *error_buf, |  | ||||||
|                      uint32 error_buf_size) |  | ||||||
| { |  | ||||||
|     WASMModule *sub_module = NULL; |  | ||||||
|     bool ret = false; |  | ||||||
|     uint8 *buffer = NULL; |  | ||||||
|     uint32 buffer_size = 0; |  | ||||||
|     const module_reader reader = wasm_runtime_get_module_reader(); |  | ||||||
|     const module_destroyer destroyer = wasm_runtime_get_module_destroyer(); |  | ||||||
| 
 |  | ||||||
|     /* check the registered module list of the parent */ |  | ||||||
|     sub_module = search_sub_module(parent_module, sub_module_name); |  | ||||||
|     if (sub_module) { |  | ||||||
|         LOG_DEBUG("%s has been loaded before", sub_module_name); |  | ||||||
|         return sub_module; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* check the global registered module list */ |  | ||||||
|     sub_module = |  | ||||||
|         (WASMModule *)wasm_runtime_find_module_registered(sub_module_name); |  | ||||||
|     if (sub_module) { |  | ||||||
|         LOG_DEBUG("%s has been loaded", sub_module_name); |  | ||||||
|         goto register_sub_module; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     LOG_VERBOSE("loading %s", sub_module_name); |  | ||||||
| 
 |  | ||||||
|     if (!reader) { |  | ||||||
|         set_error_buf_v(error_buf, error_buf_size, |  | ||||||
|                         "no sub module reader to load %s", sub_module_name); |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* start to maintain a loading module list */ |  | ||||||
|     ret = wasm_runtime_is_loading_module(sub_module_name); |  | ||||||
|     if (ret) { |  | ||||||
|         set_error_buf_v(error_buf, error_buf_size, |  | ||||||
|                         "found circular dependency on %s", sub_module_name); |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ret = wasm_runtime_add_loading_module(sub_module_name, error_buf, |  | ||||||
|                                           error_buf_size); |  | ||||||
|     if (!ret) { |  | ||||||
|         LOG_DEBUG("can not add %s into loading module list\n", sub_module_name); |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ret = reader(sub_module_name, &buffer, &buffer_size); |  | ||||||
|     if (!ret) { |  | ||||||
|         LOG_DEBUG("read the file of %s failed", sub_module_name); |  | ||||||
|         set_error_buf_v(error_buf, error_buf_size, "unknown import", |  | ||||||
|                         sub_module_name); |  | ||||||
|         goto delete_loading_module; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     sub_module = |  | ||||||
|         wasm_loader_load(buffer, buffer_size, false, error_buf, error_buf_size); |  | ||||||
|     if (!sub_module) { |  | ||||||
|         LOG_DEBUG("error: can not load the sub_module %s", sub_module_name); |  | ||||||
|         /* others will be destroyed in runtime_destroy() */ |  | ||||||
|         goto destroy_file_buffer; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     wasm_runtime_delete_loading_module(sub_module_name); |  | ||||||
| 
 |  | ||||||
|     /* register on a global list */ |  | ||||||
|     ret = wasm_runtime_register_module_internal( |  | ||||||
|         sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size, |  | ||||||
|         error_buf, error_buf_size); |  | ||||||
|     if (!ret) { |  | ||||||
|         LOG_DEBUG("error: can not register module %s globally\n", |  | ||||||
|                   sub_module_name); |  | ||||||
|         /* others will be unloaded in runtime_destroy() */ |  | ||||||
|         goto unload_module; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* register into its parent list */ |  | ||||||
| register_sub_module: |  | ||||||
|     ret = register_sub_module(parent_module, sub_module_name, sub_module); |  | ||||||
|     if (!ret) { |  | ||||||
|         set_error_buf_v(error_buf, error_buf_size, |  | ||||||
|                         "failed to register sub module %s", sub_module_name); |  | ||||||
|         /* since it is in the global module list, no need to
 |  | ||||||
|          * unload the module. the runtime_destroy() will do it |  | ||||||
|          */ |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return sub_module; |  | ||||||
| 
 |  | ||||||
| unload_module: |  | ||||||
|     wasm_loader_unload(sub_module); |  | ||||||
| 
 |  | ||||||
| destroy_file_buffer: |  | ||||||
|     if (destroyer) { |  | ||||||
|         destroyer(buffer, buffer_size); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         LOG_WARNING("need to release the reading buffer of %s manually", |  | ||||||
|                     sub_module_name); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| delete_loading_module: |  | ||||||
|     wasm_runtime_delete_loading_module(sub_module_name); |  | ||||||
|     return NULL; |  | ||||||
| } |  | ||||||
| #endif /* end of WASM_ENABLE_MULTI_MODULE */ | #endif /* end of WASM_ENABLE_MULTI_MODULE */ | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
|  | @ -1104,8 +934,9 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     else { |     else { | ||||||
|         if (!wasm_runtime_is_built_in_module(sub_module_name)) { |         if (!wasm_runtime_is_built_in_module(sub_module_name)) { | ||||||
|             sub_module = load_depended_module(parent_module, sub_module_name, |             sub_module = (WASMModule *)wasm_runtime_load_depended_module( | ||||||
|                                               error_buf, error_buf_size); |                 (WASMModuleCommon *)parent_module, sub_module_name, error_buf, | ||||||
|  |                 error_buf_size); | ||||||
|             if (!sub_module) { |             if (!sub_module) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  | @ -1193,8 +1024,9 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, | ||||||
| 
 | 
 | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     if (!wasm_runtime_is_built_in_module(sub_module_name)) { |     if (!wasm_runtime_is_built_in_module(sub_module_name)) { | ||||||
|         sub_module = load_depended_module(parent_module, sub_module_name, |         sub_module = (WASMModule *)wasm_runtime_load_depended_module( | ||||||
|                                           error_buf, error_buf_size); |             (WASMModuleCommon *)parent_module, sub_module_name, error_buf, | ||||||
|  |             error_buf_size); | ||||||
|         if (!sub_module) { |         if (!sub_module) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  | @ -1327,8 +1159,9 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, | ||||||
| 
 | 
 | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     if (!wasm_runtime_is_built_in_module(sub_module_name)) { |     if (!wasm_runtime_is_built_in_module(sub_module_name)) { | ||||||
|         sub_module = load_depended_module(parent_module, sub_module_name, |         sub_module = (WASMModule *)wasm_runtime_load_depended_module( | ||||||
|                                           error_buf, error_buf_size); |             (WASMModuleCommon *)parent_module, sub_module_name, error_buf, | ||||||
|  |             error_buf_size); | ||||||
|         if (!sub_module) { |         if (!sub_module) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  | @ -1427,8 +1260,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     if (!global->is_linked |     if (!global->is_linked | ||||||
|         && !wasm_runtime_is_built_in_module(sub_module_name)) { |         && !wasm_runtime_is_built_in_module(sub_module_name)) { | ||||||
|         sub_module = load_depended_module(parent_module, sub_module_name, |         sub_module = (WASMModule *)wasm_runtime_load_depended_module( | ||||||
|                                           error_buf, error_buf_size); |             (WASMModuleCommon *)parent_module, sub_module_name, error_buf, | ||||||
|  |             error_buf_size); | ||||||
|         if (!sub_module) { |         if (!sub_module) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -51,11 +51,15 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| WASMModule * | WASMModule * | ||||||
| wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size) | wasm_load(uint8 *buf, uint32 size, | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |           bool main_module, | ||||||
|  | #endif | ||||||
|  |           char *error_buf, uint32 error_buf_size) | ||||||
| { | { | ||||||
|     return wasm_loader_load(buf, size, |     return wasm_loader_load(buf, size, | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|                             true, |                             main_module, | ||||||
| #endif | #endif | ||||||
|                             error_buf, error_buf_size); |                             error_buf, error_buf_size); | ||||||
| } | } | ||||||
|  | @ -1265,78 +1269,6 @@ execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 |  | ||||||
| static bool |  | ||||||
| sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, |  | ||||||
|                        uint32 stack_size, uint32 heap_size, char *error_buf, |  | ||||||
|                        uint32 error_buf_size) |  | ||||||
| { |  | ||||||
|     bh_list *sub_module_inst_list = module_inst->e->sub_module_inst_list; |  | ||||||
|     WASMRegisteredModule *sub_module_list_node = |  | ||||||
|         bh_list_first_elem(module->import_module_list); |  | ||||||
| 
 |  | ||||||
|     while (sub_module_list_node) { |  | ||||||
|         WASMSubModInstNode *sub_module_inst_list_node = NULL; |  | ||||||
|         WASMModule *sub_module = (WASMModule *)sub_module_list_node->module; |  | ||||||
|         WASMModuleInstance *sub_module_inst = NULL; |  | ||||||
| 
 |  | ||||||
|         sub_module_inst = |  | ||||||
|             wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size, |  | ||||||
|                              error_buf, error_buf_size); |  | ||||||
|         if (!sub_module_inst) { |  | ||||||
|             LOG_DEBUG("instantiate %s failed", |  | ||||||
|                       sub_module_list_node->module_name); |  | ||||||
|             goto failed; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         sub_module_inst_list_node = runtime_malloc(sizeof(WASMSubModInstNode), |  | ||||||
|                                                    error_buf, error_buf_size); |  | ||||||
|         if (!sub_module_inst_list_node) { |  | ||||||
|             LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d", |  | ||||||
|                       sizeof(WASMSubModInstNode)); |  | ||||||
|             goto failed; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         sub_module_inst_list_node->module_inst = sub_module_inst; |  | ||||||
|         sub_module_inst_list_node->module_name = |  | ||||||
|             sub_module_list_node->module_name; |  | ||||||
|         bh_list_status ret = |  | ||||||
|             bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); |  | ||||||
|         bh_assert(BH_LIST_SUCCESS == ret); |  | ||||||
|         (void)ret; |  | ||||||
| 
 |  | ||||||
|         sub_module_list_node = bh_list_elem_next(sub_module_list_node); |  | ||||||
| 
 |  | ||||||
|         continue; |  | ||||||
|     failed: |  | ||||||
|         if (sub_module_inst_list_node) { |  | ||||||
|             bh_list_remove(sub_module_inst_list, sub_module_inst_list_node); |  | ||||||
|             wasm_runtime_free(sub_module_inst_list_node); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (sub_module_inst) |  | ||||||
|             wasm_deinstantiate(sub_module_inst, false); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| sub_module_deinstantiate(WASMModuleInstance *module_inst) |  | ||||||
| { |  | ||||||
|     bh_list *list = module_inst->e->sub_module_inst_list; |  | ||||||
|     WASMSubModInstNode *node = bh_list_first_elem(list); |  | ||||||
|     while (node) { |  | ||||||
|         WASMSubModInstNode *next_node = bh_list_elem_next(node); |  | ||||||
|         bh_list_remove(list, node); |  | ||||||
|         wasm_deinstantiate(node->module_inst, false); |  | ||||||
|         wasm_runtime_free(node); |  | ||||||
|         node = next_node; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| static bool | static bool | ||||||
| check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, | check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, | ||||||
|                     uint32 error_buf_size) |                     uint32 error_buf_size) | ||||||
|  | @ -1713,8 +1645,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     module_inst->e->sub_module_inst_list = |     module_inst->e->sub_module_inst_list = | ||||||
|         &module_inst->e->sub_module_inst_list_head; |         &module_inst->e->sub_module_inst_list_head; | ||||||
|     ret = sub_module_instantiate(module, module_inst, stack_size, heap_size, |     ret = wasm_runtime_sub_module_instantiate( | ||||||
|                                  error_buf, error_buf_size); |         (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, | ||||||
|  |         stack_size, heap_size, error_buf, error_buf_size); | ||||||
|     if (!ret) { |     if (!ret) { | ||||||
|         LOG_DEBUG("build a sub module list failed"); |         LOG_DEBUG("build a sub module list failed"); | ||||||
|         goto fail; |         goto fail; | ||||||
|  | @ -2197,7 +2130,8 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     sub_module_deinstantiate(module_inst); |     wasm_runtime_sub_module_deinstantiate( | ||||||
|  |         (WASMModuleInstanceCommon *)module_inst); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     if (module_inst->memory_count > 0) |     if (module_inst->memory_count > 0) | ||||||
|  |  | ||||||
|  | @ -396,7 +396,11 @@ wasm_get_func_code_end(WASMFunctionInstance *func) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| WASMModule * | WASMModule * | ||||||
| wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size); | wasm_load(uint8 *buf, uint32 size, | ||||||
|  | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|  |           bool main_module, | ||||||
|  | #endif | ||||||
|  |           char *error_buf, uint32 error_buf_size); | ||||||
| 
 | 
 | ||||||
| WASMModule * | WASMModule * | ||||||
| wasm_load_from_sections(WASMSection *section_list, char *error_buf, | wasm_load_from_sections(WASMSection *section_list, char *error_buf, | ||||||
|  |  | ||||||
|  | @ -420,19 +420,28 @@ handle_module_path(const char *module_path) | ||||||
| static char *module_search_path = "."; | static char *module_search_path = "."; | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
| module_reader_callback(const char *module_name, uint8 **p_buffer, | module_reader_callback(package_type_t module_type, const char *module_name, | ||||||
|                        uint32 *p_size) |                        uint8 **p_buffer, uint32 *p_size) | ||||||
| { | { | ||||||
|     const char *format = "%s/%s.wasm"; |     char *file_format; | ||||||
|  | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (module_type == Wasm_Module_Bytecode) | ||||||
|  |         file_format = ".wasm"; | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (module_type == Wasm_Module_AoT) | ||||||
|  |         file_format = ".aot"; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  |     const char *format = "%s/%s%s"; | ||||||
|     int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) |     int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) | ||||||
|              + strlen(".wasm") + 1; |              + strlen(file_format) + 1; | ||||||
|     char *wasm_file_name = BH_MALLOC(sz); |     char *wasm_file_name = BH_MALLOC(sz); | ||||||
|     if (!wasm_file_name) { |     if (!wasm_file_name) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 |     snprintf(wasm_file_name, sz, format, module_search_path, module_name, | ||||||
|     snprintf(wasm_file_name, sz, format, module_search_path, module_name); |              file_format); | ||||||
| 
 |  | ||||||
|     *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); |     *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); | ||||||
| 
 | 
 | ||||||
|     wasm_runtime_free(wasm_file_name); |     wasm_runtime_free(wasm_file_name); | ||||||
|  |  | ||||||
|  | @ -204,20 +204,29 @@ handle_module_path(const char *module_path) | ||||||
| 
 | 
 | ||||||
| static char *module_search_path = "."; | static char *module_search_path = "."; | ||||||
| static bool | static bool | ||||||
| module_reader_callback(const char *module_name, uint8 **p_buffer, | module_reader_callback(package_type_t module_type, const char *module_name, | ||||||
|                        uint32 *p_size) |                        uint8 **p_buffer, uint32 *p_size) | ||||||
| { | { | ||||||
|     const char *format = "%s/%s.wasm"; |     char *file_format; | ||||||
|     uint32 sz = (uint32)(strlen(module_search_path) + strlen("/") | #if WASM_ENABLE_INTERP != 0 | ||||||
|                          + strlen(module_name) + strlen(".wasm") + 1); |     if (module_type == Wasm_Module_Bytecode) | ||||||
|  |         file_format = ".wasm"; | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (module_type == Wasm_Module_AoT) | ||||||
|  |         file_format = ".aot"; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  |     const char *format = "%s/%s%s"; | ||||||
|  |     int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) | ||||||
|  |              + strlen(file_format) + 1; | ||||||
|     char *wasm_file_name = BH_MALLOC(sz); |     char *wasm_file_name = BH_MALLOC(sz); | ||||||
|     if (!wasm_file_name) { |     if (!wasm_file_name) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 |     snprintf(wasm_file_name, sz, format, module_search_path, module_name, | ||||||
|     snprintf(wasm_file_name, sz, format, module_search_path, module_name); |              file_format); | ||||||
| 
 |     *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); | ||||||
|     *p_buffer = (uint8 *)bh_read_file_to_buffer(wasm_file_name, p_size); |  | ||||||
| 
 | 
 | ||||||
|     wasm_runtime_free(wasm_file_name); |     wasm_runtime_free(wasm_file_name); | ||||||
|     return *p_buffer != NULL; |     return *p_buffer != NULL; | ||||||
|  |  | ||||||
|  | @ -43,8 +43,12 @@ if (NOT CMAKE_BUILD_TYPE) | ||||||
| endif () | endif () | ||||||
| 
 | 
 | ||||||
| set(WAMR_BUILD_INTERP 1) | set(WAMR_BUILD_INTERP 1) | ||||||
|  | if (NOT DEFINED WAMR_BUILD_AOT) | ||||||
|   set(WAMR_BUILD_AOT 0) |   set(WAMR_BUILD_AOT 0) | ||||||
|  | endif () | ||||||
|  | if (NOT DEFINED WAMR_BUILD_JIT) | ||||||
|   set(WAMR_BUILD_JIT 0) |   set(WAMR_BUILD_JIT 0) | ||||||
|  | endif () | ||||||
| set(WAMR_BUILD_LIBC_BUILTIN 1) | set(WAMR_BUILD_LIBC_BUILTIN 1) | ||||||
| set(WAMR_BUILD_LIBC_WASI 1) | set(WAMR_BUILD_LIBC_WASI 1) | ||||||
| set(WAMR_BUILD_MULTI_MODULE 1) | set(WAMR_BUILD_MULTI_MODULE 1) | ||||||
|  | @ -144,6 +148,43 @@ ExternalProject_Add(WASM_MODULE | ||||||
|                        ./mE.wasm ${CMAKE_BINARY_DIR} |                        ./mE.wasm ${CMAKE_BINARY_DIR} | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | ################ WASM MODULES TO AOT | ||||||
|  | if (WAMR_BUILD_AOT EQUAL 1) | ||||||
|  |   set(WAMR_COMPILER_DIR ${CMAKE_CURRENT_LIST_DIR}/../../wamr-compiler/build) | ||||||
|  |   message(CHECK_START "Detecting WAMR_COMPILER at ${WAMR_COMPILER_DIR}") | ||||||
|  |   find_file(WAMR_COMPILER | ||||||
|  |     wamrc | ||||||
|  |     PATHS "${CMAKE_CURRENT_LIST_DIR}/../../wamr-compiler/build" | ||||||
|  |     NO_DEFAULT_PATH | ||||||
|  |     NO_CMAKE_FIND_ROOT_PATH | ||||||
|  |   ) | ||||||
|  |   if(WAMR_COMPILER) | ||||||
|  |     message(CHECK_PASS "found") | ||||||
|  |   else() | ||||||
|  |     message(CHECK_FAIL "not found") | ||||||
|  |   endif() | ||||||
|  |   if((NOT EXISTS ${WAMR_COMPILER}) ) | ||||||
|  |     message(FATAL_ERROR "Please build wamrc under the path=${WAMR_ROOT_DIR}/wamr-compiler/ ") | ||||||
|  |   else() | ||||||
|  |     message(STATUS "WAMR_COMPILER is ${WAMR_COMPILER}") | ||||||
|  |   endif() | ||||||
|  | 
 | ||||||
|  |   add_custom_target( | ||||||
|  |     wasm_to_aot | ||||||
|  |     ALL | ||||||
|  |     DEPENDS | ||||||
|  |     WASM_MODULE ${WAMR_COMPILER} | ||||||
|  |     COMMAND | ||||||
|  |     ${WAMR_COMPILER} -o mA.aot ./mA.wasm | ||||||
|  |     COMMAND | ||||||
|  |     ${WAMR_COMPILER} -o mB.aot ./mB.wasm | ||||||
|  |     COMMAND | ||||||
|  |     ${WAMR_COMPILER} -o mC.aot ./mC.wasm | ||||||
|  |     WORKING_DIRECTORY | ||||||
|  |     ${CMAKE_BINARY_DIR} | ||||||
|  |   ) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| ################ NATIVE | ################ NATIVE | ||||||
| include_directories(${CMAKE_CURRENT_LIST_DIR}/src) | include_directories(${CMAKE_CURRENT_LIST_DIR}/src) | ||||||
| include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) | include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								samples/multi-module/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								samples/multi-module/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | # WAMR MULTI-MODUEL SAMPLE | ||||||
|  | **WAMR supports *multi-module* in both *interpreter* mode and *aot* mode.** | ||||||
|  | 
 | ||||||
|  | Multi-modules will determine the running mode based on the type of the main module. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ``` shell | ||||||
|  | $ mkdir build | ||||||
|  | $ cd build | ||||||
|  | $ cmake .. | ||||||
|  | $ make | ||||||
|  | $ # It will build multi-module runtime and  | ||||||
|  | $ # wasm file under the ./build . | ||||||
|  | $ # If you have built wamrc, | ||||||
|  | $ # aot file will also genrate. | ||||||
|  | $ ./multi-module mC.wasm | ||||||
|  | $ ... | ||||||
|  | $ ./multi-module mC.aot | ||||||
|  | $ ... | ||||||
|  | 
 | ||||||
|  | @ -1,59 +1,63 @@ | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 |  | ||||||
| #include "bh_read_file.h" | #include "bh_read_file.h" | ||||||
| #include "platform_common.h" | #include "platform_common.h" | ||||||
| #include "wasm_export.h" | #include "wasm_export.h" | ||||||
| 
 | 
 | ||||||
| static char * | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
| build_module_path(const char *module_name) | static char *module_search_path = "."; | ||||||
|  | static bool | ||||||
|  | module_reader_callback(package_type_t module_type, const char *module_name, | ||||||
|  |                        uint8 **p_buffer, uint32 *p_size) | ||||||
| { | { | ||||||
|     const char *module_search_path = "."; |     char *file_format; | ||||||
|     const char *format = "%s/%s.wasm"; | #if WASM_ENABLE_INTERP != 0 | ||||||
|  |     if (module_type == Wasm_Module_Bytecode) | ||||||
|  |         file_format = ".wasm"; | ||||||
|  | #endif | ||||||
|  | #if WASM_ENABLE_AOT != 0 | ||||||
|  |     if (module_type == Wasm_Module_AoT) | ||||||
|  |         file_format = ".aot"; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  |     const char *format = "%s/%s%s"; | ||||||
|     int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) |     int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) | ||||||
|              + strlen(".wasm") + 1; |              + strlen(file_format) + 1; | ||||||
|     char *wasm_file_name = BH_MALLOC(sz); |     char *wasm_file_name = BH_MALLOC(sz); | ||||||
|     if (!wasm_file_name) { |     if (!wasm_file_name) { | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     snprintf(wasm_file_name, sz, format, module_search_path, module_name); |  | ||||||
|     return wasm_file_name; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool |  | ||||||
| module_reader_cb(const char *module_name, uint8 **p_buffer, uint32 *p_size) |  | ||||||
| { |  | ||||||
|     char *wasm_file_path = build_module_path(module_name); |  | ||||||
|     if (!wasm_file_path) { |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |     snprintf(wasm_file_name, sz, format, module_search_path, module_name, | ||||||
|  |              file_format); | ||||||
|  |     *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); | ||||||
| 
 | 
 | ||||||
|     printf("- bh_read_file_to_buffer %s\n", wasm_file_path); |     wasm_runtime_free(wasm_file_name); | ||||||
|     *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_path, p_size); |  | ||||||
|     BH_FREE(wasm_file_path); |  | ||||||
|     return *p_buffer != NULL; |     return *p_buffer != NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| module_destroyer_cb(uint8 *buffer, uint32 size) | moudle_destroyer(uint8 *buffer, uint32 size) | ||||||
| { | { | ||||||
|     printf("- release the read file buffer\n"); |  | ||||||
|     if (!buffer) { |     if (!buffer) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     BH_FREE(buffer); |     wasm_runtime_free(buffer); | ||||||
|     buffer = NULL; |     buffer = NULL; | ||||||
| } | } | ||||||
|  | #endif /* WASM_ENABLE_MULTI_MODULE */ | ||||||
| 
 | 
 | ||||||
| /* 10M */ | /* 10M */ | ||||||
| static char sandbox_memory_space[10 * 1024 * 1024] = { 0 }; | static char sandbox_memory_space[10 * 1024 * 1024] = { 0 }; | ||||||
| int | int | ||||||
| main() | main(int argc, char *argv[]) | ||||||
| { | { | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|  |     if (argc != 2) { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     char *wasm_file = argv[1]; | ||||||
|     /* 16K */ |     /* 16K */ | ||||||
|     const uint32 stack_size = 16 * 1024; |     const uint32 stack_size = 16 * 1024; | ||||||
|     const uint32 heap_size = 16 * 1024; |     const uint32 heap_size = 16 * 1024; | ||||||
|  | @ -84,16 +88,16 @@ main() | ||||||
| #if WASM_ENABLE_MULTI_MODULE != 0 | #if WASM_ENABLE_MULTI_MODULE != 0 | ||||||
|     printf("- wasm_runtime_set_module_reader\n"); |     printf("- wasm_runtime_set_module_reader\n"); | ||||||
|     /* set module reader and destroyer */ |     /* set module reader and destroyer */ | ||||||
|     wasm_runtime_set_module_reader(module_reader_cb, module_destroyer_cb); |     wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     /* load WASM byte buffer from WASM bin file */ |     /* load WASM byte buffer from WASM bin file */ | ||||||
|     if (!module_reader_cb("mC", &file_buf, &file_buf_size)) { |     if (!(file_buf = | ||||||
|  |               (uint8 *)bh_read_file_to_buffer(wasm_file, &file_buf_size))) | ||||||
|         goto RELEASE_RUNTIME; |         goto RELEASE_RUNTIME; | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* load mC and let WAMR load mA and mB */ |     /* load mC and let WAMR load mA and mB */ | ||||||
|     printf("- wasm_runtime_load\n"); |     printf("- wasm_runtime_load\n"); | ||||||
|  | 
 | ||||||
|     if (!(module = wasm_runtime_load(file_buf, file_buf_size, error_buf, |     if (!(module = wasm_runtime_load(file_buf, file_buf_size, error_buf, | ||||||
|                                      sizeof(error_buf)))) { |                                      sizeof(error_buf)))) { | ||||||
|         printf("%s\n", error_buf); |         printf("%s\n", error_buf); | ||||||
|  | @ -158,7 +162,7 @@ UNLOAD_MODULE: | ||||||
|     printf("- wasm_runtime_unload\n"); |     printf("- wasm_runtime_unload\n"); | ||||||
|     wasm_runtime_unload(module); |     wasm_runtime_unload(module); | ||||||
| RELEASE_BINARY: | RELEASE_BINARY: | ||||||
|     module_destroyer_cb(file_buf, file_buf_size); |     moudle_destroyer(file_buf, file_buf_size); | ||||||
| RELEASE_RUNTIME: | RELEASE_RUNTIME: | ||||||
|     printf("- wasm_runtime_destroy\n"); |     printf("- wasm_runtime_destroy\n"); | ||||||
|     wasm_runtime_destroy(); |     wasm_runtime_destroy(); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,174 @@ | ||||||
|  | diff --git a/test/core/linking.wast b/test/core/linking.wast
 | ||||||
|  | index d0bfb5f..6617945 100644
 | ||||||
|  | --- a/test/core/linking.wast
 | ||||||
|  | +++ b/test/core/linking.wast
 | ||||||
|  | @@ -35,7 +35,7 @@
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  ;; Globals | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (module $Mg | ||||||
|  |    (global $glob (export "glob") i32 (i32.const 42)) | ||||||
|  |    (func (export "get") (result i32) (global.get $glob)) | ||||||
|  | @@ -63,7 +63,7 @@
 | ||||||
|  |    (export "Mg.get_mut" (func $get_mut)) | ||||||
|  |    (export "Mg.set_mut" (func $set_mut)) | ||||||
|  |  ) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (get $Mg "glob") (i32.const 42)) | ||||||
|  |  (assert_return (get $Ng "Mg.glob") (i32.const 42)) | ||||||
|  | @@ -84,7 +84,7 @@
 | ||||||
|  |  (assert_return (invoke $Ng "Mg.get_mut") (i32.const 241)) | ||||||
|  |  ;) | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (assert_unlinkable | ||||||
|  |    (module (import "Mg" "mut_glob" (global i32))) | ||||||
|  |    "incompatible import type" | ||||||
|  | @@ -166,7 +166,7 @@
 | ||||||
|  |      (call_indirect (type 1) (local.get 0)) | ||||||
|  |    ) | ||||||
|  |  ) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4)) | ||||||
|  |  (assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4)) | ||||||
|  | @@ -191,7 +191,7 @@
 | ||||||
|  |  (assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4)) | ||||||
|  |  (assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch") | ||||||
|  |  ;) | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (module $Ot | ||||||
|  |    (type (func (result i32))) | ||||||
|  |   | ||||||
|  | @@ -204,7 +204,7 @@
 | ||||||
|  |      (call_indirect (type 0) (local.get 0)) | ||||||
|  |    ) | ||||||
|  |  ) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4)) | ||||||
|  |  (assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4)) | ||||||
|  | @@ -231,7 +231,7 @@
 | ||||||
|  |   | ||||||
|  |  (assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element") | ||||||
|  |  ;) | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (module | ||||||
|  |    (table (import "Mt" "tab") 0 funcref) | ||||||
|  |    (elem (i32.const 9) $f) | ||||||
|  | @@ -266,7 +266,7 @@
 | ||||||
|  |    "unknown import" | ||||||
|  |  ) | ||||||
|  |  (assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element") | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  ;; Unlike in the v1 spec, active element segments stored before an | ||||||
|  |  ;; out-of-bounds access persist after the instantiation failure. | ||||||
|  |  (; | ||||||
|  | @@ -297,7 +297,7 @@
 | ||||||
|  |  (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) | ||||||
|  |  ;) | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (module $Mtable_ex | ||||||
|  |    (table $t1 (export "t-func") 1 funcref) | ||||||
|  |    (table $t2 (export "t-extern") 1 externref) | ||||||
|  | @@ -308,7 +308,7 @@
 | ||||||
|  |    (table (import "Mtable_ex" "t-func") 1 funcref) | ||||||
|  |    (table (import "Mtable_ex" "t-extern") 1 externref) | ||||||
|  |  ) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_unlinkable | ||||||
|  |    (module (table (import "Mtable_ex" "t-func") 1 externref)) | ||||||
|  | @@ -322,7 +322,7 @@
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  ;; Memories | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (module $Mm | ||||||
|  |    (memory (export "mem") 1 5) | ||||||
|  |    (data (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") | ||||||
|  | @@ -357,14 +357,14 @@
 | ||||||
|  |      (i32.load8_u (local.get 0)) | ||||||
|  |    ) | ||||||
|  |  ) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) | ||||||
|  |  (assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) | ||||||
|  |  (assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) | ||||||
|  |  (assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) | ||||||
|  |  ;) | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (module | ||||||
|  |    (memory (import "Mm" "mem") 0) | ||||||
|  |    (data (i32.const 0xffff) "a") | ||||||
|  | @@ -385,7 +385,7 @@
 | ||||||
|  |      (memory.grow (local.get 0)) | ||||||
|  |    ) | ||||||
|  |  ) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) | ||||||
|  |  (assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) | ||||||
|  | @@ -396,7 +396,7 @@
 | ||||||
|  |  (assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) | ||||||
|  |  (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) | ||||||
|  |  ;) | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (assert_unlinkable | ||||||
|  |    (module | ||||||
|  |      (func $host (import "spectest" "print")) | ||||||
|  | @@ -419,11 +419,12 @@
 | ||||||
|  |    ) | ||||||
|  |    "out of bounds memory access" | ||||||
|  |  ) | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) | ||||||
|  |  (assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) | ||||||
|  |  ;) | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  (assert_trap | ||||||
|  |    (module | ||||||
|  |      (memory (import "Mm" "mem") 1) | ||||||
|  | @@ -434,10 +435,11 @@
 | ||||||
|  |    ) | ||||||
|  |    "out of bounds table access" | ||||||
|  |  ) | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) | ||||||
|  |  ;) | ||||||
|  | -
 | ||||||
|  | +(;
 | ||||||
|  |  ;; Store is modified if the start function traps. | ||||||
|  |  (module $Ms | ||||||
|  |    (type $t (func (result i32))) | ||||||
|  | @@ -451,7 +453,7 @@
 | ||||||
|  |    ) | ||||||
|  |  ) | ||||||
|  |  (register "Ms" $Ms) | ||||||
|  | -
 | ||||||
|  | +;)
 | ||||||
|  |  (; | ||||||
|  |  (assert_trap | ||||||
|  |    (module | ||||||
|  | @ -1299,6 +1299,16 @@ if __name__ == "__main__": | ||||||
| 
 | 
 | ||||||
|                     # add new_module copied from the old into temp_file_repo[] |                     # add new_module copied from the old into temp_file_repo[] | ||||||
|                     temp_file_repo.append(new_module) |                     temp_file_repo.append(new_module) | ||||||
|  | 
 | ||||||
|  |                     if test_aot: | ||||||
|  |                         new_module_aot = os.path.join(tempfile.gettempdir(), name_new + ".aot") | ||||||
|  |                         r = compile_wasm_to_aot(new_module, new_module_aot, True, opts, r) | ||||||
|  |                         try: | ||||||
|  |                             assert_prompt(r, ['Compile success'], opts.start_timeout, True) | ||||||
|  |                         except: | ||||||
|  |                             raise Exception("compile wasm to aot failed") | ||||||
|  |                         # add aot module into temp_file_repo[] | ||||||
|  |                         temp_file_repo.append(new_module_aot) | ||||||
|                 else: |                 else: | ||||||
|                     # there is no name defined in register cmd |                     # there is no name defined in register cmd | ||||||
|                     raise Exception("can not find module name from the register") |                     raise Exception("can not find module name from the register") | ||||||
|  | @ -1341,3 +1351,4 @@ if __name__ == "__main__": | ||||||
|             log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile])) |             log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile])) | ||||||
| 
 | 
 | ||||||
|         sys.exit(ret_code) |         sys.exit(ret_code) | ||||||
|  |          | ||||||
|  | @ -333,6 +333,9 @@ function spec_test() | ||||||
|     if [[ ${ENABLE_SIMD} == 1 ]]; then |     if [[ ${ENABLE_SIMD} == 1 ]]; then | ||||||
|         git apply ../../spec-test-script/simd_ignore_cases.patch |         git apply ../../spec-test-script/simd_ignore_cases.patch | ||||||
|     fi |     fi | ||||||
|  |     if [[ ${ENABLE_MULTI_MODULE} == 1 && $1 == 'aot'  ]]; then | ||||||
|  |         git apply ../../spec-test-script/muti_module_aot_ignore_cases.patch | ||||||
|  |     fi | ||||||
| 
 | 
 | ||||||
|     # udpate thread cases |     # udpate thread cases | ||||||
|     if [ ${ENABLE_MULTI_THREAD} == 1 ]; then |     if [ ${ENABLE_MULTI_THREAD} == 1 ]; then | ||||||
|  | @ -424,7 +427,7 @@ function spec_test() | ||||||
| 
 | 
 | ||||||
|     # multi-module only enable in interp mode |     # multi-module only enable in interp mode | ||||||
|     if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then |     if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then | ||||||
|         if [[ $1 == 'classic-interp' || $1 == 'fast-interp' ]]; then |         if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then | ||||||
|             ARGS_FOR_SPEC_TEST+="-M " |             ARGS_FOR_SPEC_TEST+="-M " | ||||||
|         fi |         fi | ||||||
|     fi |     fi | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 dongsheng28849455
						dongsheng28849455